summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/vfs_mount.c55
-rw-r--r--sys/sys/mount.h7
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.
*
OpenPOWER on IntegriCloud