aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/vfs_mount.c
diff options
context:
space:
mode:
authorIan Dowse <iedowse@FreeBSD.org>2003-07-01 17:40:23 +0000
committerIan Dowse <iedowse@FreeBSD.org>2003-07-01 17:40:23 +0000
commit318f2fb4bf0401e59e5959a8315624686028edb7 (patch)
tree1027d5dd057a3d0ef01110534de81d0fc8bb748b /sys/kern/vfs_mount.c
parent9c3f1b326fd24c2e8f88f3875eecb5bdaf558387 (diff)
downloadsrc-318f2fb4bf0401e59e5959a8315624686028edb7.tar.gz
src-318f2fb4bf0401e59e5959a8315624686028edb7.zip
Add a new mount flag MNT_BYFSID that can be used to unmount a file
system by specifying the file system ID instead of a path. Use this by default in umount(8). This avoids the need to perform any vnode operations to look up the mount point, so it makes it possible to unmount a file system whose root vnode cannot be looked up (e.g. due to a dead NFS server, or a file system that has become detached from the hierarchy because an underlying file system was unmounted). It also provides an unambiguous way to specify which file system is to be unmunted. Since the ability to unmount using a path name is retained only for compatibility, that case now just uses a simple string comparison of the supplied path against f_mntonname of each mounted file system. Discussed on: freebsd-arch mdoc help from: ru
Notes
Notes: svn path=/head/; revision=117132
Diffstat (limited to 'sys/kern/vfs_mount.c')
-rw-r--r--sys/kern/vfs_mount.c55
1 files changed, 32 insertions, 23 deletions
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 02997c3d1ca1..7d166f02f45d 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));
}