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

Jonathan Anderson jonathan at FreeBSD.org
Thu Jun 30 15:22:49 UTC 2011


Author: jonathan
Date: Thu Jun 30 15:22:49 2011
New Revision: 223694
URL: http://svn.freebsd.org/changeset/base/223694

Log:
  When Capsicum starts creating capabilities to wrap existing file
  descriptors, we will want to allocate a new descriptor without installing
  it in the FD array.
  
  Split falloc() into falloc_noinstall() and finstall(), and rewrite
  falloc() to call them with appropriate atomicity.
  
  Approved by: mentor (rwatson), re (bz)

Modified:
  head/sys/kern/kern_descrip.c
  head/sys/sys/filedesc.h

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c	Thu Jun 30 14:10:49 2011	(r223693)
+++ head/sys/kern/kern_descrip.c	Thu Jun 30 15:22:49 2011	(r223694)
@@ -1561,54 +1561,85 @@ fdavail(struct thread *td, int n)
 int
 falloc(struct thread *td, struct file **resultfp, int *resultfd, int flags)
 {
-	struct proc *p = td->td_proc;
 	struct file *fp;
-	int error, i;
+	int error, fd;
+
+	error = falloc_noinstall(td, &fp);
+	if (error)
+		return (error);		/* no reference held on error */
+
+	error = finstall(td, fp, &fd, flags);
+	if (error) {
+		fdrop(fp, td);		/* one reference (fp only) */
+		return (error);
+	}
+
+	if (resultfp != NULL)
+		*resultfp = fp;		/* copy out result */
+	else
+		fdrop(fp, td);		/* release local reference */
+
+	if (resultfd != NULL)
+		*resultfd = fd;
+
+	return (0);
+}
+
+/*
+ * Create a new open file structure without allocating a file descriptor.
+ */
+int
+falloc_noinstall(struct thread *td, struct file **resultfp)
+{
+	struct file *fp;
 	int maxuserfiles = maxfiles - (maxfiles / 20);
 	static struct timeval lastfail;
 	static int curfail;
 
-	fp = uma_zalloc(file_zone, M_WAITOK | M_ZERO);
+	KASSERT(resultfp != NULL, ("%s: resultfp == NULL", __func__));
+
 	if ((openfiles >= maxuserfiles &&
 	    priv_check(td, PRIV_MAXFILES) != 0) ||
 	    openfiles >= maxfiles) {
 		if (ppsratecheck(&lastfail, &curfail, 1)) {
-			printf("kern.maxfiles limit exceeded by uid %i, please see tuning(7).\n",
-				td->td_ucred->cr_ruid);
+			printf("kern.maxfiles limit exceeded by uid %i, "
+			    "please see tuning(7).\n", td->td_ucred->cr_ruid);
 		}
-		uma_zfree(file_zone, fp);
 		return (ENFILE);
 	}
 	atomic_add_int(&openfiles, 1);
-
-	/*
-	 * If the process has file descriptor zero open, add the new file
-	 * descriptor to the list of open files at that point, otherwise
-	 * put it at the front of the list of open files.
-	 */
+	fp = uma_zalloc(file_zone, M_WAITOK | M_ZERO);
 	refcount_init(&fp->f_count, 1);
-	if (resultfp)
-		fhold(fp);
 	fp->f_cred = crhold(td->td_ucred);
 	fp->f_ops = &badfileops;
 	fp->f_data = NULL;
 	fp->f_vnode = NULL;
-	FILEDESC_XLOCK(p->p_fd);
-	if ((error = fdalloc(td, 0, &i))) {
-		FILEDESC_XUNLOCK(p->p_fd);
-		fdrop(fp, td);
-		if (resultfp)
-			fdrop(fp, td);
+	*resultfp = fp;
+	return (0);
+}
+
+/*
+ * Install a file in a file descriptor table.
+ */
+int
+finstall(struct thread *td, struct file *fp, int *fd, int flags)
+{
+	struct filedesc *fdp = td->td_proc->p_fd;
+	int error;
+
+	KASSERT(fd != NULL, ("%s: fd == NULL", __func__));
+	KASSERT(fp != NULL, ("%s: fp == NULL", __func__));
+
+	FILEDESC_XLOCK(fdp);
+	if ((error = fdalloc(td, 0, fd))) {
+		FILEDESC_XUNLOCK(fdp);
 		return (error);
 	}
-	p->p_fd->fd_ofiles[i] = fp;
+	fhold(fp);
+	fdp->fd_ofiles[*fd] = fp;
 	if ((flags & O_CLOEXEC) != 0)
-		p->p_fd->fd_ofileflags[i] |= UF_EXCLOSE;
-	FILEDESC_XUNLOCK(p->p_fd);
-	if (resultfp)
-		*resultfp = fp;
-	if (resultfd)
-		*resultfd = i;
+		fdp->fd_ofileflags[*fd] |= UF_EXCLOSE;
+	FILEDESC_XUNLOCK(fdp);
 	return (0);
 }
 

Modified: head/sys/sys/filedesc.h
==============================================================================
--- head/sys/sys/filedesc.h	Thu Jun 30 14:10:49 2011	(r223693)
+++ head/sys/sys/filedesc.h	Thu Jun 30 15:22:49 2011	(r223694)
@@ -113,6 +113,8 @@ int	dupfdopen(struct thread *td, struct 
 	    int mode, int error);
 int	falloc(struct thread *td, struct file **resultfp, int *resultfd,
 	    int flags);
+int	falloc_noinstall(struct thread *td, struct file **resultfp);
+int	finstall(struct thread *td, struct file *fp, int *resultfp, int flags);
 int	fdalloc(struct thread *td, int minfd, int *result);
 int	fdavail(struct thread *td, int n);
 int	fdcheckstd(struct thread *td);


More information about the svn-src-all mailing list