From 7429328cf4ef5915d7909e8b69cc912ba858963c Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 22 Feb 2006 06:19:08 +0000 Subject: - Hold the vnode used in the statfs related functions until we're done with the VFS_STATFS call to prevent the mount from disappearing while we're stating. - Convert these routines to use MPSAFE namei semantics. MFC After: 1 week --- sys/kern/vfs_extattr.c | 49 ++++++++++++++++++++++++++++--------------------- sys/kern/vfs_syscalls.c | 49 ++++++++++++++++++++++++++++--------------------- 2 files changed, 56 insertions(+), 42 deletions(-) (limited to 'sys') diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index f208deb..00f180d 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -245,22 +245,21 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, struct statfs *sp, sb; int error; struct nameidata nd; + int vfslocked; - mtx_lock(&Giant); - NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); + NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF|MPSAFE, pathseg, path, td); error = namei(&nd); - if (error) { - mtx_unlock(&Giant); + if (error) return (error); - } + vfslocked = NDHASGIANT(&nd); mp = nd.ni_vp->v_mount; sp = &mp->mnt_stat; NDFREE(&nd, NDF_ONLY_PNBUF); - vrele(nd.ni_vp); #ifdef MAC error = mac_check_mount_stat(td->td_ucred, mp); if (error) { - mtx_unlock(&Giant); + vput(nd.ni_vp); + VFS_UNLOCK_GIANT(vfslocked); return (error); } #endif @@ -271,17 +270,16 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, sp->f_namemax = NAME_MAX; sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; error = VFS_STATFS(mp, sp, td); - if (error) { - mtx_unlock(&Giant); + vput(nd.ni_vp); + VFS_UNLOCK_GIANT(vfslocked); + if (error) return (error); - } if (suser(td)) { bcopy(sp, &sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; prison_enforce_statfs(td->td_ucred, mp, &sb); sp = &sb; } - mtx_unlock(&Giant); *buf = *sp; return (0); } @@ -319,21 +317,26 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf) struct mount *mp; struct statfs *sp, sb; struct vnode *vp; + int vfslocked; int error; error = getvnode(td->td_proc->p_fd, fd, &fp); if (error) return (error); vp = fp->f_vnode; - mp = vp->v_mount; + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + /* Lock the vnode to prevent the mount from going away. */ + error = vn_lock(vp, LK_EXCLUSIVE, td); fdrop(fp, td); - if (vp->v_iflag & VI_DOOMED) + if (error) { + VFS_UNLOCK_GIANT(vfslocked); return (EBADF); - mtx_lock(&Giant); + } + mp = vp->v_mount; #ifdef MAC error = mac_check_mount_stat(td->td_ucred, mp); if (error) { - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); return (error); } #endif @@ -345,17 +348,16 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf) sp->f_namemax = NAME_MAX; sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; error = VFS_STATFS(mp, sp, td); - if (error) { - mtx_unlock(&Giant); + VOP_UNLOCK(vp, 0, td); + VFS_UNLOCK_GIANT(vfslocked); + if (error) return (error); - } if (suser(td)) { bcopy(sp, &sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; prison_enforce_statfs(td->td_ucred, mp, &sb); sp = &sb; } - mtx_unlock(&Giant); *buf = *sp; return (0); } @@ -691,6 +693,7 @@ fchdir(td, uap) #endif else error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); + /* XXX Unref'd mp access. */ while (!error && (mp = vp->v_mountedhere) != NULL) { int tvfslocked; if (vfs_busy(mp, 0, 0, td)) @@ -4243,13 +4246,16 @@ kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf) } mp = vp->v_mount; sp = &mp->mnt_stat; - vput(vp); error = prison_canseemount(td->td_ucred, mp); - if (error) + if (error) { + vput(vp); + mtx_unlock(&Giant); return (error); + } #ifdef MAC error = mac_check_mount_stat(td->td_ucred, mp); if (error) { + vput(vp); mtx_unlock(&Giant); return (error); } @@ -4261,6 +4267,7 @@ kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf) sp->f_namemax = NAME_MAX; sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; error = VFS_STATFS(mp, sp, td); + vput(vp); mtx_unlock(&Giant); if (error) return (error); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index f208deb..00f180d 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -245,22 +245,21 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, struct statfs *sp, sb; int error; struct nameidata nd; + int vfslocked; - mtx_lock(&Giant); - NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td); + NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF|MPSAFE, pathseg, path, td); error = namei(&nd); - if (error) { - mtx_unlock(&Giant); + if (error) return (error); - } + vfslocked = NDHASGIANT(&nd); mp = nd.ni_vp->v_mount; sp = &mp->mnt_stat; NDFREE(&nd, NDF_ONLY_PNBUF); - vrele(nd.ni_vp); #ifdef MAC error = mac_check_mount_stat(td->td_ucred, mp); if (error) { - mtx_unlock(&Giant); + vput(nd.ni_vp); + VFS_UNLOCK_GIANT(vfslocked); return (error); } #endif @@ -271,17 +270,16 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, sp->f_namemax = NAME_MAX; sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; error = VFS_STATFS(mp, sp, td); - if (error) { - mtx_unlock(&Giant); + vput(nd.ni_vp); + VFS_UNLOCK_GIANT(vfslocked); + if (error) return (error); - } if (suser(td)) { bcopy(sp, &sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; prison_enforce_statfs(td->td_ucred, mp, &sb); sp = &sb; } - mtx_unlock(&Giant); *buf = *sp; return (0); } @@ -319,21 +317,26 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf) struct mount *mp; struct statfs *sp, sb; struct vnode *vp; + int vfslocked; int error; error = getvnode(td->td_proc->p_fd, fd, &fp); if (error) return (error); vp = fp->f_vnode; - mp = vp->v_mount; + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + /* Lock the vnode to prevent the mount from going away. */ + error = vn_lock(vp, LK_EXCLUSIVE, td); fdrop(fp, td); - if (vp->v_iflag & VI_DOOMED) + if (error) { + VFS_UNLOCK_GIANT(vfslocked); return (EBADF); - mtx_lock(&Giant); + } + mp = vp->v_mount; #ifdef MAC error = mac_check_mount_stat(td->td_ucred, mp); if (error) { - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); return (error); } #endif @@ -345,17 +348,16 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf) sp->f_namemax = NAME_MAX; sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; error = VFS_STATFS(mp, sp, td); - if (error) { - mtx_unlock(&Giant); + VOP_UNLOCK(vp, 0, td); + VFS_UNLOCK_GIANT(vfslocked); + if (error) return (error); - } if (suser(td)) { bcopy(sp, &sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; prison_enforce_statfs(td->td_ucred, mp, &sb); sp = &sb; } - mtx_unlock(&Giant); *buf = *sp; return (0); } @@ -691,6 +693,7 @@ fchdir(td, uap) #endif else error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); + /* XXX Unref'd mp access. */ while (!error && (mp = vp->v_mountedhere) != NULL) { int tvfslocked; if (vfs_busy(mp, 0, 0, td)) @@ -4243,13 +4246,16 @@ kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf) } mp = vp->v_mount; sp = &mp->mnt_stat; - vput(vp); error = prison_canseemount(td->td_ucred, mp); - if (error) + if (error) { + vput(vp); + mtx_unlock(&Giant); return (error); + } #ifdef MAC error = mac_check_mount_stat(td->td_ucred, mp); if (error) { + vput(vp); mtx_unlock(&Giant); return (error); } @@ -4261,6 +4267,7 @@ kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf) sp->f_namemax = NAME_MAX; sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; error = VFS_STATFS(mp, sp, td); + vput(vp); mtx_unlock(&Giant); if (error) return (error); -- cgit v1.1