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
This commit is contained in:
Pawel Jakub Dawidek 2012-06-11 19:57:31 +00:00
parent 129c87eb7d
commit 642db963ab
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=236913

View File

@ -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);
@ -1156,6 +1158,59 @@ fgetown(sigiop)
return (pgid);
}
/*
* 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.
*/