summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authoralfred <alfred@FreeBSD.org>2002-01-14 00:13:45 +0000
committeralfred <alfred@FreeBSD.org>2002-01-14 00:13:45 +0000
commit1f82bc18d1d1e906cd9ed68039acb051fa6e11cf (patch)
treefe7842143c9585ef2ebb793d812ec71cc4488a51 /sys/kern
parentc4988e25d265bba2c63409a8c8b8708c13d8525e (diff)
downloadFreeBSD-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.c187
-rw-r--r--sys/kern/kern_event.c8
-rw-r--r--sys/kern/sys_generic.c10
-rw-r--r--sys/kern/vfs_extattr.c7
-rw-r--r--sys/kern/vfs_syscalls.c7
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);
OpenPOWER on IntegriCloud