svn commit: r274482 - head/sys/kern

Mateusz Guzik mjg at FreeBSD.org
Thu Nov 13 21:15:10 UTC 2014


Author: mjg
Date: Thu Nov 13 21:15:09 2014
New Revision: 274482
URL: https://svnweb.freebsd.org/changeset/base/274482

Log:
  filedesc: fixup fdinit to lock fdp and preapare files conditinally
  
  Not all consumers providing fdp to copy from want files.
  
  Perhaps these functions should be reorganized to better express the outcome.
  
  This fixes up panics after r273895 .
  
  Reported by:	markj

Modified:
  head/sys/kern/init_main.c
  head/sys/kern/kern_descrip.c
  head/sys/kern/kern_fork.c

Modified: head/sys/kern/init_main.c
==============================================================================
--- head/sys/kern/init_main.c	Thu Nov 13 20:09:47 2014	(r274481)
+++ head/sys/kern/init_main.c	Thu Nov 13 21:15:09 2014	(r274482)
@@ -527,7 +527,7 @@ proc0_init(void *dummy __unused)
 	siginit(&proc0);
 
 	/* Create the file descriptor table. */
-	p->p_fd = fdinit(NULL);
+	p->p_fd = fdinit(NULL, false);
 	p->p_fdtol = NULL;
 
 	/* Create the limits structures. */

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c	Thu Nov 13 20:09:47 2014	(r274481)
+++ head/sys/kern/kern_descrip.c	Thu Nov 13 21:15:09 2014	(r274482)
@@ -1797,7 +1797,7 @@ finstall(struct thread *td, struct file 
  * If fdp is not NULL, return with it shared locked.
  */
 struct filedesc *
-fdinit(struct filedesc *fdp)
+fdinit(struct filedesc *fdp, bool prepfiles)
 {
 	struct filedesc0 *newfdp0;
 	struct filedesc *newfdp;
@@ -1818,7 +1818,7 @@ fdinit(struct filedesc *fdp)
 	if (fdp == NULL)
 		return (newfdp);
 
-	if (fdp->fd_lastfile >= newfdp->fd_nfiles)
+	if (prepfiles && fdp->fd_lastfile >= newfdp->fd_nfiles)
 		fdgrowtable(newfdp, fdp->fd_lastfile + 1);
 
 	FILEDESC_SLOCK(fdp);
@@ -1832,10 +1832,14 @@ fdinit(struct filedesc *fdp)
 	if (newfdp->fd_jdir)
 		VREF(newfdp->fd_jdir);
 
-	while (fdp->fd_lastfile >= newfdp->fd_nfiles) {
+	if (!prepfiles) {
 		FILEDESC_SUNLOCK(fdp);
-		fdgrowtable(newfdp, fdp->fd_lastfile + 1);
-		FILEDESC_SLOCK(fdp);
+	} else {
+		while (fdp->fd_lastfile >= newfdp->fd_nfiles) {
+			FILEDESC_SUNLOCK(fdp);
+			fdgrowtable(newfdp, fdp->fd_lastfile + 1);
+			FILEDESC_SLOCK(fdp);
+		}
 	}
 
 	return (newfdp);
@@ -1914,7 +1918,7 @@ fdcopy(struct filedesc *fdp)
 
 	MPASS(fdp != NULL);
 
-	newfdp = fdinit(fdp);
+	newfdp = fdinit(fdp, true);
 	/* copy all passable descriptors (i.e. not kqueue) */
 	newfdp->fd_freefile = -1;
 	for (i = 0; i <= fdp->fd_lastfile; ++i) {

Modified: head/sys/kern/kern_fork.c
==============================================================================
--- head/sys/kern/kern_fork.c	Thu Nov 13 20:09:47 2014	(r274481)
+++ head/sys/kern/kern_fork.c	Thu Nov 13 21:15:09 2014	(r274482)
@@ -333,7 +333,7 @@ fork_norfproc(struct thread *td, int fla
 	 */
 	if (flags & RFCFDG) {
 		struct filedesc *fdtmp;
-		fdtmp = fdinit(td->td_proc->p_fd);
+		fdtmp = fdinit(td->td_proc->p_fd, false);
 		fdescfree(td);
 		p1->p_fd = fdtmp;
 	}
@@ -418,7 +418,7 @@ do_fork(struct thread *td, int flags, st
 	 * Copy filedesc.
 	 */
 	if (flags & RFCFDG) {
-		fd = fdinit(p1->p_fd);
+		fd = fdinit(p1->p_fd, false);
 		fdtol = NULL;
 	} else if (flags & RFFDG) {
 		fd = fdcopy(p1->p_fd);


More information about the svn-src-all mailing list