summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_descrip.c
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2012-06-11 19:57:31 +0000
committerpjd <pjd@FreeBSD.org>2012-06-11 19:57:31 +0000
commitc8465e01a12c87cc250fef1a3c3e50a9c5f8b8d5 (patch)
tree1ed9cc4422edbc3b03afc2988fdb85c8ef373343 /sys/kern/kern_descrip.c
parentcab8c2dc3aae7f1ca63d0c4fe8b5e0c87d02dad7 (diff)
downloadFreeBSD-src-c8465e01a12c87cc250fef1a3c3e50a9c5f8b8d5.zip
FreeBSD-src-c8465e01a12c87cc250fef1a3c3e50a9c5f8b8d5.tar.gz
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
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r--sys/kern/kern_descrip.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 7c7bc34..2e34e09 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -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_
OpenPOWER on IntegriCloud