diff options
author | alfred <alfred@FreeBSD.org> | 2002-01-14 00:13:45 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 2002-01-14 00:13:45 +0000 |
commit | 1f82bc18d1d1e906cd9ed68039acb051fa6e11cf (patch) | |
tree | fe7842143c9585ef2ebb793d812ec71cc4488a51 /sys/kern | |
parent | c4988e25d265bba2c63409a8c8b8708c13d8525e (diff) | |
download | FreeBSD-src-1f82bc18d1d1e906cd9ed68039acb051fa6e11cf.zip FreeBSD-src-1f82bc18d1d1e906cd9ed68039acb051fa6e11cf.tar.gz |
Replace ffind_* with fget calls.
Make fget MPsafe.
Make fgetvp and fgetsock use the fget subsystem to reduce code bloat.
Push giant down in fpathconf().
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_descrip.c | 187 | ||||
-rw-r--r-- | sys/kern/kern_event.c | 8 | ||||
-rw-r--r-- | sys/kern/sys_generic.c | 10 | ||||
-rw-r--r-- | sys/kern/vfs_extattr.c | 7 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 7 |
5 files changed, 81 insertions, 138 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 1adb3e3..c47c3c0 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -843,36 +843,31 @@ fpathconf(td, uap) struct vnode *vp; int error; - fp = ffind_hold(td, uap->fd); - if (fp == NULL) - return (EBADF); - mtx_lock(&Giant); if ((error = fget(td, uap->fd, &fp)) != 0) - goto done2; + return (error); switch (fp->f_type) { case DTYPE_PIPE: case DTYPE_SOCKET: if (uap->name != _PC_PIPE_BUF) { - fdrop(fp, td); error = EINVAL; - goto done2; + } else { + td->td_retval[0] = PIPE_BUF; + error = 0; } - td->td_retval[0] = PIPE_BUF; - error = 0; break; case DTYPE_FIFO: case DTYPE_VNODE: vp = (struct vnode *)fp->f_data; + mtx_lock(&Giant); error = VOP_PATHCONF(vp, uap->name, td->td_retval); + mtx_unlock(&Giant); break; default: error = EOPNOTSUPP; break; } fdrop(fp, td); -done2: - mtx_unlock(&Giant); return(error); } @@ -1456,50 +1451,6 @@ closef(fp, td) } /* - * Find the struct file 'fd' in process 'p' and bump it's refcount - * struct file is not locked on return. - */ -struct file * -ffind_hold(td, fd) - struct thread *td; - int fd; -{ - struct file *fp; - - fp = ffind_lock(td, fd); - if (fp != NULL) - FILE_UNLOCK(fp); - return (fp); -} - -/* - * Find the struct file 'fd' in process 'p' and bump it's refcount, - * struct file is locked on return. - */ -struct file * -ffind_lock(td, fd) - struct thread *td; - int fd; -{ - struct filedesc *fdp; - struct file *fp; - - if (td == NULL || (fdp = td->td_proc->p_fd) == NULL) - return (NULL); - FILEDESC_LOCK(fdp); - if (fd < 0 || fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[fd]) == NULL || - fp->f_ops == &badfileops) { - fp = NULL; - } else { - FILE_LOCK(fp); - fhold_locked(fp); - } - FILEDESC_UNLOCK(fdp); - return (fp); -} - -/* * Drop reference on struct file passed in, may call closef if the * reference hits zero. */ @@ -1515,29 +1466,38 @@ fdrop(fp, td) /* * Extract the file pointer associated with the specified descriptor for - * the current user process. If no error occured 0 is returned, *fpp - * will be set to the file pointer, and the file pointer's ref count - * will be bumped. Use fdrop() to drop it. If an error occured the - * non-zero error is returned and *fpp is set to NULL. + * the current user process. + * + * If the descriptor doesn't exist, EBADF is returned. * - * This routine requires Giant for the moment. Once enough of the - * system is converted over to this and other encapsulated APIs we - * will be able to mutex it and call it without Giant. + * If the descriptor exists but doesn't match 'flags' then + * return EBADF for read attempts and EINVAL for write attempts. + * + * If 'hold' is set (non-zero) the file's refcount will be bumped on return. + * It should be droped with fdrop(). + * If it is not set, then the refcount will not be bumped however the + * thread's filedesc struct will be returned locked (for fgetsock). + * + * If an error occured the non-zero error is returned and *fpp is set to NULL. + * Otherwise *fpp is set and zero is returned. */ static __inline int -_fget(struct thread *td, int fd, struct file **fpp, int flags) +_fget(struct thread *td, int fd, struct file **fpp, int flags, int hold) { struct filedesc *fdp; struct file *fp; - GIANT_REQUIRED; - fdp = td->td_proc->p_fd; *fpp = NULL; - if ((u_int)fd >= fdp->fd_nfiles) + if (td == NULL || (fdp = td->td_proc->p_fd) == NULL) return(EBADF); - if ((fp = fdp->fd_ofiles[fd]) == NULL) + FILEDESC_LOCK(fdp); + if (fd < 0 || (u_int)fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[fd]) == NULL || + fp->f_ops == &badfileops) { + FILEDESC_UNLOCK(fdp); return(EBADF); + } /* * Note: FREAD failures returns EBADF to maintain backwards @@ -1545,11 +1505,18 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags) * * Only one flag, or 0, may be specified. */ - if (flags == FREAD && (fp->f_flag & FREAD) == 0) + if (flags == FREAD && (fp->f_flag & FREAD) == 0) { + FILEDESC_UNLOCK(fdp); return(EBADF); - if (flags == FWRITE && (fp->f_flag & FWRITE) == 0) + } + if (flags == FWRITE && (fp->f_flag & FWRITE) == 0) { + FILEDESC_UNLOCK(fdp); return(EINVAL); - ++fp->f_count; + } + if (hold) { + fhold(fp); + FILEDESC_UNLOCK(fdp); + } *fpp = fp; return(0); } @@ -1557,19 +1524,19 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags) int fget(struct thread *td, int fd, struct file **fpp) { - return(_fget(td, fd, fpp, 0)); + return(_fget(td, fd, fpp, 0, 1)); } int fget_read(struct thread *td, int fd, struct file **fpp) { - return(_fget(td, fd, fpp, FREAD)); + return(_fget(td, fd, fpp, FREAD, 1)); } int fget_write(struct thread *td, int fd, struct file **fpp) { - return(_fget(td, fd, fpp, FWRITE)); + return(_fget(td, fd, fpp, FWRITE, 1)); } /* @@ -1583,34 +1550,20 @@ static __inline int _fgetvp(struct thread *td, int fd, struct vnode **vpp, int flags) { - struct filedesc *fdp; struct file *fp; + int error; - GIANT_REQUIRED; - fdp = td->td_proc->p_fd; *vpp = NULL; - if ((u_int)fd >= fdp->fd_nfiles) - return(EBADF); - if ((fp = fdp->fd_ofiles[fd]) == NULL) - return(EBADF); - if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) - return(EINVAL); - if (fp->f_data == NULL) - return(EINVAL); - - /* - * Note: FREAD failures returns EBADF to maintain backwards - * compatibility with what routines returned before. - * - * Only one flag, or 0, may be specified. - */ - if (flags == FREAD && (fp->f_flag & FREAD) == 0) - return(EBADF); - if (flags == FWRITE && (fp->f_flag & FWRITE) == 0) - return(EINVAL); - *vpp = (struct vnode *)fp->f_data; - vref(*vpp); - return(0); + if ((error = _fget(td, fd, &fp, 0, 0)) != 0) + return (error); + if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) { + error = EINVAL; + } else { + *vpp = (struct vnode *)fp->f_data; + vref(*vpp); + } + FILEDESC_UNLOCK(td->td_proc->p_fd); + return (error); } int @@ -1641,29 +1594,24 @@ fgetvp_write(struct thread *td, int fd, struct vnode **vpp) int fgetsock(struct thread *td, int fd, struct socket **spp, u_int *fflagp) { - struct filedesc *fdp; struct file *fp; - struct socket *so; + int error; - GIANT_REQUIRED; - fdp = td->td_proc->p_fd; *spp = NULL; if (fflagp) *fflagp = 0; - if ((u_int)fd >= fdp->fd_nfiles) - return(EBADF); - if ((fp = fdp->fd_ofiles[fd]) == NULL) - return(EBADF); - if (fp->f_type != DTYPE_SOCKET) - return(ENOTSOCK); - if (fp->f_data == NULL) - return(EINVAL); - so = (struct socket *)fp->f_data; - if (fflagp) - *fflagp = fp->f_flag; - soref(so); - *spp = so; - return(0); + if ((error = _fget(td, fd, &fp, 0, 0)) != 0) + return (error); + if (fp->f_type != DTYPE_SOCKET) { + error = ENOTSOCK; + } else { + *spp = (struct socket *)fp->f_data; + if (fflagp) + *fflagp = fp->f_flag; + soref(*spp); + } + FILEDESC_UNLOCK(td->td_proc->p_fd); + return(error); } /* @@ -1737,14 +1685,13 @@ flock(td, uap) struct thread *td; register struct flock_args *uap; { - register struct file *fp; + struct file *fp; struct vnode *vp; struct flock lf; int error; - fp = ffind_hold(td, uap->fd); - if (fp == NULL) - return (EBADF); + if ((error = fget(td, uap->fd, &fp)) != 0) + return (error); if (fp->f_type != DTYPE_VNODE) { fdrop(fp, td); return (EOPNOTSUPP); diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 038b233..bf89043 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -414,10 +414,10 @@ kevent(struct thread *td, struct kevent_args *uap) struct timespec ts; int i, n, nerrors, error; - fp = ffind_hold(td, uap->fd); - if (fp == NULL || fp->f_type != DTYPE_KQUEUE) { - if (fp != NULL) - fdrop(fp, td); + if ((error = fget(td, uap->fd, &fp)) != 0) + return (error); + if (fp->f_type != DTYPE_KQUEUE) { + fdrop(fp, td); return (EBADF); } if (uap->timeout != NULL) { diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index df85cf2..77b843d 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -603,7 +603,7 @@ ioctl(td, uap) struct thread *td; register struct ioctl_args *uap; { - register struct file *fp; + struct file *fp; register struct filedesc *fdp; register u_long com; int error = 0; @@ -616,9 +616,8 @@ ioctl(td, uap) long align; } ubuf; - fp = ffind_hold(td, uap->fd); - if (fp == NULL) - return (EBADF); + if ((error = fget(td, uap->fd, &fp)) != 0) + return (error); if ((fp->f_flag & (FREAD | FWRITE)) == 0) { fdrop(fp, td); return (EBADF); @@ -992,8 +991,7 @@ selscan(td, ibits, obits, nfd) for (fd = i; bits && fd < nfd; fd++, bits >>= 1) { if (!(bits & 1)) continue; - fp = ffind_hold(td, fd); - if (fp == NULL) + if (fget(td, fd, &fp)) return (EBADF); if (fo_poll(fp, flag[msk], fp->f_cred, td)) { obits[msk][(fd)/NFDBITS] |= diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 75ac3d0..539c418 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -1704,15 +1704,14 @@ lseek(td, uap) } */ *uap; { struct ucred *cred = td->td_proc->p_ucred; - register struct file *fp; + struct file *fp; struct vnode *vp; struct vattr vattr; off_t offset; int error, noneg; - fp = ffind_hold(td, uap->fd); - if (fp == NULL) - return (EBADF); + if ((error = fget(td, uap->fd, &fp)) != 0) + return (error); if (fp->f_type != DTYPE_VNODE) { fdrop(fp, td); return (ESPIPE); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 75ac3d0..539c418 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1704,15 +1704,14 @@ lseek(td, uap) } */ *uap; { struct ucred *cred = td->td_proc->p_ucred; - register struct file *fp; + struct file *fp; struct vnode *vp; struct vattr vattr; off_t offset; int error, noneg; - fp = ffind_hold(td, uap->fd); - if (fp == NULL) - return (EBADF); + if ((error = fget(td, uap->fd, &fp)) != 0) + return (error); if (fp->f_type != DTYPE_VNODE) { fdrop(fp, td); return (ESPIPE); |