- 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
This commit is contained in:
Jeff Roberson 2006-02-22 06:19:08 +00:00
parent f5cacb3964
commit 05b6a20a66
2 changed files with 56 additions and 42 deletions

View File

@ -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);

View File

@ -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);