Diff below shuffles the code used by sys_setsid() and sys_setpgid()
into two functions instead of one.

It is extracted from guenther@'s proctree diff and I'd like to get
it in to reduce the locking diff.

ok?

Index: kern/kern_proc.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_proc.c,v
retrieving revision 1.80
diff -u -p -r1.80 kern_proc.c
--- kern/kern_proc.c    10 Feb 2018 10:32:51 -0000      1.80
+++ kern/kern_proc.c    19 Feb 2018 14:46:06 -0000
@@ -73,6 +73,9 @@ struct pool ucred_pool;
 struct pool pgrp_pool;
 struct pool session_pool;
 
+void   pgdelete(struct pgrp *);
+void   fixjobc(struct process *, struct pgrp *, int);
+
 static void orphanpg(struct pgrp *);
 #ifdef DEBUG
 void pgrpdump(void);
@@ -222,67 +225,54 @@ zombiefind(pid_t pid)
 }
 
 /*
- * Move p to a new or existing process group (and session)
- * Caller provides a pre-allocated pgrp and session that should
- * be freed if they are not used.
- * XXX need proctree lock
+ * Move process to a new process group.  If a session is provided
+ * then it's a new session to contain this process group; otherwise
+ * the process is staying within its existing session.
  */
-int
-enterpgrp(struct process *pr, pid_t pgid, struct pgrp *newpgrp,
-    struct session *newsess)
+void
+enternewpgrp(struct process *pr, struct pgrp *pgrp, struct session *newsess)
 {
-       struct pgrp *pgrp = pgfind(pgid);
-
 #ifdef DIAGNOSTIC
-       if (pgrp != NULL && newsess)    /* firewalls */
-               panic("enterpgrp: setsid into non-empty pgrp");
        if (SESS_LEADER(pr))
-               panic("enterpgrp: session leader attempted setpgrp");
+               panic("%s: session leader attempted setpgrp", __func__);
 #endif
-       if (pgrp == NULL) {
+
+       if (newsess != NULL) {
                /*
-                * new process group
+                * New session.  Initialize it completely
                 */
+               timeout_set(&newsess->s_verauthto, zapverauth, newsess);
+               newsess->s_leader = pr;
+               newsess->s_count = 1;
+               newsess->s_ttyvp = NULL;
+               newsess->s_ttyp = NULL;
+               memcpy(newsess->s_login, pr->ps_session->s_login,
+                   sizeof(newsess->s_login));
+               atomic_clearbits_int(&pr->ps_flags, PS_CONTROLT);
+               pgrp->pg_session = newsess;
 #ifdef DIAGNOSTIC
-               if (pr->ps_pid != pgid)
-                       panic("enterpgrp: new pgrp and pid != pgid");
-#endif
-
-               pgrp = newpgrp;
-               if (newsess) {
-                       /*
-                        * new session
-                        */
-                       newsess->s_leader = pr;
-                       newsess->s_count = 1;
-                       newsess->s_ttyvp = NULL;
-                       newsess->s_ttyp = NULL;
-                       memcpy(newsess->s_login, pr->ps_session->s_login,
-                           sizeof(newsess->s_login));
-                       atomic_clearbits_int(&pr->ps_flags, PS_CONTROLT);
-                       pgrp->pg_session = newsess;
-#ifdef DIAGNOSTIC
-                       if (pr != curproc->p_p)
-                               panic("enterpgrp: mksession but not curproc");
+               if (pr != curproc->p_p)
+                       panic("%s: mksession but not curproc", __func__);
 #endif
-               } else {
-                       pgrp->pg_session = pr->ps_session;
-                       pgrp->pg_session->s_count++;
-               }
-               pgrp->pg_id = pgid;
-               LIST_INIT(&pgrp->pg_members);
-               LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
-               pgrp->pg_jobc = 0;
-       } else if (pgrp == pr->ps_pgrp) {
-               if (newsess)
-                       pool_put(&session_pool, newsess);
-               pool_put(&pgrp_pool, newpgrp);
-               return (0);
        } else {
-               if (newsess)
-                       pool_put(&session_pool, newsess);
-               pool_put(&pgrp_pool, newpgrp);
+               pgrp->pg_session = pr->ps_session;
+               pgrp->pg_session->s_count++;
        }
+       pgrp->pg_id = pr->ps_pid;
+       LIST_INIT(&pgrp->pg_members);
+       LIST_INSERT_HEAD(PGRPHASH(pr->ps_pid), pgrp, pg_hash);
+       pgrp->pg_jobc = 0;
+
+       enterthispgrp(pr, pgrp);
+}
+
+/*
+ * move process to an existing process group
+ */
+void
+enterthispgrp(struct process *pr, struct pgrp *pgrp)
+{
+       struct pgrp *savepgrp = pr->ps_pgrp;
 
        /*
         * Adjust eligibility of affected pgrps to participate in job control.
@@ -290,14 +280,13 @@ enterpgrp(struct process *pr, pid_t pgid
         * could reach 0 spuriously during the first call.
         */
        fixjobc(pr, pgrp, 1);
-       fixjobc(pr, pr->ps_pgrp, 0);
+       fixjobc(pr, savepgrp, 0);
 
        LIST_REMOVE(pr, ps_pglist);
-       if (LIST_EMPTY(&pr->ps_pgrp->pg_members))
-               pgdelete(pr->ps_pgrp);
        pr->ps_pgrp = pgrp;
        LIST_INSERT_HEAD(&pgrp->pg_members, pr, ps_pglist);
-       return (0);
+       if (LIST_EMPTY(&savepgrp->pg_members))
+               pgdelete(savepgrp);
 }
 
 /*
Index: kern/kern_prot.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_prot.c,v
retrieving revision 1.72
diff -u -p -r1.72 kern_prot.c
--- kern/kern_prot.c    19 Feb 2018 08:59:52 -0000      1.72
+++ kern/kern_prot.c    19 Feb 2018 14:47:03 -0000
@@ -222,15 +222,14 @@ sys_setsid(struct proc *p, void *v, regi
        pid_t pid = pr->ps_pid;
 
        newsess = pool_get(&session_pool, PR_WAITOK);
-       timeout_set(&newsess->s_verauthto, zapverauth, newsess);
        newpgrp = pool_get(&pgrp_pool, PR_WAITOK);
 
-       if (pr->ps_pgid == pid || pgfind(pid)) {
+       if (pr->ps_pgid == pid || pgfind(pid) != NULL) {
                pool_put(&pgrp_pool, newpgrp);
                pool_put(&session_pool, newsess);
                return (EPERM);
        } else {
-               (void) enterpgrp(pr, pid, newpgrp, newsess);
+               enternewpgrp(pr, newpgrp, newsess);
                *retval = pid;
                return (0);
        }
@@ -291,15 +290,26 @@ sys_setpgid(struct proc *curp, void *v, 
        }
        if (pgid == 0)
                pgid = targpr->ps_pid;
-       else if (pgid != targpr->ps_pid)
-               if ((pgrp = pgfind(pgid)) == 0 ||
-                   pgrp->pg_session != curpr->ps_session) {
+
+       error = 0;
+       if ((pgrp = pgfind(pgid)) == NULL) {
+               /* can only create a new process group with pgid == pid */
+               if (pgid != targpr->ps_pid)
                        error = EPERM;
-                       goto out;
+               else {
+                       enternewpgrp(targpr, newpgrp, NULL);
+                       newpgrp = NULL;
                }
-       return (enterpgrp(targpr, pgid, newpgrp, NULL));
-out:
-       pool_put(&pgrp_pool, newpgrp);
+       } else if (pgrp != targpr->ps_pgrp) {           /* anything to do? */
+               if (pgid != targpr->ps_pid &&
+                   pgrp->pg_session != curpr->ps_session)
+                       error = EPERM;
+               else
+                       enterthispgrp(targpr, pgrp);
+       }
+ out:
+       if (newpgrp != NULL)
+               pool_put(&pgrp_pool, newpgrp);
        return (error);
 }
 
Index: sys/proc.h
===================================================================
RCS file: /cvs/src/sys/sys/proc.h,v
retrieving revision 1.245
diff -u -p -r1.245 proc.h
--- sys/proc.h  10 Feb 2018 10:32:51 -0000      1.245
+++ sys/proc.h  19 Feb 2018 14:44:55 -0000
@@ -496,13 +496,12 @@ void      proc_printit(struct proc *p, const 
     int (*pr)(const char *, ...));
 
 int    chgproccnt(uid_t uid, int diff);
-int    enterpgrp(struct process *, pid_t, struct pgrp *, struct session *);
-void   fixjobc(struct process *, struct pgrp *, int);
+void   enternewpgrp(struct process *, struct pgrp *, struct session *);
+void   enterthispgrp(struct process *, struct pgrp *);
 int    inferior(struct process *, struct process *);
 void   leavepgrp(struct process *);
 void   killjobc(struct process *);
 void   preempt(void);
-void   pgdelete(struct pgrp *);
 void   procinit(void);
 void   resetpriority(struct proc *);
 void   setrunnable(struct proc *);

Reply via email to