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().
This commit is contained in:
Alfred Perlstein 2002-01-14 00:13:45 +00:00
parent 59047ccade
commit a4db49537b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=89319
22 changed files with 136 additions and 230 deletions

View File

@ -672,10 +672,8 @@ osf1_fstat(td, uap)
struct osf1_stat oub;
int error;
fp = ffind_hold(td, uap->fd);
if (fp == NULL)
return (EBADF);
if ((error = fget(td, uap->fd, &fp)) != 0)
return (error);
error = fo_stat(fp, &ub, td);
fdrop(fp, td);
cvtstat2osf1(&ub, &oub);

View File

@ -137,11 +137,13 @@ linux_open(struct thread *td, struct linux_open_args *args)
SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
struct file *fp;
fp = ffind_hold(td, td->td_retval[0]);
error = fget(td, td->td_retval[0], &fp);
PROC_UNLOCK(p);
if (fp->f_type == DTYPE_VNODE)
fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td);
fdrop(fp, td);
if (!error) {
if (fp->f_type == DTYPE_VNODE)
fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td);
fdrop(fp, td);
}
} else
PROC_UNLOCK(p);
#ifdef DEBUG
@ -996,9 +998,9 @@ fcntl_common(struct thread *td, struct linux_fcntl64_args *args)
* significant effect for pipes (SIGIO is not delivered for
* pipes under Linux-2.2.35 at least).
*/
fp = ffind_hold(td, args->fd);
if (fp == NULL)
return EBADF;
error = fget(td, args->fd, &fp);
if (error)
return (error);
if (fp->f_type == DTYPE_PIPE) {
fdrop(fp, td);
return (EINVAL);

View File

@ -109,9 +109,8 @@ linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args)
int error;
struct disklabel dl;
fp = ffind_hold(td, args->fd);
if (fp == NULL)
return (EBADF);
if ((error = fget(td, args->fd, &fp)) != 0)
return (error);
switch (args->cmd & 0xffff) {
case LINUX_BLKGETSIZE:
error = fo_ioctl(fp, DIOCGDINFO, (caddr_t)&dl, td);
@ -555,9 +554,9 @@ linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
struct file *fp;
int error;
fp = ffind_hold(td, args->fd);
if (fp == NULL)
return (EBADF);
if ((error = fget(td, args->fd, &fp)) != 0)
return (error);
switch (args->cmd & 0xffff) {
case LINUX_TCGETS:
@ -1249,9 +1248,8 @@ linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
struct file *fp;
int error;
fp = ffind_hold(td, args->fd);
if (fp == NULL)
return (EBADF);
if ((error = fget(td, args->fd, &fp)) != 0)
return (error);
switch (args->cmd & 0xffff) {
case LINUX_CDROMPAUSE:
@ -1706,9 +1704,8 @@ linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args)
struct file *fp;
int error;
fp = ffind_hold(td, args->fd);
if (fp == NULL)
return (EBADF);
if ((error = fget(td, args->fd, &fp)) != 0)
return (error);
switch (args->cmd & 0xffff) {
case LINUX_KIOCSOUND:
@ -2259,9 +2256,8 @@ linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
(unsigned long)args->cmd);
#endif
fp = ffind_hold(td, args->fd);
if (fp == NULL)
return (EBADF);
if ((error = fget(td, args->fd, &fp)) != 0)
return (error);
if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
fdrop(fp, td);
return (EBADF);

View File

@ -160,9 +160,8 @@ linux_newfstat(struct thread *td, struct linux_newfstat_args *args)
printf(ARGS(newfstat, "%d, *"), args->fd);
#endif
fp = ffind_hold(td, args->fd);
if (fp == NULL)
return (EBADF);
if ((error = fget(td, args->fd, &fp)) != 0)
return (error);
error = fo_stat(fp, &buf, td);
fdrop(fp, td);

View File

@ -246,23 +246,14 @@ fd_revoke(td, fd)
struct thread *td;
int fd;
{
struct file *fp;
struct vnode *vp;
struct mount *mp;
struct vattr vattr;
int error, *retval;
retval = td->td_retval;
fp = ffind_hold(td, fd);
if (fp == NULL)
return EBADF;
if (fp->f_type != DTYPE_VNODE) {
fdrop(fp, td);
return EINVAL;
}
vp = (struct vnode *) fp->f_data;
if ((error = fgetvp(td, fd, &vp)) != 0)
return (error);
if (vp->v_type != VCHR && vp->v_type != VBLK) {
error = EINVAL;
@ -283,7 +274,6 @@ fd_revoke(td, fd)
vn_finished_write(mp);
out:
vrele(vp);
fdrop(fp, td);
return error;
}
@ -294,7 +284,6 @@ fd_truncate(td, fd, flp)
int fd;
struct flock *flp;
{
struct file *fp;
off_t start, length;
struct vnode *vp;
struct vattr vattr;
@ -306,18 +295,16 @@ fd_truncate(td, fd, flp)
/*
* We only support truncating the file.
*/
fp = ffind_hold(td, fd);
if (fp == NULL)
return EBADF;
if ((error = fgetvp(td, uap->fd, &vp)) != 0)
return (error);
vp = (struct vnode *)fp->f_data;
if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
fdrop(fp, td);
if (vp->v_type == VFIFO) {
vrele(vp);
return ESPIPE;
}
if ((error = VOP_GETATTR(vp, &vattr, td->td_proc->p_ucred, td)) != 0)
fdrop(fp, td);
vrele(vp);
return error;
}
@ -337,7 +324,7 @@ fd_truncate(td, fd, flp)
break;
default:
fdrop(fp, td);
vrele(vp);
return EINVAL;
}
@ -351,7 +338,7 @@ fd_truncate(td, fd, flp)
error = ftruncate(td, &ft);
fdrop(fp, td);
vrele(vp);
return (error);
}
@ -386,13 +373,13 @@ svr4_sys_open(td, uap)
#if defined(NOTYET)
struct file *fp;
fp = ffind_hold(td, retval);
error = fget(td, retval, &fp);
PROC_UNLOCK(p);
/*
* we may have lost a race the above open() and
* another thread issuing a close()
*/
if (fp == NULL)
if (error)
return (EBADF); /* XXX: correct errno? */
/* ignore any error, just give it a try */
if (fp->f_type == DTYPE_VNODE)

View File

@ -107,8 +107,7 @@ svr4_sys_read(td, uap)
SCARG(&ra, buf) = SCARG(uap, buf);
SCARG(&ra, nbyte) = SCARG(uap, nbyte);
fp = ffind_hold(td, uap->fd);
if (fp == NULL) {
if (fget(td, uap->fd, &fp) != 0) {
DPRINTF(("Something fishy with the user-supplied file descriptor...\n"));
return EBADF;
}

View File

@ -102,9 +102,8 @@ svr4_sys_ioctl(td, uap)
retval = td->td_retval;
cmd = SCARG(uap, com);
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);

View File

@ -1717,8 +1717,7 @@ svr4_sys_putmsg(td, uap)
struct file *fp;
int error;
fp = ffind_hold(td, uap->fd);
if (fp == NULL) {
if ((error = fget(td, uap->fd, &fp)) != 0) {
#ifdef DEBUG_SVR4
uprintf("putmsg: bad fp\n");
#endif
@ -1905,8 +1904,7 @@ svr4_sys_getmsg(td, uap)
struct file *fp;
int error;
fp = ffind_hold(td, uap->fd);
if (fp == NULL) {
if ((error = fget(td, uap->fd, &fp)) != 0) {
#ifdef DEBUG_SVR4
uprintf("getmsg: bad fp\n");
#endif

View File

@ -2582,9 +2582,8 @@ aac_linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
debug_called(2);
fp = ffind_hold(td, args->fd);
if (fp == NULL)
return (EBADF);
if ((error = fget(td, args->fd, &fp)) != 0)
return (error);
cmd = args->cmd;
/*

View File

@ -844,9 +844,8 @@ linux_ioctl_tdfx(struct thread *td, struct linux_ioctl_args* args)
struct file *fp;
fp = ffind_hold(td, args->fd);
if (fp == NULL)
return (EBADF);
if ((error = fget(td, args->fd, &fp)) != 0)
return (error);
/* We simply copy the data and send it right to ioctl */
copyin((caddr_t)args->arg, &d_pio, sizeof(d_pio));
error = fo_ioctl(fp, cmd, (caddr_t)&d_pio, td);

View File

@ -213,11 +213,8 @@ fdesc_lookup(ap)
fd = 10 * fd + *pname++ - '0';
}
fp = ffind_hold(td, fd);
if (fp == NULL) {
error = EBADF;
if ((error = fget(td, fd, &fp)) != 0)
goto bad;
}
error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp, td);
fdrop(fp, td);
@ -301,9 +298,8 @@ fdesc_getattr(ap)
case Fdesc:
fd = VTOFDESC(vp)->fd_fd;
fp = ffind_hold(ap->a_td, fd);
if (fp == NULL)
return (EBADF);
if ((error = fget(ap->a_td, fd, &fp)) != 0)
return (error);
bzero(&stb, sizeof(stb));
error = fo_stat(fp, &stb, ap->a_td);

View File

@ -402,11 +402,8 @@ portal_open(ap)
* Check that the mode the file is being opened for is a subset
* of the mode of the existing descriptor.
*/
fp = ffind_hold(td, fd);
if (fp == NULL) {
error = EBADF;
if ((error = fget(td, fd, &fp)) != 0)
goto bad;
}
if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) {
fdrop(fp, td);
portal_closefd(td, fd);

View File

@ -194,10 +194,11 @@ ibcs2_open(td, uap)
PROC_LOCK(p);
if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
struct file *fp;
int error;
fp = ffind_hold(td, td->td_retval[0]);
error = fget(td, td->td_retval[0], &fp);
PROC_UNLOCK(p);
if (fp == NULL)
if (error)
return (EBADF);
/* ignore any error, just give it a try */

View File

@ -346,8 +346,7 @@ ibcs2_ioctl(td, uap)
struct file *fp;
int error;
fp = ffind_hold(td, uap->fd);
if (fp == NULL) {
if ((error = fget(td, uap->fd, &fp)) != 0) {
DPRINTF(("ibcs2_ioctl(%d): bad fd %d ", p->p_pid,
SCARG(uap, fd)));
return EBADF;

View File

@ -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);
}
@ -1455,50 +1450,6 @@ closef(fp, td)
return (fdrop(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.
*
* 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 doesn't exist, EBADF is returned.
*
* 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);

View File

@ -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) {

View File

@ -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] |=

View File

@ -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);

View File

@ -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);

View File

@ -591,9 +591,8 @@ ng_internalize(struct mbuf *control, struct thread *td)
/* Check that the FD given is legit. and change it to a pointer to a
* struct file. */
fd = CMSG_DATA(cm);
fp = ffind_hold(td, fd);
if (fp == NULL)
return (EBADF);
if ((error = fget(td, fd, &fp)) != 0)
return (error);
/* Depending on what kind of resource it is, act differently. For
* devices, we treat it as a file. For a AF_NETGRAPH socket,

View File

@ -166,8 +166,6 @@ static __inline int fo_stat __P((struct file *fp, struct stat *sb,
static __inline int fo_close __P((struct file *fp, struct thread *td));
static __inline int fo_kqfilter __P((struct file *fp, struct knote *kn));
struct proc;
struct file *ffind_hold(struct thread *, int fd);
struct file *ffind_lock(struct thread *, int fd);
static __inline int
fo_read(fp, uio, cred, flags, td)

View File

@ -292,11 +292,8 @@ mmap(td, uap)
* sure it is of appropriate type.
* don't let the descriptor disappear on us if we block
*/
fp = ffind_hold(td, uap->fd);
if (fp == NULL) {
error = EBADF;
if ((error = fget(td, uap->fd, &fp)) != 0)
goto done;
}
if (fp->f_type != DTYPE_VNODE) {
error = EINVAL;
goto done;