Author: pjd
Date: Mon Jun 11 19:57:31 2012
New Revision: 236913
URL: http://svn.freebsd.org/changeset/base/236913

Log:
  Introduce closefp() function that we will be able to use to eliminate
  code duplication in kern_close() and do_dup().
  
  This is committed separately from the actual removal of the duplicated
  code, as the combined diff was very hard to read.
  
  Discussed with:       kib
  Tested by:    pho
  MFC after:    1 month

Modified:
  head/sys/kern/kern_descrip.c

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c        Mon Jun 11 19:53:41 2012        
(r236912)
+++ head/sys/kern/kern_descrip.c        Mon Jun 11 19:57:31 2012        
(r236913)
@@ -114,6 +114,8 @@ static uma_zone_t file_zone;
 #define DUP_FIXED      0x1     /* Force fixed allocation */
 #define DUP_FCNTL      0x2     /* fcntl()-style errors */
 
+static int     closefp(struct filedesc *fdp, int fd, struct file *fp,
+    struct thread *td);
 static int do_dup(struct thread *td, int flags, int old, int new,
     register_t *retval);
 static int     fd_first_free(struct filedesc *, int, int);
@@ -1157,6 +1159,59 @@ fgetown(sigiop)
 }
 
 /*
+ * Function drops the filedesc lock on return.
+ */
+static int
+closefp(struct filedesc *fdp, int fd, struct file *fp, struct thread *td)
+{
+       struct file *fp_object;
+       int error, holdleaders;
+
+       FILEDESC_XLOCK_ASSERT(fdp);
+
+       if (td->td_proc->p_fdtol != NULL) {
+               /*
+                * Ask fdfree() to sleep to ensure that all relevant
+                * process leaders can be traversed in closef().
+                */
+               fdp->fd_holdleaderscount++;
+               holdleaders = 1;
+       } else {
+               holdleaders = 0;
+       }
+
+       /*
+        * We now hold the fp reference that used to be owned by the
+        * descriptor array.  We have to unlock the FILEDESC *AFTER*
+        * knote_fdclose to prevent a race of the fd getting opened, a knote
+        * added, and deleteing a knote for the new fd.
+        */
+       knote_fdclose(td, fd);
+
+       /*
+        * When we're closing an fd with a capability, we need to notify
+        * mqueue if the underlying object is of type mqueue.
+        */
+       (void)cap_funwrap(fp, 0, &fp_object);
+       if (fp_object->f_type == DTYPE_MQUEUE)
+               mq_fdclose(td, fd, fp_object);
+       FILEDESC_XUNLOCK(fdp);
+
+       error = closef(fp, td);
+       if (holdleaders) {
+               FILEDESC_XLOCK(fdp);
+               fdp->fd_holdleaderscount--;
+               if (fdp->fd_holdleaderscount == 0 &&
+                   fdp->fd_holdleaderswakeup != 0) {
+                       fdp->fd_holdleaderswakeup = 0;
+                       wakeup(&fdp->fd_holdleaderscount);
+               }
+               FILEDESC_XUNLOCK(fdp);
+       }
+       return (error);
+}
+
+/*
  * Close a file descriptor.
  */
 #ifndef _SYS_SYSPROTO_H_
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to