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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to