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.
This commit is contained in:
parent
d6cc98f055
commit
7fbc7a8dce
@ -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;
|
||||
|
@ -394,23 +394,19 @@ struct kevent_args {
|
||||
int
|
||||
kevent(struct thread *td, struct kevent_args *uap)
|
||||
{
|
||||
struct filedesc *fdp;
|
||||
struct kevent *kevp;
|
||||
struct kqueue *kq;
|
||||
struct file *fp = NULL;
|
||||
struct file *fp;
|
||||
struct timespec ts;
|
||||
int i, n, nerrors, error;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
fdp = td->td_proc->p_fd;
|
||||
if (((u_int)uap->fd) >= fdp->fd_nfiles ||
|
||||
(fp = fdp->fd_ofiles[uap->fd]) == NULL ||
|
||||
(fp->f_type != DTYPE_KQUEUE)) {
|
||||
if ((error = fget(td, uap->fd, &fp)) != 0)
|
||||
goto done;
|
||||
if (fp->f_type != DTYPE_KQUEUE) {
|
||||
error = EBADF;
|
||||
goto done;
|
||||
}
|
||||
fhold(fp);
|
||||
|
||||
if (uap->timeout != NULL) {
|
||||
error = copyin(uap->timeout, &ts, sizeof(ts));
|
||||
if (error)
|
||||
|
@ -83,22 +83,6 @@ static int dofileread __P((struct thread *, struct file *, int, void *,
|
||||
static int dofilewrite __P((struct thread *, struct file *, int,
|
||||
const void *, size_t, off_t, int));
|
||||
|
||||
struct file*
|
||||
holdfp(fdp, fd, flag)
|
||||
struct filedesc* fdp;
|
||||
int fd, flag;
|
||||
{
|
||||
struct file* fp;
|
||||
|
||||
if (((u_int)fd) >= fdp->fd_nfiles ||
|
||||
(fp = fdp->fd_ofiles[fd]) == NULL ||
|
||||
(fp->f_flag & flag) == 0) {
|
||||
return (NULL);
|
||||
}
|
||||
fhold(fp);
|
||||
return (fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read system call.
|
||||
*/
|
||||
@ -115,18 +99,16 @@ struct read_args {
|
||||
int
|
||||
read(td, uap)
|
||||
struct thread *td;
|
||||
register struct read_args *uap;
|
||||
struct read_args *uap;
|
||||
{
|
||||
register struct file *fp;
|
||||
struct file *fp;
|
||||
int error;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
if ((fp = holdfp(td->td_proc->p_fd, uap->fd, FREAD)) != NULL) {
|
||||
if ((error = fget_read(td, uap->fd, &fp)) == 0) {
|
||||
error = dofileread(td, fp, uap->fd, uap->buf,
|
||||
uap->nbyte, (off_t)-1, 0);
|
||||
fdrop(fp, td);
|
||||
} else {
|
||||
error = EBADF;
|
||||
}
|
||||
mtx_unlock(&Giant);
|
||||
return(error);
|
||||
@ -150,20 +132,19 @@ struct pread_args {
|
||||
int
|
||||
pread(td, uap)
|
||||
struct thread *td;
|
||||
register struct pread_args *uap;
|
||||
struct pread_args *uap;
|
||||
{
|
||||
register struct file *fp;
|
||||
struct file *fp;
|
||||
int error;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
if ((fp = holdfp(td->td_proc->p_fd, uap->fd, FREAD)) == NULL) {
|
||||
error = EBADF;
|
||||
} else if (fp->f_type != DTYPE_VNODE) {
|
||||
error = ESPIPE;
|
||||
fdrop(fp, td);
|
||||
} else {
|
||||
error = dofileread(td, fp, uap->fd, uap->buf, uap->nbyte,
|
||||
uap->offset, FOF_OFFSET);
|
||||
if ((error = fget_read(td, uap->fd, &fp)) == 0) {
|
||||
if (fp->f_type == DTYPE_VNODE) {
|
||||
error = dofileread(td, fp, uap->fd, uap->buf,
|
||||
uap->nbyte, uap->offset, FOF_OFFSET);
|
||||
} else {
|
||||
error = ESPIPE;
|
||||
}
|
||||
fdrop(fp, td);
|
||||
}
|
||||
mtx_unlock(&Giant);
|
||||
@ -247,12 +228,11 @@ struct readv_args {
|
||||
int
|
||||
readv(td, uap)
|
||||
struct thread *td;
|
||||
register struct readv_args *uap;
|
||||
struct readv_args *uap;
|
||||
{
|
||||
register struct file *fp;
|
||||
register struct filedesc *fdp;
|
||||
struct file *fp;
|
||||
struct uio auio;
|
||||
register struct iovec *iov;
|
||||
struct iovec *iov;
|
||||
struct iovec *needfree;
|
||||
struct iovec aiov[UIO_SMALLIOV];
|
||||
long i, cnt, error = 0;
|
||||
@ -262,12 +242,9 @@ readv(td, uap)
|
||||
struct uio ktruio;
|
||||
#endif
|
||||
mtx_lock(&Giant);
|
||||
fdp = td->td_proc->p_fd;
|
||||
|
||||
if ((fp = holdfp(fdp, uap->fd, FREAD)) == NULL) {
|
||||
error = EBADF;
|
||||
if ((error = fget_read(td, uap->fd, &fp)) != 0)
|
||||
goto done2;
|
||||
}
|
||||
/* note: can't use iovlen until iovcnt is validated */
|
||||
iovlen = uap->iovcnt * sizeof (struct iovec);
|
||||
if (uap->iovcnt > UIO_SMALLIOV) {
|
||||
@ -352,18 +329,18 @@ struct write_args {
|
||||
int
|
||||
write(td, uap)
|
||||
struct thread *td;
|
||||
register struct write_args *uap;
|
||||
struct write_args *uap;
|
||||
{
|
||||
register struct file *fp;
|
||||
struct file *fp;
|
||||
int error;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
if ((fp = holdfp(td->td_proc->p_fd, uap->fd, FWRITE)) != NULL) {
|
||||
if ((error = fget_write(td, uap->fd, &fp)) == 0) {
|
||||
error = dofilewrite(td, fp, uap->fd, uap->buf, uap->nbyte,
|
||||
(off_t)-1, 0);
|
||||
fdrop(fp, td);
|
||||
} else {
|
||||
error = EBADF;
|
||||
error = EBADF; /* XXX this can't be right */
|
||||
}
|
||||
mtx_unlock(&Giant);
|
||||
return(error);
|
||||
@ -387,21 +364,22 @@ struct pwrite_args {
|
||||
int
|
||||
pwrite(td, uap)
|
||||
struct thread *td;
|
||||
register struct pwrite_args *uap;
|
||||
struct pwrite_args *uap;
|
||||
{
|
||||
register struct file *fp;
|
||||
struct file *fp;
|
||||
int error;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
if ((fp = holdfp(td->td_proc->p_fd, uap->fd, FWRITE)) == NULL) {
|
||||
error = EBADF;
|
||||
} else if (fp->f_type != DTYPE_VNODE) {
|
||||
error = ESPIPE;
|
||||
if ((error = fget_write(td, uap->fd, &fp)) == 0) {
|
||||
if (fp->f_type == DTYPE_VNODE) {
|
||||
error = dofilewrite(td, fp, uap->fd, uap->buf,
|
||||
uap->nbyte, uap->offset, FOF_OFFSET);
|
||||
} else {
|
||||
error = ESPIPE;
|
||||
}
|
||||
fdrop(fp, td);
|
||||
} else {
|
||||
error = dofilewrite(td, fp, uap->fd, uap->buf, uap->nbyte,
|
||||
uap->offset, FOF_OFFSET);
|
||||
fdrop(fp, td);
|
||||
error = EBADF; /* this can't be right */
|
||||
}
|
||||
mtx_unlock(&Giant);
|
||||
return(error);
|
||||
@ -489,8 +467,7 @@ writev(td, uap)
|
||||
struct thread *td;
|
||||
register struct writev_args *uap;
|
||||
{
|
||||
register struct file *fp;
|
||||
register struct filedesc *fdp;
|
||||
struct file *fp;
|
||||
struct uio auio;
|
||||
register struct iovec *iov;
|
||||
struct iovec *needfree;
|
||||
@ -503,8 +480,7 @@ writev(td, uap)
|
||||
#endif
|
||||
|
||||
mtx_lock(&Giant);
|
||||
fdp = td->td_proc->p_fd;
|
||||
if ((fp = holdfp(fdp, uap->fd, FWRITE)) == NULL) {
|
||||
if ((error = fget_write(td, uap->fd, &fp)) != 0) {
|
||||
error = EBADF;
|
||||
goto done2;
|
||||
}
|
||||
|
@ -1678,8 +1678,7 @@ sf_buf_free(caddr_t addr, void *args)
|
||||
int
|
||||
sendfile(struct thread *td, struct sendfile_args *uap)
|
||||
{
|
||||
struct file *fp;
|
||||
struct filedesc *fdp = td->td_proc->p_fd;
|
||||
struct file *fp = NULL;
|
||||
struct vnode *vp;
|
||||
struct vm_object *obj;
|
||||
struct socket *so;
|
||||
@ -1689,30 +1688,19 @@ sendfile(struct thread *td, struct sendfile_args *uap)
|
||||
struct writev_args nuap;
|
||||
struct sf_hdtr hdtr;
|
||||
off_t off, xfsize, sbytes = 0;
|
||||
int error = 0, s;
|
||||
int error, s;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
vp = NULL;
|
||||
|
||||
/*
|
||||
* Do argument checking. Must be a regular file in, stream
|
||||
* type and connected socket out, positive offset.
|
||||
* The descriptor must be a regular file and have a backing VM object.
|
||||
*/
|
||||
fp = holdfp(fdp, uap->fd, FREAD);
|
||||
if (fp == NULL) {
|
||||
error = EBADF;
|
||||
if ((error = fgetvp_read(td, uap->fd, &vp)) != 0)
|
||||
goto done;
|
||||
}
|
||||
if (fp->f_type != DTYPE_VNODE) {
|
||||
error = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
vp = (struct vnode *)fp->f_data;
|
||||
vref(vp);
|
||||
if (vp->v_type != VREG || VOP_GETVOBJECT(vp, &obj) != 0) {
|
||||
error = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
fdrop(fp, td);
|
||||
error = holdsock(td->td_proc->p_fd, uap->s, &fp);
|
||||
if (error)
|
||||
goto done;
|
||||
|
@ -49,6 +49,7 @@ struct stat;
|
||||
struct thread;
|
||||
struct uio;
|
||||
struct knote;
|
||||
struct vnode;
|
||||
|
||||
/*
|
||||
* Kernel descriptor table.
|
||||
@ -109,8 +110,15 @@ extern int maxfilesperproc; /* per process limit on number of open files */
|
||||
extern int nfiles; /* actual number of open files */
|
||||
|
||||
static __inline void fhold __P((struct file *fp));
|
||||
int fget __P((struct thread *td, int fd, struct file **fpp));
|
||||
int fget_read __P((struct thread *td, int fd, struct file **fpp));
|
||||
int fget_write __P((struct thread *td, int fd, struct file **fpp));
|
||||
int fdrop __P((struct file *fp, struct thread *td));
|
||||
|
||||
int fgetvp __P((struct thread *td, int fd, struct vnode **vpp));
|
||||
int fgetvp_read __P((struct thread *td, int fd, struct vnode **vpp));
|
||||
int fgetvp_write __P((struct thread *td, int fd, struct vnode **vpp));
|
||||
|
||||
static __inline void
|
||||
fhold(fp)
|
||||
struct file *fp;
|
||||
|
Loading…
Reference in New Issue
Block a user