summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorgreen <green@FreeBSD.org>1999-09-19 17:00:25 +0000
committergreen <green@FreeBSD.org>1999-09-19 17:00:25 +0000
commit140cb4ff83b0061eeba0756f708f3f7c117e76e5 (patch)
treedbfb58e46547ab96401ba9719626c5b12448fbfd /sys/kern
parentc171f3b18205ec5324a32cba54aff58ae5594701 (diff)
downloadFreeBSD-src-140cb4ff83b0061eeba0756f708f3f7c117e76e5.zip
FreeBSD-src-140cb4ff83b0061eeba0756f708f3f7c117e76e5.tar.gz
This is what was "fdfix2.patch," a fix for fd sharing. It's pretty
far-reaching in fd-land, so you'll want to consult the code for changes. The biggest change is that now, you don't use fp->f_ops->fo_foo(fp, bar) but instead fo_foo(fp, bar), which increments and decrements the fp refcount upon entry and exit. Two new calls, fhold() and fdrop(), are provided. Each does what it seems like it should, and if fdrop() brings the refcount to zero, the fd is freed as well. Thanks to peter ("to hell with it, it looks ok to me.") for his review. Thanks to msmith for keeping me from putting locks everywhere :) Reviewed by: peter
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_descrip.c45
-rw-r--r--sys/kern/sys_generic.c21
-rw-r--r--sys/kern/sys_pipe.c10
-rw-r--r--sys/kern/sys_socket.c6
-rw-r--r--sys/kern/uipc_syscalls.c4
-rw-r--r--sys/kern/vfs_aio.c8
-rw-r--r--sys/kern/vfs_vnops.c19
7 files changed, 66 insertions, 47 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 7e718a2..45f0945 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -96,7 +96,7 @@ static struct cdevsw fildesc_cdevsw = {
static int finishdup __P((struct filedesc *fdp, int old, int new, register_t *retval));
static int badfo_readwrite __P((struct file *fp, struct uio *uio,
- struct ucred *cred, int flags));
+ struct ucred *cred, int flags, struct proc *p));
static int badfo_ioctl __P((struct file *fp, u_long com, caddr_t data,
struct proc *p));
static int badfo_poll __P((struct file *fp, int events,
@@ -263,26 +263,23 @@ fcntl(p, uap)
fp->f_flag &= ~FCNTLFLAGS;
fp->f_flag |= FFLAGS(uap->arg & ~O_ACCMODE) & FCNTLFLAGS;
tmp = fp->f_flag & FNONBLOCK;
- error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
+ error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
if (error)
return (error);
tmp = fp->f_flag & FASYNC;
- error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
+ error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, p);
if (!error)
return (0);
fp->f_flag &= ~FNONBLOCK;
tmp = 0;
- (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
+ (void)fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
return (error);
case F_GETOWN:
- error = (*fp->f_ops->fo_ioctl)
- (fp, FIOGETOWN, (caddr_t)p->p_retval, p);
- return (error);
+ return (fo_ioctl(fp, FIOGETOWN, (caddr_t)p->p_retval, p));
case F_SETOWN:
- return ((*fp->f_ops->fo_ioctl)
- (fp, FIOSETOWN, (caddr_t)&uap->arg, p));
+ return (fo_ioctl(fp, FIOSETOWN, (caddr_t)&uap->arg, p));
case F_SETLKW:
flg |= F_WAIT;
@@ -360,7 +357,7 @@ finishdup(fdp, old, new, retval)
fp = fdp->fd_ofiles[old];
fdp->fd_ofiles[new] = fp;
fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
- fp->f_count++;
+ fhold(fp);
if (new > fdp->fd_lastfile)
fdp->fd_lastfile = new;
*retval = new;
@@ -967,7 +964,7 @@ fdcopy(p)
fpp = newfdp->fd_ofiles;
for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
if (*fpp != NULL)
- (*fpp)->f_count++;
+ fhold(*fpp);
return (newfdp);
}
@@ -1048,7 +1045,6 @@ closef(fp, p)
{
struct vnode *vp;
struct flock lf;
- int error;
if (fp == NULL)
return (0);
@@ -1068,10 +1064,6 @@ closef(fp, p)
vp = (struct vnode *)fp->f_data;
(void) VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_UNLCK, &lf, F_POSIX);
}
- if (--fp->f_count > 0)
- return (0);
- if (fp->f_count < 0)
- panic("closef: count < 0");
if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
lf.l_whence = SEEK_SET;
lf.l_start = 0;
@@ -1080,8 +1072,22 @@ closef(fp, p)
vp = (struct vnode *)fp->f_data;
(void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
}
+ return (fdrop(fp, p));
+}
+
+int
+fdrop(fp, p)
+ struct file *fp;
+ struct proc *p;
+{
+ int error;
+
+ if (--fp->f_count > 0)
+ return (0);
+ if (fp->f_count < 0)
+ panic("fdrop: count < 0");
if (fp->f_ops != &badfileops)
- error = (*fp->f_ops->fo_close)(fp, p);
+ error = fo_close(fp, p);
else
error = 0;
ffree(fp);
@@ -1212,7 +1218,7 @@ dupfdopen(fdp, indx, dfd, mode, error)
return (EACCES);
fdp->fd_ofiles[indx] = wfp;
fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
- wfp->f_count++;
+ fhold(wfp);
if (indx > fdp->fd_lastfile)
fdp->fd_lastfile = indx;
return (0);
@@ -1309,10 +1315,11 @@ struct fileops badfileops = {
};
static int
-badfo_readwrite(fp, uio, cred, flags)
+badfo_readwrite(fp, uio, cred, flags, p)
struct file *fp;
struct uio *uio;
struct ucred *cred;
+ struct proc *p;
int flags;
{
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index e187c21..1371f44 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -176,7 +176,7 @@ dofileread(p, fp, fd, buf, nbyte, offset, flags)
ktriov = aiov;
#endif
cnt = nbyte;
- if ((error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred, flags)))
+ if ((error = fo_read(fp, &auio, fp->f_cred, flags, p)))
if (auio.uio_resid != cnt && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
error = 0;
@@ -256,7 +256,7 @@ readv(p, uap)
}
#endif
cnt = auio.uio_resid;
- if ((error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred, 0)))
+ if ((error = fo_read(fp, &auio, fp->f_cred, 0, p)))
if (auio.uio_resid != cnt && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
error = 0;
@@ -360,7 +360,7 @@ dofilewrite(p, fp, fd, buf, nbyte, offset, flags)
ktriov = aiov;
#endif
cnt = nbyte;
- if ((error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred, flags))) {
+ if ((error = fo_write(fp, &auio, fp->f_cred, flags, p))) {
if (auio.uio_resid != cnt && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
error = 0;
@@ -444,7 +444,7 @@ writev(p, uap)
}
#endif
cnt = auio.uio_resid;
- if ((error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred, 0))) {
+ if ((error = fo_write(fp, &auio, fp->f_cred, 0, p))) {
if (auio.uio_resid != cnt && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
error = 0;
@@ -549,7 +549,7 @@ ioctl(p, uap)
fp->f_flag |= FNONBLOCK;
else
fp->f_flag &= ~FNONBLOCK;
- error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
+ error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
break;
case FIOASYNC:
@@ -557,11 +557,11 @@ ioctl(p, uap)
fp->f_flag |= FASYNC;
else
fp->f_flag &= ~FASYNC;
- error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
+ error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, p);
break;
default:
- error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
+ error = fo_ioctl(fp, com, data, p);
/*
* Copy any data to user, size was
* already set and checked above.
@@ -740,8 +740,7 @@ selscan(p, ibits, obits, nfd)
fp = fdp->fd_ofiles[fd];
if (fp == NULL)
return (EBADF);
- if ((*fp->f_ops->fo_poll)(fp, flag[msk],
- fp->f_cred, p)) {
+ if (fo_poll(fp, flag[msk], fp->f_cred, p)) {
obits[msk][(fd)/NFDBITS] |=
(1 << ((fd) % NFDBITS));
n++;
@@ -868,8 +867,8 @@ pollscan(p, fds, nfd)
* Note: backend also returns POLLHUP and
* POLLERR if appropriate.
*/
- fds->revents = (*fp->f_ops->fo_poll)(fp,
- fds->events, fp->f_cred, p);
+ fds->revents = fo_poll(fp, fds->events,
+ fp->f_cred, p);
if (fds->revents != 0)
n++;
}
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index e4f6d50..c8f8e35 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -88,9 +88,9 @@
* interfaces to the outside world
*/
static int pipe_read __P((struct file *fp, struct uio *uio,
- struct ucred *cred, int flags));
+ struct ucred *cred, int flags, struct proc *p));
static int pipe_write __P((struct file *fp, struct uio *uio,
- struct ucred *cred, int flags));
+ struct ucred *cred, int flags, struct proc *p));
static int pipe_close __P((struct file *fp, struct proc *p));
static int pipe_poll __P((struct file *fp, int events, struct ucred *cred,
struct proc *p));
@@ -319,10 +319,11 @@ pipeselwakeup(cpipe)
/* ARGSUSED */
static int
-pipe_read(fp, uio, cred, flags)
+pipe_read(fp, uio, cred, flags, p)
struct file *fp;
struct uio *uio;
struct ucred *cred;
+ struct proc *p;
int flags;
{
@@ -681,10 +682,11 @@ error1:
#endif
static int
-pipe_write(fp, uio, cred, flags)
+pipe_write(fp, uio, cred, flags, p)
struct file *fp;
struct uio *uio;
struct ucred *cred;
+ struct proc *p;
int flags;
{
int error = 0;
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
index 6ad4383..aa892e3 100644
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -54,10 +54,11 @@ struct fileops socketops =
/* ARGSUSED */
int
-soo_read(fp, uio, cred, flags)
+soo_read(fp, uio, cred, flags, p)
struct file *fp;
struct uio *uio;
struct ucred *cred;
+ struct proc *p;
int flags;
{
struct socket *so = (struct socket *)fp->f_data;
@@ -66,10 +67,11 @@ soo_read(fp, uio, cred, flags)
/* ARGSUSED */
int
-soo_write(fp, uio, cred, flags)
+soo_write(fp, uio, cred, flags, p)
struct file *fp;
struct uio *uio;
struct ucred *cred;
+ struct proc *p;
int flags;
{
struct socket *so = (struct socket *)fp->f_data;
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 05fb328..b87114d 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -1420,6 +1420,7 @@ sendfile(struct proc *p, struct sendfile_args *uap)
off_t off, xfsize, sbytes = 0;
int error = 0, s;
+ vp = NULL;
/*
* Do argument checking. Must be a regular file in, stream
* type and connected socket out, positive offset.
@@ -1435,6 +1436,7 @@ sendfile(struct proc *p, struct sendfile_args *uap)
goto done;
}
vp = (struct vnode *)fp->f_data;
+ vref(vp);
obj = vp->v_object;
if (vp->v_type != VREG || obj == NULL) {
error = EINVAL;
@@ -1698,5 +1700,7 @@ done:
if (uap->sbytes != NULL) {
copyout(&sbytes, uap->sbytes, sizeof(off_t));
}
+ if (vp)
+ vrele(vp);
return (error);
}
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index 7caf954..f5a0d58 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -564,10 +564,10 @@ aio_process(struct aiocblist *aiocbe)
oublock_st = mycp->p_stats->p_ru.ru_oublock;
if (cb->aio_lio_opcode == LIO_READ) {
auio.uio_rw = UIO_READ;
- error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred, FOF_OFFSET);
+ error = fo_read(fp, &auio, fp->f_cred, FOF_OFFSET, mycp);
} else {
auio.uio_rw = UIO_WRITE;
- error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred, FOF_OFFSET);
+ error = fo_write(fp, &auio, fp->f_cred, FOF_OFFSET, mycp);
}
inblock_end = mycp->p_stats->p_ru.ru_inblock;
oublock_end = mycp->p_stats->p_ru.ru_oublock;
@@ -1661,7 +1661,7 @@ aio_read(struct proc *p, struct aio_read_args *uap)
auio.uio_procp = p;
cnt = iocb.aio_nbytes;
- error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred, FOF_OFFSET);
+ error = fo_read(fp, &auio, fp->f_cred, FOF_OFFSET, p);
if (error &&
(auio.uio_resid != cnt) &&
(error == ERESTART || error == EINTR || error == EWOULDBLOCK))
@@ -1727,7 +1727,7 @@ aio_write(struct proc *p, struct aio_write_args *uap)
auio.uio_procp = p;
cnt = iocb.aio_nbytes;
- error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred, FOF_OFFSET);
+ error = fo_write(fp, &auio, fp->f_cred, FOF_OFFSET, p);
if (error) {
if (auio.uio_resid != cnt) {
if (error == ERESTART || error == EINTR || error == EWOULDBLOCK)
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index c42ebf6..242c696 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -57,11 +57,11 @@ static int vn_closefile __P((struct file *fp, struct proc *p));
static int vn_ioctl __P((struct file *fp, u_long com, caddr_t data,
struct proc *p));
static int vn_read __P((struct file *fp, struct uio *uio,
- struct ucred *cred, int flags));
+ struct ucred *cred, int flags, struct proc *p));
static int vn_poll __P((struct file *fp, int events, struct ucred *cred,
struct proc *p));
static int vn_write __P((struct file *fp, struct uio *uio,
- struct ucred *cred, int flags));
+ struct ucred *cred, int flags, struct proc *p));
struct fileops vnops =
{ vn_read, vn_write, vn_ioctl, vn_poll, vn_closefile };
@@ -274,16 +274,19 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
* File table vnode read routine.
*/
static int
-vn_read(fp, uio, cred, flags)
+vn_read(fp, uio, cred, flags, p)
struct file *fp;
struct uio *uio;
struct ucred *cred;
+ struct proc *p;
int flags;
{
- struct vnode *vp = (struct vnode *)fp->f_data;
- struct proc *p = uio->uio_procp;
+ struct vnode *vp;
int error, ioflag;
+ KASSERT(uio->uio_procp == p, ("uio_procp %p is not p %p",
+ uio->uio_procp, p));
+ vp = (struct vnode *)fp->f_data;
ioflag = 0;
if (fp->f_flag & FNONBLOCK)
ioflag |= IO_NDELAY;
@@ -330,16 +333,18 @@ vn_read(fp, uio, cred, flags)
* File table vnode write routine.
*/
static int
-vn_write(fp, uio, cred, flags)
+vn_write(fp, uio, cred, flags, p)
struct file *fp;
struct uio *uio;
struct ucred *cred;
+ struct proc *p;
int flags;
{
struct vnode *vp;
- struct proc *p = uio->uio_procp;
int error, ioflag;
+ KASSERT(uio->uio_procp == p, ("uio_procp %p is not p %p",
+ uio->uio_procp, p));
vp = (struct vnode *)fp->f_data;
if (vp->v_type == VREG)
bwillwrite();
OpenPOWER on IntegriCloud