svn commit: r225940 - in head/sys: kern sys

Edward Tomasz Napierala trasz at FreeBSD.org
Mon Oct 3 16:23:21 UTC 2011


Author: trasz
Date: Mon Oct  3 16:23:20 2011
New Revision: 225940
URL: http://svn.freebsd.org/changeset/base/225940

Log:
  Fix another bug introduced in r225641, which caused rctl to access certain
  fields in 'struct proc' before they got initialized in do_fork().
  
  MFC after:	3 days

Modified:
  head/sys/kern/kern_fork.c
  head/sys/kern/kern_racct.c
  head/sys/kern/kern_rctl.c
  head/sys/sys/racct.h

Modified: head/sys/kern/kern_fork.c
==============================================================================
--- head/sys/kern/kern_fork.c	Mon Oct  3 16:02:55 2011	(r225939)
+++ head/sys/kern/kern_fork.c	Mon Oct  3 16:23:20 2011	(r225940)
@@ -939,6 +939,7 @@ fork1(struct thread *td, int flags, int 
 		if (flags & RFPROCDESC)
 			procdesc_finit(newproc->p_procdesc, fp_procdesc);
 #endif
+		racct_proc_fork_done(newproc);
 		return (0);
 	}
 

Modified: head/sys/kern/kern_racct.c
==============================================================================
--- head/sys/kern/kern_racct.c	Mon Oct  3 16:02:55 2011	(r225939)
+++ head/sys/kern/kern_racct.c	Mon Oct  3 16:23:20 2011	(r225940)
@@ -585,6 +585,24 @@ out:
 	return (error);
 }
 
+/*
+ * Called at the end of fork1(), to handle rules that require the process
+ * to be fully initialized.
+ */
+void
+racct_proc_fork_done(struct proc *child)
+{
+
+#ifdef RCTL
+	PROC_LOCK(child);
+	mtx_lock(&racct_lock);
+	rctl_enforce(child, RACCT_NPROC, 0);
+	rctl_enforce(child, RACCT_NTHR, 0);
+	mtx_unlock(&racct_lock);
+	PROC_UNLOCK(child);
+#endif
+}
+
 void
 racct_proc_exit(struct proc *p)
 {
@@ -810,6 +828,11 @@ racct_proc_fork(struct proc *parent, str
 }
 
 void
+racct_proc_fork_done(struct proc *child)
+{
+}
+
+void
 racct_proc_exit(struct proc *p)
 {
 }

Modified: head/sys/kern/kern_rctl.c
==============================================================================
--- head/sys/kern/kern_rctl.c	Mon Oct  3 16:02:55 2011	(r225939)
+++ head/sys/kern/kern_rctl.c	Mon Oct  3 16:23:20 2011	(r225940)
@@ -312,6 +312,16 @@ rctl_enforce(struct proc *p, int resourc
 			if (link->rrl_exceeded != 0)
 				continue;
 
+			/*
+			 * If the process state is not fully initialized yet,
+			 * we can't access most of the required fields, e.g.
+			 * p->p_comm.  This happens when called from fork1().
+			 * Ignore this rule for now; it will be processed just
+			 * after fork, when called from racct_proc_fork_done().
+			 */
+			if (p->p_state != PRS_NORMAL)
+				continue;
+
 			if (!ppsratecheck(&lasttime, &curtime, 10))
 				continue;
 
@@ -335,6 +345,9 @@ rctl_enforce(struct proc *p, int resourc
 			if (link->rrl_exceeded != 0)
 				continue;
 
+			if (p->p_state != PRS_NORMAL)
+				continue;
+	
 			buf = malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT);
 			if (buf == NULL) {
 				printf("rctl_enforce: out of memory\n");
@@ -357,23 +370,15 @@ rctl_enforce(struct proc *p, int resourc
 			if (link->rrl_exceeded != 0)
 				continue;
 
+			if (p->p_state != PRS_NORMAL)
+				continue;
+
 			KASSERT(rule->rr_action > 0 &&
 			    rule->rr_action <= RCTL_ACTION_SIGNAL_MAX,
 			    ("rctl_enforce: unknown action %d",
 			     rule->rr_action));
 
 			/*
-			 * We're supposed to send a signal, but the process
-			 * is not fully initialized yet, probably because we
-			 * got called from fork1().  For now just deny the
-			 * allocation instead.
-			 */
-			if (p->p_state != PRS_NORMAL) {
-				should_deny = 1;
-				continue;
-			}
-
-			/*
 			 * We're using the fact that RCTL_ACTION_SIG* values
 			 * are equal to their counterparts from sys/signal.h.
 			 */

Modified: head/sys/sys/racct.h
==============================================================================
--- head/sys/sys/racct.h	Mon Oct  3 16:02:55 2011	(r225939)
+++ head/sys/sys/racct.h	Mon Oct  3 16:23:20 2011	(r225940)
@@ -137,6 +137,7 @@ void	racct_create(struct racct **racctp)
 void	racct_destroy(struct racct **racctp);
 
 int	racct_proc_fork(struct proc *parent, struct proc *child);
+void	racct_proc_fork_done(struct proc *child);
 void	racct_proc_exit(struct proc *p);
 
 void	racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred,


More information about the svn-src-head mailing list