diff options
author | dillon <dillon@FreeBSD.org> | 2001-11-14 06:30:36 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 2001-11-14 06:30:36 +0000 |
commit | e3b965f7d57557c7273b062793ee6de6ff40223d (patch) | |
tree | dc13d87ccb395b03afaf10cd5a87755eea002ec3 /sys/kern/kern_descrip.c | |
parent | 06b00a671bcb44fa0375ea17871931d7e0b5c5ca (diff) | |
download | FreeBSD-src-e3b965f7d57557c7273b062793ee6de6ff40223d.zip FreeBSD-src-e3b965f7d57557c7273b062793ee6de6ff40223d.tar.gz |
remove holdfp()
Replace uses of holdfp() with fget*() or fgetvp*() calls as appropriate
introduce fget(), fget_read(), fget_write() - these functions will take
a thread and file descriptor and return a file pointer with its ref
count bumped.
introduce fgetvp(), fgetvp_read(), fgetvp_write() - these functions will
take a thread and file descriptor and return a vref()'d vnode.
*_read() requires that the file pointer be FREAD, *_write that it be
FWRITE.
This continues the cleanup of struct filedesc and struct file access
routines which, when are all through with it, will allow us to then
make the API calls MP safe and be able to move Giant down into the fo_*
functions.
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r-- | sys/kern/kern_descrip.c | 164 |
1 files changed, 127 insertions, 37 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index b0f9e08..1d8d038 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -677,20 +677,14 @@ ofstat(td, uap) struct thread *td; register struct ofstat_args *uap; { - register struct filedesc *fdp = td->td_proc->p_fd; - register struct file *fp; + struct file *fp; struct stat ub; struct ostat oub; int error; mtx_lock(&Giant); - - if ((unsigned)uap->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL) { - error = EBADF; + if ((error = fget(td, uap->fd, &fp)) != 0) goto done2; - } - fhold(fp); error = fo_stat(fp, &ub, td); if (error == 0) { cvtstat(&ub, &oub); @@ -719,22 +713,15 @@ struct fstat_args { int fstat(td, uap) struct thread *td; - register struct fstat_args *uap; + struct fstat_args *uap; { - register struct filedesc *fdp; - register struct file *fp; + struct file *fp; struct stat ub; int error; mtx_lock(&Giant); - fdp = td->td_proc->p_fd; - - if ((unsigned)uap->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL) { - error = EBADF; + if ((error = fget(td, uap->fd, &fp)) != 0) goto done2; - } - fhold(fp); error = fo_stat(fp, &ub, td); if (error == 0) error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); @@ -762,21 +749,14 @@ nfstat(td, uap) struct thread *td; register struct nfstat_args *uap; { - register struct filedesc *fdp; - register struct file *fp; + struct file *fp; struct stat ub; struct nstat nub; int error; mtx_lock(&Giant); - - fdp = td->td_proc->p_fd; - if ((unsigned)uap->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL) { - error = EBADF; + if ((error = fget(td, uap->fd, &fp)) != 0) goto done2; - } - fhold(fp); error = fo_stat(fp, &ub, td); if (error == 0) { cvtnstat(&ub, &nub); @@ -806,21 +786,13 @@ fpathconf(td, uap) struct thread *td; register struct fpathconf_args *uap; { - struct filedesc *fdp; struct file *fp; struct vnode *vp; - int error = 0; + int error; mtx_lock(&Giant); - fdp = td->td_proc->p_fd; - - if ((unsigned)uap->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL) { - error = EBADF; + if ((error = fget(td, uap->fd, &fp)) != 0) goto done2; - } - - fhold(fp); switch (fp->f_type) { case DTYPE_PIPE: @@ -1335,6 +1307,124 @@ closef(fp, td) return (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. + * + * 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. + */ +static __inline +int +_fget(struct thread *td, int fd, struct file **fpp, int flags) +{ + struct filedesc *fdp; + struct file *fp; + + GIANT_REQUIRED; + fdp = td->td_proc->p_fd; + *fpp = NULL; + if ((u_int)fd >= fdp->fd_nfiles) + return(EBADF); + if ((fp = fdp->fd_ofiles[fd]) == NULL) + return(EBADF); + + /* + * 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); + ++fp->f_count; + *fpp = fp; + return(0); +} + +int +fget(struct thread *td, int fd, struct file **fpp) +{ + return(_fget(td, fd, fpp, 0)); +} + +int +fget_read(struct thread *td, int fd, struct file **fpp) +{ + return(_fget(td, fd, fpp, FREAD)); +} + +int +fget_write(struct thread *td, int fd, struct file **fpp) +{ + return(_fget(td, fd, fpp, FWRITE)); +} + +/* + * Like fget() but loads the underlying vnode, or returns an error if + * the descriptor does not represent a vnode. Note that pipes use vnodes + * but never have VM objects (so VOP_GETVOBJECT() calls will return an + * error). The returned vnode will be vref()d. + */ + +static __inline +int +_fgetvp(struct thread *td, int fd, struct vnode **vpp, int flags) +{ + struct filedesc *fdp; + struct file *fp; + + 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); +} + +int +fgetvp(struct thread *td, int fd, struct vnode **vpp) +{ + return(_fgetvp(td, fd, vpp, 0)); +} + +int +fgetvp_read(struct thread *td, int fd, struct vnode **vpp) +{ + return(_fgetvp(td, fd, vpp, FREAD)); +} + +int +fgetvp_write(struct thread *td, int fd, struct vnode **vpp) +{ + return(_fgetvp(td, fd, vpp, FWRITE)); +} + int fdrop(fp, td) struct file *fp; |