summaryrefslogtreecommitdiffstats
path: root/sys/cddl/compat
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2008-11-25 21:14:00 +0000
committerpjd <pjd@FreeBSD.org>2008-11-25 21:14:00 +0000
commit49203afd8c7d7140010993df59b7bfdb0557de3f (patch)
tree1909c16832a56eb1acac6a8c2f278445984e360c /sys/cddl/compat
parent12359ec70ec661ba582eacfd18561d9e3ca3ed4e (diff)
downloadFreeBSD-src-49203afd8c7d7140010993df59b7bfdb0557de3f.zip
FreeBSD-src-49203afd8c7d7140010993df59b7bfdb0557de3f.tar.gz
Fix locking (file descriptor table and Giant around VFS).
Most submitted by: kib Reviewed by: kib
Diffstat (limited to 'sys/cddl/compat')
-rw-r--r--sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c34
-rw-r--r--sys/cddl/compat/opensolaris/sys/vnode.h27
2 files changed, 43 insertions, 18 deletions
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c b/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c
index bf47fb8..21b2f23 100644
--- a/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c
+++ b/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c
@@ -67,17 +67,25 @@ static void *
kobj_open_file_vnode(const char *file)
{
struct thread *td = curthread;
+ struct filedesc *fd;
struct nameidata nd;
int error, flags;
- if (td->td_proc->p_fd->fd_rdir == NULL)
- td->td_proc->p_fd->fd_rdir = rootvnode;
- if (td->td_proc->p_fd->fd_cdir == NULL)
- td->td_proc->p_fd->fd_cdir = rootvnode;
+ fd = td->td_proc->p_fd;
+ FILEDESC_XLOCK(fd);
+ if (fd->fd_rdir == NULL) {
+ fd->fd_rdir = rootvnode;
+ vref(fd->fd_rdir);
+ }
+ if (fd->fd_cdir == NULL) {
+ fd->fd_cdir = rootvnode;
+ vref(fd->fd_cdir);
+ }
+ FILEDESC_XUNLOCK(fd);
flags = FREAD;
- NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, file, td);
- error = vn_open_cred(&nd, &flags, 0, curthread->td_ucred, NULL);
+ NDINIT(&nd, LOOKUP, MPSAFE, UIO_SYSSPACE, file, td);
+ error = vn_open_cred(&nd, &flags, O_NOFOLLOW, curthread->td_ucred, NULL);
NDFREE(&nd, NDF_ONLY_PNBUF);
if (error != 0)
return (NULL);
@@ -120,13 +128,15 @@ kobj_get_filesize_vnode(struct _buf *file, uint64_t *size)
{
struct vnode *vp = file->ptr;
struct vattr va;
- int error;
+ int error, vfslocked;
+ vfslocked = VFS_LOCK_GIANT(vp->v_mount);
vn_lock(vp, LK_SHARED | LK_RETRY);
error = VOP_GETATTR(vp, &va, curthread->td_ucred);
VOP_UNLOCK(vp, 0);
if (error == 0)
*size = (uint64_t)va.va_size;
+ VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@@ -159,7 +169,7 @@ kobj_read_file_vnode(struct _buf *file, char *buf, unsigned size, unsigned off)
struct thread *td = curthread;
struct uio auio;
struct iovec aiov;
- int error;
+ int error, vfslocked;
bzero(&aiov, sizeof(aiov));
bzero(&auio, sizeof(auio));
@@ -175,9 +185,11 @@ kobj_read_file_vnode(struct _buf *file, char *buf, unsigned size, unsigned off)
auio.uio_resid = size;
auio.uio_td = td;
+ vfslocked = VFS_LOCK_GIANT(vp->v_mount);
vn_lock(vp, LK_SHARED | LK_RETRY);
error = VOP_READ(vp, &auio, IO_UNIT | IO_SYNC, td->td_ucred);
VOP_UNLOCK(vp, 0);
+ VFS_UNLOCK_GIANT(vfslocked);
return (error != 0 ? -1 : size - auio.uio_resid);
}
@@ -211,9 +223,11 @@ kobj_close_file(struct _buf *file)
if (file->mounted) {
struct vnode *vp = file->ptr;
struct thread *td = curthread;
- int flags = FREAD;
+ int vfslocked;
- vn_close(vp, flags, td->td_ucred, td);
+ vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ vn_close(vp, FREAD, td->td_ucred, td);
+ VFS_UNLOCK_GIANT(vfslocked);
}
kmem_free(file, sizeof(*file));
}
diff --git a/sys/cddl/compat/opensolaris/sys/vnode.h b/sys/cddl/compat/opensolaris/sys/vnode.h
index b490d33..6044235 100644
--- a/sys/cddl/compat/opensolaris/sys/vnode.h
+++ b/sys/cddl/compat/opensolaris/sys/vnode.h
@@ -149,6 +149,7 @@ vn_openat(char *pnamep, enum uio_seg seg, int filemode, int createmode,
int fd)
{
struct thread *td = curthread;
+ struct filedesc *fdc;
struct nameidata nd;
int error, operation;
@@ -164,20 +165,26 @@ vn_openat(char *pnamep, enum uio_seg seg, int filemode, int createmode,
}
ASSERT(umask == 0);
- if (td->td_proc->p_fd->fd_rdir == NULL)
- td->td_proc->p_fd->fd_rdir = rootvnode;
- if (td->td_proc->p_fd->fd_cdir == NULL)
- td->td_proc->p_fd->fd_cdir = rootvnode;
+ fdc = td->td_proc->p_fd;
+ FILEDESC_XLOCK(fdc);
+ if (fdc->fd_rdir == NULL) {
+ fdc->fd_rdir = rootvnode;
+ vref(fdc->fd_rdir);
+ }
+ if (fdc->fd_cdir == NULL) {
+ fdc->fd_cdir = rootvnode;
+ vref(fdc->fd_rdir);
+ }
+ FILEDESC_XUNLOCK(fdc);
if (startvp != NULL)
vref(startvp);
- NDINIT_ATVP(&nd, operation, NOFOLLOW | MPSAFE, UIO_SYSSPACE, pnamep,
- startvp, td);
+ NDINIT_ATVP(&nd, operation, MPSAFE, UIO_SYSSPACE, pnamep, startvp, td);
+ filemode |= O_NOFOLLOW;
error = vn_open_cred(&nd, &filemode, createmode, td->td_ucred, NULL);
NDFREE(&nd, NDF_ONLY_PNBUF);
if (error == 0) {
/* We just unlock so we hold a reference. */
- VN_HOLD(nd.ni_vp);
VOP_UNLOCK(nd.ni_vp, 0);
*vpp = nd.ni_vp;
}
@@ -248,12 +255,16 @@ drop:
static __inline int
zfs_vop_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr)
{
+ int error, vfslocked;
ASSERT(flag == (FWRITE | FCREAT | FTRUNC | FOFFMAX));
ASSERT(count == 1);
ASSERT(offset == 0);
- return (vn_close(vp, flag, cr, curthread));
+ vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ error = vn_close(vp, flag, cr, curthread);
+ VFS_UNLOCK_GIANT(vfslocked);
+ return (error);
}
#define VOP_CLOSE(vp, oflags, count, offset, cr, ct) \
zfs_vop_close((vp), (oflags), (count), (offset), (cr))
OpenPOWER on IntegriCloud