diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/vfs_mount.c | 55 | ||||
-rw-r--r-- | sys/sys/mount.h | 7 |
2 files changed, 34 insertions, 28 deletions
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 02997c3..7d166f0 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -1224,17 +1224,39 @@ unmount(td, uap) int flags; } */ *uap; { - register struct vnode *vp; struct mount *mp; - int error; - struct nameidata nd; + char *pathbuf; + int error, id0, id1; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, td); - if ((error = namei(&nd)) != 0) + pathbuf = malloc(MNAMELEN, M_TEMP, M_WAITOK); + error = copyinstr(uap->path, pathbuf, MNAMELEN, NULL); + if (error) { + free(pathbuf, M_TEMP); return (error); - vp = nd.ni_vp; - NDFREE(&nd, NDF_ONLY_PNBUF); - mp = vp->v_mount; + } + if (uap->flags & MNT_BYFSID) { + /* Decode the filesystem ID. */ + if (sscanf(pathbuf, "FSID:%d:%d", &id0, &id1) != 2) { + free(pathbuf, M_TEMP); + return (EINVAL); + } + + mtx_lock(&mountlist_mtx); + TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) + if (mp->mnt_stat.f_fsid.val[0] == id0 && + mp->mnt_stat.f_fsid.val[1] == id1) + break; + mtx_unlock(&mountlist_mtx); + } else { + mtx_lock(&mountlist_mtx); + TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) + if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0) + break; + mtx_unlock(&mountlist_mtx); + } + free(pathbuf, M_TEMP); + if (mp == NULL) + return (ENOENT); /* * Only root, or the user that did the original mount is @@ -1242,28 +1264,15 @@ unmount(td, uap) */ if (mp->mnt_cred->cr_uid != td->td_ucred->cr_uid) { error = suser(td); - if (error) { - vput(vp); + if (error) return (error); - } } /* * Don't allow unmounting the root filesystem. */ - if (mp->mnt_flag & MNT_ROOTFS) { - vput(vp); + if (mp->mnt_flag & MNT_ROOTFS) return (EINVAL); - } - - /* - * Must be the root of the filesystem - */ - if ((vp->v_vflag & VV_ROOT) == 0) { - vput(vp); - return (EINVAL); - } - vput(vp); return (dounmount(mp, uap->flags, td)); } diff --git a/sys/sys/mount.h b/sys/sys/mount.h index 7c4c471..eed3ed4 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -224,12 +224,9 @@ struct mount { #define MNT_RELOAD 0x00040000 /* reload filesystem data */ #define MNT_FORCE 0x00080000 /* force unmount or readonly change */ #define MNT_SNAPSHOT 0x01000000 /* snapshot the filesystem */ +#define MNT_BYFSID 0x08000000 /* specify filesystem by ID. */ #define MNT_CMDFLAGS (MNT_UPDATE | MNT_DELEXPORT | MNT_RELOAD | \ - MNT_FORCE | MNT_SNAPSHOT) -/* - * Still available - */ -#define MNT_SPARE3 0x08000000 + MNT_FORCE | MNT_SNAPSHOT | MNT_BYFSID) /* * Internal filesystem control flags stored in mnt_kern_flag. * |