summaryrefslogtreecommitdiffstats
path: root/sys/kern/sys_generic.c
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2001-09-01 19:34:23 +0000
committerdillon <dillon@FreeBSD.org>2001-09-01 19:34:23 +0000
commit3f8ba718ee9c96acb7bc5d81453a0f44c1c17368 (patch)
tree01684b057eb764d6be338a2be91a2065798b74ea /sys/kern/sys_generic.c
parentfe1db6c569c0dc4b40561ec4b0c9366c53cffbb4 (diff)
downloadFreeBSD-src-3f8ba718ee9c96acb7bc5d81453a0f44c1c17368.zip
FreeBSD-src-3f8ba718ee9c96acb7bc5d81453a0f44c1c17368.tar.gz
Giant Pushdown:
read() pread() readv() write () pwrite() writev() ioctl() select () poll() openbsd_poll()
Diffstat (limited to 'sys/kern/sys_generic.c')
-rw-r--r--sys/kern/sys_generic.c160
1 files changed, 120 insertions, 40 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index e4db30d..945530a 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -109,6 +109,9 @@ struct read_args {
size_t nbyte;
};
#endif
+/*
+ * MPSAFE
+ */
int
read(p, uap)
struct proc *p;
@@ -117,10 +120,15 @@ read(p, uap)
register struct file *fp;
int error;
- if ((fp = holdfp(p->p_fd, uap->fd, FREAD)) == NULL)
- return (EBADF);
- error = dofileread(p, fp, uap->fd, uap->buf, uap->nbyte, (off_t)-1, 0);
- fdrop(fp, p);
+ mtx_lock(&Giant);
+ if ((fp = holdfp(p->p_fd, uap->fd, FREAD)) != NULL) {
+ error = dofileread(p, fp, uap->fd, uap->buf,
+ uap->nbyte, (off_t)-1, 0);
+ fdrop(fp, p);
+ } else {
+ error = EBADF;
+ }
+ mtx_unlock(&Giant);
return(error);
}
@@ -136,6 +144,9 @@ struct pread_args {
off_t offset;
};
#endif
+/*
+ * MPSAFE
+ */
int
pread(p, uap)
struct proc *p;
@@ -144,15 +155,18 @@ pread(p, uap)
register struct file *fp;
int error;
- if ((fp = holdfp(p->p_fd, uap->fd, FREAD)) == NULL)
- return (EBADF);
- if (fp->f_type != DTYPE_VNODE) {
+ mtx_lock(&Giant);
+ if ((fp = holdfp(p->p_fd, uap->fd, FREAD)) == NULL) {
+ error = EBADF;
+ } else if (fp->f_type != DTYPE_VNODE) {
error = ESPIPE;
+ fdrop(fp, p);
} else {
- error = dofileread(p, fp, uap->fd, uap->buf, uap->nbyte,
- uap->offset, FOF_OFFSET);
+ error = dofileread(p, fp, uap->fd, uap->buf, uap->nbyte,
+ uap->offset, FOF_OFFSET);
+ fdrop(fp, p);
}
- fdrop(fp, p);
+ mtx_unlock(&Giant);
return(error);
}
@@ -227,13 +241,16 @@ struct readv_args {
u_int iovcnt;
};
#endif
+/*
+ * MPSAFE
+ */
int
readv(p, uap)
struct proc *p;
register struct readv_args *uap;
{
register struct file *fp;
- register struct filedesc *fdp = p->p_fd;
+ register struct filedesc *fdp;
struct uio auio;
register struct iovec *iov;
struct iovec *needfree;
@@ -244,14 +261,20 @@ readv(p, uap)
struct iovec *ktriov = NULL;
struct uio ktruio;
#endif
+ mtx_lock(&Giant);
+ fdp = p->p_fd;
- if ((fp = holdfp(fdp, uap->fd, FREAD)) == NULL)
- return (EBADF);
+ if ((fp = holdfp(fdp, uap->fd, FREAD)) == NULL) {
+ error = EBADF;
+ goto done2;
+ }
/* note: can't use iovlen until iovcnt is validated */
iovlen = uap->iovcnt * sizeof (struct iovec);
if (uap->iovcnt > UIO_SMALLIOV) {
- if (uap->iovcnt > UIO_MAXIOV)
- return (EINVAL);
+ if (uap->iovcnt > UIO_MAXIOV) {
+ error = EINVAL;
+ goto done2;
+ }
MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
needfree = iov;
} else {
@@ -308,6 +331,8 @@ done:
fdrop(fp, p);
if (needfree)
FREE(needfree, M_IOV);
+done2:
+ mtx_unlock(&Giant);
return (error);
}
@@ -321,6 +346,9 @@ struct write_args {
size_t nbyte;
};
#endif
+/*
+ * MPSAFE
+ */
int
write(p, uap)
struct proc *p;
@@ -329,10 +357,15 @@ write(p, uap)
register struct file *fp;
int error;
- if ((fp = holdfp(p->p_fd, uap->fd, FWRITE)) == NULL)
- return (EBADF);
- error = dofilewrite(p, fp, uap->fd, uap->buf, uap->nbyte, (off_t)-1, 0);
- fdrop(fp, p);
+ mtx_lock(&Giant);
+ if ((fp = holdfp(p->p_fd, uap->fd, FWRITE)) != NULL) {
+ error = dofilewrite(p, fp, uap->fd, uap->buf, uap->nbyte,
+ (off_t)-1, 0);
+ fdrop(fp, p);
+ } else {
+ error = EBADF;
+ }
+ mtx_unlock(&Giant);
return(error);
}
@@ -348,6 +381,9 @@ struct pwrite_args {
off_t offset;
};
#endif
+/*
+ * MPSAFE
+ */
int
pwrite(p, uap)
struct proc *p;
@@ -356,15 +392,18 @@ pwrite(p, uap)
register struct file *fp;
int error;
- if ((fp = holdfp(p->p_fd, uap->fd, FWRITE)) == NULL)
- return (EBADF);
- if (fp->f_type != DTYPE_VNODE) {
+ mtx_lock(&Giant);
+ if ((fp = holdfp(p->p_fd, uap->fd, FWRITE)) == NULL) {
+ error = EBADF;
+ } else if (fp->f_type != DTYPE_VNODE) {
error = ESPIPE;
+ fdrop(fp, p);
} else {
- error = dofilewrite(p, fp, uap->fd, uap->buf, uap->nbyte,
- uap->offset, FOF_OFFSET);
+ error = dofilewrite(p, fp, uap->fd, uap->buf, uap->nbyte,
+ uap->offset, FOF_OFFSET);
+ fdrop(fp, p);
}
- fdrop(fp, p);
+ mtx_unlock(&Giant);
return(error);
}
@@ -442,13 +481,16 @@ struct writev_args {
u_int iovcnt;
};
#endif
+/*
+ * MPSAFE
+ */
int
writev(p, uap)
struct proc *p;
register struct writev_args *uap;
{
register struct file *fp;
- register struct filedesc *fdp = p->p_fd;
+ register struct filedesc *fdp;
struct uio auio;
register struct iovec *iov;
struct iovec *needfree;
@@ -460,8 +502,12 @@ writev(p, uap)
struct uio ktruio;
#endif
- if ((fp = holdfp(fdp, uap->fd, FWRITE)) == NULL)
- return (EBADF);
+ mtx_lock(&Giant);
+ fdp = p->p_fd;
+ if ((fp = holdfp(fdp, uap->fd, FWRITE)) == NULL) {
+ error = EBADF;
+ goto done2;
+ }
/* note: can't use iovlen until iovcnt is validated */
iovlen = uap->iovcnt * sizeof (struct iovec);
if (uap->iovcnt > UIO_SMALLIOV) {
@@ -533,6 +579,8 @@ done:
fdrop(fp, p);
if (needfree)
FREE(needfree, M_IOV);
+done2:
+ mtx_unlock(&Giant);
return (error);
}
@@ -546,6 +594,9 @@ struct ioctl_args {
caddr_t data;
};
#endif
+/*
+ * MPSAFE
+ */
/* ARGSUSED */
int
ioctl(p, uap)
@@ -555,7 +606,7 @@ ioctl(p, uap)
register struct file *fp;
register struct filedesc *fdp;
register u_long com;
- int error;
+ int error = 0;
register u_int size;
caddr_t data, memp;
int tmp;
@@ -565,21 +616,26 @@ ioctl(p, uap)
long align;
} ubuf;
+ mtx_lock(&Giant);
fdp = p->p_fd;
if ((u_int)uap->fd >= fdp->fd_nfiles ||
- (fp = fdp->fd_ofiles[uap->fd]) == NULL)
- return (EBADF);
+ (fp = fdp->fd_ofiles[uap->fd]) == NULL) {
+ error = EBADF;
+ goto done2;
+ }
- if ((fp->f_flag & (FREAD | FWRITE)) == 0)
- return (EBADF);
+ if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
+ error = EBADF;
+ goto done2;
+ }
switch (com = uap->com) {
case FIONCLEX:
fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE;
- return (0);
+ goto done2;
case FIOCLEX:
fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE;
- return (0);
+ goto done2;
}
/*
@@ -587,8 +643,10 @@ ioctl(p, uap)
* copied to/from the user's address space.
*/
size = IOCPARM_LEN(com);
- if (size > IOCPARM_MAX)
- return (ENOTTY);
+ if (size > IOCPARM_MAX) {
+ error = ENOTTY;
+ goto done2;
+ }
fhold(fp);
@@ -606,7 +664,7 @@ ioctl(p, uap)
if (memp)
free(memp, M_IOCTLOPS);
fdrop(fp, p);
- return (error);
+ goto done2;
}
} else {
*(caddr_t *)data = uap->data;
@@ -652,6 +710,8 @@ ioctl(p, uap)
if (memp)
free(memp, M_IOCTLOPS);
fdrop(fp, p);
+done2:
+ mtx_unlock(&Giant);
return (error);
}
@@ -669,6 +729,9 @@ struct select_args {
struct timeval *tv;
};
#endif
+/*
+ * MPSAFE
+ */
int
select(p, uap)
register struct proc *p;
@@ -689,6 +752,9 @@ select(p, uap)
if (uap->nd < 0)
return (EINVAL);
+
+ mtx_lock(&Giant);
+
if (uap->nd > p->p_fd->fd_nfiles)
uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */
@@ -831,6 +897,8 @@ done_noproclock:
free(selbits, M_SELECT);
if (heldbits != &s_heldbits[0])
free(heldbits, M_SELECT);
+
+ mtx_unlock(&Giant);
return (error);
}
@@ -916,6 +984,9 @@ struct poll_args {
int timeout;
};
#endif
+/*
+ * MPSAFE
+ */
int
poll(p, uap)
struct proc *p;
@@ -931,6 +1002,8 @@ poll(p, uap)
struct pollfd *heldbits;
nfds = SCARG(uap, nfds);
+
+ mtx_lock(&Giant);
/*
* This is kinda bogus. We have fd limits, but that is not
* really related to the size of the pollfd array. Make sure
@@ -938,8 +1011,10 @@ poll(p, uap)
* least enough for the current limits. We want to be reasonably
* safe, but not overly restrictive.
*/
- if (nfds > p->p_rlimit[RLIMIT_NOFILE].rlim_cur && nfds > FD_SETSIZE)
- return (EINVAL);
+ if (nfds > p->p_rlimit[RLIMIT_NOFILE].rlim_cur && nfds > FD_SETSIZE) {
+ error = EINVAL;
+ goto done2;
+ }
ni = nfds * sizeof(struct pollfd);
if (ni > sizeof(smallbits))
bits = malloc(ni, M_TEMP, M_WAITOK);
@@ -1030,6 +1105,8 @@ out:
free(bits, M_TEMP);
if (ni > sizeof(p_heldbits))
free(heldbits, M_TEMP);
+done2:
+ mtx_unlock(&Giant);
return (error);
}
@@ -1109,6 +1186,9 @@ struct openbsd_poll_args {
int timeout;
};
#endif
+/*
+ * MPSAFE
+ */
int
openbsd_poll(p, uap)
register struct proc *p;
OpenPOWER on IntegriCloud