[PATCH 1/2] fork: pass arguments to fork1 in a dedicated structure
Mateusz Guzik
mjguzik at gmail.com
Tue Feb 2 04:07:54 UTC 2016
From: Mateusz Guzik <mjg at freebsd.org>
---
sys/compat/cloudabi/cloudabi_proc.c | 7 +++++-
sys/compat/linux/linux_fork.c | 17 ++++++++++----
sys/kern/init_main.c | 6 +++--
sys/kern/kern_fork.c | 46 +++++++++++++++++++++++++------------
sys/kern/kern_kthread.c | 7 ++++--
sys/sys/proc.h | 12 ++++++++--
6 files changed, 68 insertions(+), 27 deletions(-)
diff --git a/sys/compat/cloudabi/cloudabi_proc.c b/sys/compat/cloudabi/cloudabi_proc.c
index d917337..010efca 100644
--- a/sys/compat/cloudabi/cloudabi_proc.c
+++ b/sys/compat/cloudabi/cloudabi_proc.c
@@ -75,12 +75,17 @@ int
cloudabi_sys_proc_fork(struct thread *td,
struct cloudabi_sys_proc_fork_args *uap)
{
+ struct fork_req fr = {};
struct filecaps fcaps = {};
struct proc *p2;
int error, fd;
cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_EVENT);
- error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2, &fd, 0, &fcaps);
+ fr.fr_flags = RFFDG | RFPROC | RFPROCDESC;
+ fr.fr_procp = &p2;
+ fr.fr_pd_fd = &fd;
+ fr.fr_pd_fcaps = &fcaps;
+ error = fork1(td, &fr);
if (error != 0)
return (error);
/* Return the file descriptor to the parent process. */
diff --git a/sys/compat/linux/linux_fork.c b/sys/compat/linux/linux_fork.c
index d0f73ad..4cd521b 100644
--- a/sys/compat/linux/linux_fork.c
+++ b/sys/compat/linux/linux_fork.c
@@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
int
linux_fork(struct thread *td, struct linux_fork_args *args)
{
+ struct fork_req fr = {};
int error;
struct proc *p2;
struct thread *td2;
@@ -73,8 +74,9 @@ linux_fork(struct thread *td, struct linux_fork_args *args)
printf(ARGS(fork, ""));
#endif
- if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2, NULL, 0,
- NULL)) != 0)
+ fr.fr_flags = RFFDG | RFPROC | RFSTOPPED;
+ fr.fr_procp = &p2;
+ if ((error = fork1(td, &fr)) != 0)
return (error);
td2 = FIRST_THREAD_IN_PROC(p2);
@@ -97,6 +99,7 @@ linux_fork(struct thread *td, struct linux_fork_args *args)
int
linux_vfork(struct thread *td, struct linux_vfork_args *args)
{
+ struct fork_req fr = {};
int error;
struct proc *p2;
struct thread *td2;
@@ -106,8 +109,9 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
printf(ARGS(vfork, ""));
#endif
- if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED,
- 0, &p2, NULL, 0, NULL)) != 0)
+ fr.fr_flags = RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED;
+ fr.fr_procp = &p2;
+ if ((error = fork1(td, &fr)) != 0)
return (error);
td2 = FIRST_THREAD_IN_PROC(p2);
@@ -130,6 +134,7 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
static int
linux_clone_proc(struct thread *td, struct linux_clone_args *args)
{
+ struct fork_req fr = {};
int error, ff = RFPROC | RFSTOPPED;
struct proc *p2;
struct thread *td2;
@@ -170,7 +175,9 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args)
if (args->flags & LINUX_CLONE_VFORK)
ff |= RFPPWAIT;
- error = fork1(td, ff, 0, &p2, NULL, 0, NULL);
+ fr.fr_flags = ff;
+ fr.fr_procp = &p2;
+ error = fork1(td, &fr);
if (error)
return (error);
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 8d5580b..a63d4e0 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -828,12 +828,14 @@ start_init(void *dummy)
static void
create_init(const void *udata __unused)
{
+ struct fork_req fr = {};
struct ucred *newcred, *oldcred;
struct thread *td;
int error;
- error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc,
- NULL, 0, NULL);
+ fr.fr_flags = RFFDG | RFPROC | RFSTOPPED;
+ fr.fr_procp = &initproc;
+ error = fork1(&thread0, &fr);
if (error)
panic("cannot fork init: %d\n", error);
KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1"));
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index e7d7276..3b51b7f 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -101,10 +101,13 @@ struct fork_args {
int
sys_fork(struct thread *td, struct fork_args *uap)
{
+ struct fork_req fr = {};
int error;
struct proc *p2;
- error = fork1(td, RFFDG | RFPROC, 0, &p2, NULL, 0, NULL);
+ fr.fr_flags = RFFDG | RFPROC;
+ fr.fr_procp = &p2;
+ error = fork1(td, &fr);
if (error == 0) {
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
@@ -118,16 +121,20 @@ sys_pdfork(td, uap)
struct thread *td;
struct pdfork_args *uap;
{
+ struct fork_req fr = {};
int error, fd;
struct proc *p2;
+ fr.fr_flags = RFFDG | RFPROC | RFPROCDESC;
+ fr.fr_procp = &p2;
+ fr.fr_pd_fd = &fd;
+ fr.fr_pd_flags = uap->flags;
/*
* It is necessary to return fd by reference because 0 is a valid file
* descriptor number, and the child needs to be able to distinguish
* itself from the parent using the return value.
*/
- error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2,
- &fd, uap->flags, NULL);
+ error = fork1(td, &fr);
if (error == 0) {
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
@@ -140,11 +147,13 @@ sys_pdfork(td, uap)
int
sys_vfork(struct thread *td, struct vfork_args *uap)
{
- int error, flags;
+ struct fork_req fr = {};
+ int error;
struct proc *p2;
- flags = RFFDG | RFPROC | RFPPWAIT | RFMEM;
- error = fork1(td, flags, 0, &p2, NULL, 0, NULL);
+ fr.fr_flags = RFFDG | RFPROC | RFPPWAIT | RFMEM;
+ fr.fr_procp = &p2;
+ error = fork1(td, &fr);
if (error == 0) {
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
@@ -155,6 +164,7 @@ sys_vfork(struct thread *td, struct vfork_args *uap)
int
sys_rfork(struct thread *td, struct rfork_args *uap)
{
+ struct fork_req fr = {};
struct proc *p2;
int error;
@@ -163,7 +173,9 @@ sys_rfork(struct thread *td, struct rfork_args *uap)
return (EINVAL);
AUDIT_ARG_FFLAGS(uap->flags);
- error = fork1(td, uap->flags, 0, &p2, NULL, 0, NULL);
+ fr.fr_flags = uap->flags;
+ fr.fr_procp = &p2;
+ error = fork1(td, &fr);
if (error == 0) {
td->td_retval[0] = p2 ? p2->p_pid : 0;
td->td_retval[1] = 0;
@@ -761,8 +773,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
}
int
-fork1(struct thread *td, int flags, int pages, struct proc **procp,
- int *procdescp, int pdflags, struct filecaps *fcaps)
+fork1(struct thread *td, struct fork_req *fr)
{
struct proc *p1, *newproc;
struct thread *td2;
@@ -772,6 +783,10 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
int error, nprocs_new, ok;
static int curfail;
static struct timeval lastfail;
+ int flags, pages;
+
+ flags = fr->fr_flags;
+ pages = fr->fr_pages;
/* Check for the undefined or unimplemented flags. */
if ((flags & ~(RFFLAGS | RFTSIGFLAGS(RFTSIGMASK))) != 0)
@@ -795,7 +810,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
return (EINVAL);
/* Must provide a place to put a procdesc if creating one. */
- if (procdescp == NULL)
+ if (fr->fr_pd_fd == NULL)
return (EINVAL);
}
@@ -806,7 +821,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
* certain parts of a process from itself.
*/
if ((flags & RFPROC) == 0) {
- *procp = NULL;
+ *fr->fr_procp = NULL;
return (fork_norfproc(td, flags));
}
@@ -845,7 +860,8 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
* later.
*/
if (flags & RFPROCDESC) {
- error = falloc_caps(td, &fp_procdesc, procdescp, 0, fcaps);
+ error = falloc_caps(td, &fp_procdesc, fr->fr_pd_fd, 0,
+ fr->fr_pd_fcaps);
if (error != 0)
goto fail2;
}
@@ -933,12 +949,12 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
lim_cur(td, RLIMIT_NPROC));
}
if (ok) {
- do_fork(td, flags, newproc, td2, vm2, pdflags);
+ do_fork(td, flags, newproc, td2, vm2, fr->fr_pd_flags);
/*
* Return child proc pointer to parent.
*/
- *procp = newproc;
+ *fr->fr_procp = newproc;
if (flags & RFPROCDESC) {
procdesc_finit(newproc->p_procdesc, fp_procdesc);
fdrop(fp_procdesc, td);
@@ -962,7 +978,7 @@ fail2:
vmspace_free(vm2);
uma_zfree(proc_zone, newproc);
if ((flags & RFPROCDESC) != 0 && fp_procdesc != NULL) {
- fdclose(td, fp_procdesc, *procdescp);
+ fdclose(td, fp_procdesc, *fr->fr_pd_fd);
fdrop(fp_procdesc, td);
}
atomic_add_int(&nprocs, -1);
diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c
index 2072dc7..970c33f 100644
--- a/sys/kern/kern_kthread.c
+++ b/sys/kern/kern_kthread.c
@@ -80,6 +80,7 @@ int
kproc_create(void (*func)(void *), void *arg,
struct proc **newpp, int flags, int pages, const char *fmt, ...)
{
+ struct fork_req fr = {};
int error;
va_list ap;
struct thread *td;
@@ -88,8 +89,10 @@ kproc_create(void (*func)(void *), void *arg,
if (!proc0.p_stats)
panic("kproc_create called too soon");
- error = fork1(&thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags,
- pages, &p2, NULL, 0, NULL);
+ fr.fr_flags = RFMEM | RFFDG | RFPROC | RFSTOPPED | flags;
+ fr.fr_pages = pages;
+ fr.fr_procp = &p2;
+ error = fork1(&thread0, &fr);
if (error)
return error;
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index f2f4a9d..ac96566 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -907,6 +907,15 @@ struct proc *pfind_locked(pid_t pid);
struct pgrp *pgfind(pid_t); /* Find process group by id. */
struct proc *zpfind(pid_t); /* Find zombie process by id. */
+struct fork_req {
+ int fr_flags;
+ int fr_pages;
+ struct proc **fr_procp;
+ int *fr_pd_fd;
+ int fr_pd_flags;
+ struct filecaps *fr_pd_fcaps;
+};
+
/*
* pget() flags.
*/
@@ -930,8 +939,7 @@ int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp,
int enterthispgrp(struct proc *p, struct pgrp *pgrp);
void faultin(struct proc *p);
void fixjobc(struct proc *p, struct pgrp *pgrp, int entering);
-int fork1(struct thread *, int, int, struct proc **, int *, int,
- struct filecaps *);
+int fork1(struct thread *, struct fork_req *);
void fork_exit(void (*)(void *, struct trapframe *), void *,
struct trapframe *);
void fork_return(struct thread *, struct trapframe *);
--
2.7.0
More information about the freebsd-hackers
mailing list