summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libc/sys/mount.218
-rw-r--r--sbin/umount/umount.c141
-rw-r--r--sys/kern/vfs_mount.c55
-rw-r--r--sys/sys/mount.h7
4 files changed, 122 insertions, 99 deletions
diff --git a/lib/libc/sys/mount.2 b/lib/libc/sys/mount.2
index 838c1e6..1b551ed 100644
--- a/lib/libc/sys/mount.2
+++ b/lib/libc/sys/mount.2
@@ -32,7 +32,7 @@
.\" @(#)mount.2 8.3 (Berkeley) 5/24/95
.\" $FreeBSD$
.\"
-.Dd June 30, 2003
+.Dd July 1, 2003
.Dt MOUNT 2
.Os
.Sh NAME
@@ -183,6 +183,22 @@ even if files are still active.
Active special devices continue to work,
but any further accesses to any other active files result in errors
even if the file system is later remounted.
+.Pp
+If the
+.Dv MNT_BYFSID
+flag is specified,
+.Fa dir
+should instead be a file system ID encoded as
+.Dq Li FSID : Ns Ar val0 : Ns Ar val1 ,
+where
+.Ar val0
+and
+.Ar val1
+are the contents of the
+.Vt fsid_t
+.Va val[]
+array in decimal.
+The file system that has the specified file system ID will be unmounted.
.Sh RETURN VALUES
.Rv -std
.Sh ERRORS
diff --git a/sbin/umount/umount.c b/sbin/umount/umount.c
index 8ffdbce..19e4400 100644
--- a/sbin/umount/umount.c
+++ b/sbin/umount/umount.c
@@ -54,6 +54,7 @@ static const char rcsid[] =
#include <nfs/rpcv2.h>
#include <err.h>
+#include <errno.h>
#include <fstab.h>
#include <stdio.h>
#include <stdlib.h>
@@ -72,10 +73,10 @@ struct addrinfo *nfshost_ai = NULL;
int fflag, vflag;
char *nfshost;
-void checkmntlist (char *, char **, char **, char **);
+struct statfs *checkmntlist (char *, char **);
int checkvfsname (const char *, char **);
-char *getmntname (const char *, const char *,
- mntwhat, char **, dowhat);
+struct statfs *getmntentry (const char *, const char *, mntwhat, char **,
+ dowhat);
char *getrealname(char *, char *resolved_path);
char **makevfslist (const char *);
size_t mntinfo (struct statfs **);
@@ -83,7 +84,7 @@ int namematch (struct addrinfo *);
int sacmp (struct sockaddr *, struct sockaddr *);
int umountall (char **);
int checkname (char *, char **);
-int umountfs (char *, char *, char *);
+int umountfs (char *, char *, fsid_t *, char *);
void usage (void);
int xdr_dir (XDR *, char *);
@@ -92,8 +93,8 @@ main(int argc, char *argv[])
{
int all, errs, ch, mntsize, error;
char **typelist = NULL, *mntonname, *mntfromname;
- char *type, *mntfromnamerev, *mntonnamerev;
- struct statfs *mntbuf;
+ char *type;
+ struct statfs *mntbuf, *sfsrev;
struct addrinfo hints;
/* Start disks transferring immediately. */
@@ -166,18 +167,16 @@ main(int argc, char *argv[])
*/
mntonname = mntbuf[mntsize].f_mntonname;
mntfromname = mntbuf[mntsize].f_mntfromname;
- mntonnamerev = getmntname(getmntname(mntonname,
- NULL, MNTFROM, &type, NAME), NULL,
- MNTON, &type, NAME);
- mntfromnamerev = getmntname(mntonnamerev,
- NULL, MNTFROM, &type, NAME);
+ sfsrev = getmntentry(mntonname, NULL, MNTON, &type,
+ NAME);
- if (strcmp(mntonnamerev, mntonname) == 0 &&
- strcmp(mntfromnamerev, mntfromname ) != 0)
+ if (!fflag && bcmp(&sfsrev->f_fsid,
+ &mntbuf[mntsize].f_fsid, sizeof(fsid_t)) != 0) {
warnx("cannot umount %s, %s\n "
"is mounted there, umount it first",
- mntonname, mntfromnamerev);
+ mntonname, sfsrev->f_mntfromname);
+ }
if (checkname(mntbuf[mntsize].f_mntonname,
typelist) != 0)
@@ -196,7 +195,7 @@ main(int argc, char *argv[])
errs = 1;
break;
}
- (void)getmntname(NULL, NULL, NOTHING, NULL, FREE);
+ (void)getmntentry(NULL, NULL, NOTHING, NULL, FREE);
exit(errs);
}
@@ -258,29 +257,29 @@ checkname(char *name, char **typelist)
{
size_t len;
int speclen;
- char *mntonname, *mntfromname;
- char *mntfromnamerev;
char *resolved, realname[MAXPATHLEN];
char *type, *hostp, *delimp, *origname;
+ struct statfs *sfs, *sfsrev;
len = 0;
- mntfromname = mntonname = delimp = hostp = NULL;
+ delimp = hostp = NULL;
+ sfs = NULL;
/*
* 1. Check if the name exists in the mounttable.
*/
- (void)checkmntlist(name, &mntfromname, &mntonname, &type);
+ sfs = checkmntlist(name, &type);
/*
* 2. Remove trailing slashes if there are any. After that
* we look up the name in the mounttable again.
*/
- if (mntfromname == NULL && mntonname == NULL) {
+ if (sfs == NULL) {
speclen = strlen(name);
for (speclen = strlen(name);
speclen > 1 && name[speclen - 1] == '/';
speclen--)
name[speclen - 1] = '\0';
- (void)checkmntlist(name, &mntfromname, &mntonname, &type);
+ sfs = checkmntlist(name, &type);
resolved = name;
/* Save off original name in origname */
if ((origname = strdup(name)) == NULL)
@@ -290,7 +289,7 @@ checkname(char *name, char **typelist)
* has been used and translate it to the ':' syntax.
* Look up the name in the mounttable again.
*/
- if (mntfromname == NULL && mntonname == NULL) {
+ if (sfs == NULL) {
if ((delimp = strrchr(name, '@')) != NULL) {
hostp = delimp + 1;
if (*hostp != '\0') {
@@ -313,8 +312,7 @@ checkname(char *name, char **typelist)
speclen--)
name[speclen - 1] = '\0';
name[len + speclen + 1] = '\0';
- (void)checkmntlist(name, &mntfromname,
- &mntonname, &type);
+ sfs = checkmntlist(name, &type);
resolved = name;
}
/*
@@ -325,11 +323,10 @@ checkname(char *name, char **typelist)
* basedir of mountpoint and add the dirname again.
* Check the name in mounttable one last time.
*/
- if (mntfromname == NULL && mntonname == NULL) {
+ if (sfs == NULL) {
(void)strcpy(name, origname);
if ((getrealname(name, realname)) != NULL) {
- (void)checkmntlist(realname,
- &mntfromname, &mntonname, &type);
+ sfs = checkmntlist(realname, &type);
resolved = realname;
}
/*
@@ -343,9 +340,9 @@ checkname(char *name, char **typelist)
* fstat structure get's more reliable,
* but at the moment we cannot thrust it.
*/
- if (mntfromname == NULL && mntonname == NULL) {
+ if (sfs == NULL) {
(void)strcpy(name, origname);
- if (umountfs(NULL, origname,
+ if (umountfs(NULL, origname, NULL,
"none") == 0) {;
warnx("%s not found in "
"mount table, "
@@ -370,38 +367,37 @@ checkname(char *name, char **typelist)
* Check if the reverse entrys of the mounttable are really the
* same as the normal ones.
*/
- if ((mntfromnamerev = strdup(getmntname(getmntname(mntfromname,
- NULL, MNTON, &type, NAME), NULL, MNTFROM, &type, NAME))) == NULL)
- err(1, "strdup");
+ sfsrev = getmntentry(sfs->f_mntonname, NULL, MNTON, &type, NAME);
/*
* Mark the uppermost mount as unmounted.
*/
- (void)getmntname(mntfromname, mntonname, NOTHING, &type, MARK);
+ (void)getmntentry(sfs->f_mntfromname, sfs->f_mntonname, NOTHING, &type,
+ MARK);
/*
* If several equal mounts are in the mounttable, check the order
* and warn the user if necessary.
*/
- if (strcmp(mntfromnamerev, mntfromname ) != 0 &&
- strcmp(resolved, mntonname) != 0) {
+ if (fflag != MNT_FORCE && sfsrev != sfs) {
warnx("cannot umount %s, %s\n "
"is mounted there, umount it first",
- mntonname, mntfromnamerev);
+ sfs->f_mntonname, sfsrev->f_mntfromname);
- /* call getmntname again to set mntcheck[i] to 0 */
- (void)getmntname(mntfromname, mntonname,
+ /* call getmntentry again to set mntcheck[i] to 0 */
+ (void)getmntentry(sfs->f_mntfromname, sfs->f_mntonname,
NOTHING, &type, UNMARK);
return (1);
}
- free(mntfromnamerev);
- return (umountfs(mntfromname, mntonname, type));
+ return (umountfs(sfs->f_mntfromname, sfs->f_mntonname, &sfs->f_fsid,
+ type));
}
/*
* NFS stuff and unmount(2) call
*/
int
-umountfs(char *mntfromname, char *mntonname, char *type)
+umountfs(char *mntfromname, char *mntonname, fsid_t *fsid, char *type)
{
+ char fsidbuf[64];
enum clnt_stat clnt_stat;
struct timeval try;
struct addrinfo *ai, hints;
@@ -439,14 +435,27 @@ umountfs(char *mntfromname, char *mntonname, char *type)
* A non-NULL return means that this is the last
* mount from mntfromname that is still mounted.
*/
- if (getmntname(mntfromname, NULL, NOTHING, &type, COUNT)
- != NULL)
+ if (getmntentry(mntfromname, NULL, NOTHING, &type, COUNT)
+ != NULL)
do_rpc = 1;
}
if (!namematch(ai))
return (1);
- if (unmount(mntonname, fflag) != 0 ) {
+ /* First try to unmount using the specified file system ID. */
+ if (fsid != NULL) {
+ snprintf(fsidbuf, sizeof(fsidbuf), "FSID:%d:%d", fsid->val[0],
+ fsid->val[1]);
+ if (unmount(fsidbuf, fflag | MNT_BYFSID) != 0) {
+ warn("unmount of %s failed", mntonname);
+ if (errno != ENOENT)
+ return (1);
+ /* Compatability for old kernels. */
+ warnx("retrying using path instead of file system ID");
+ fsid = NULL;
+ }
+ }
+ if (fsid == NULL && unmount(mntonname, fflag) != 0) {
warn("unmount of %s failed", mntonname);
return (1);
}
@@ -490,9 +499,9 @@ umountfs(char *mntfromname, char *mntonname, char *type)
return (0);
}
-char *
-getmntname(const char *fromname, const char *onname,
- mntwhat what, char **type, dowhat mark)
+struct statfs *
+getmntentry(const char *fromname, const char *onname, mntwhat what,
+ char **type, dowhat mark)
{
static struct statfs *mntbuf;
static size_t mntsize = 0;
@@ -523,21 +532,15 @@ getmntname(const char *fromname, const char *onname,
case NAME:
/* Return only the specific name */
for (i = mntsize - 1; i >= 0; i--) {
- if (fromname != NULL && what == MNTON &&
- !strcmp(mntbuf[i].f_mntfromname, fromname) &&
- mntcheck[i] != 1) {
+ if (fromname != NULL && !strcmp((what == MNTFROM) ?
+ mntbuf[i].f_mntfromname : mntbuf[i].f_mntonname,
+ fromname) && mntcheck[i] != 1) {
if (type)
*type = mntbuf[i].f_fstypename;
- return (mntbuf[i].f_mntonname);
- }
- if (fromname != NULL && what == MNTFROM &&
- !strcmp(mntbuf[i].f_mntonname, fromname) &&
- mntcheck[i] != 1) {
- if (type)
- *type = mntbuf[i].f_fstypename;
- return (mntbuf[i].f_mntfromname);
+ return (&mntbuf[i]);
}
}
+
return (NULL);
case MARK:
/* Mark current mount with '1' and return name */
@@ -546,7 +549,7 @@ getmntname(const char *fromname, const char *onname,
(strcmp(mntbuf[i].f_mntonname, onname) == 0) &&
(strcmp(mntbuf[i].f_mntfromname, fromname) == 0)) {
mntcheck[i] = 1;
- return (mntbuf[i].f_mntonname);
+ return (&mntbuf[i]);
}
}
return (NULL);
@@ -557,7 +560,7 @@ getmntname(const char *fromname, const char *onname,
(strcmp(mntbuf[i].f_mntonname, onname) == 0) &&
(strcmp(mntbuf[i].f_mntfromname, fromname) == 0)) {
mntcheck[i] = 0;
- return (mntbuf[i].f_mntonname);
+ return (&mntbuf[i]);
}
}
return (NULL);
@@ -582,7 +585,7 @@ getmntname(const char *fromname, const char *onname,
}
}
if (count <= 1)
- return (mntbuf[i].f_mntonname);
+ return (&mntbuf[i]);
else
return (NULL);
case FREE:
@@ -646,17 +649,15 @@ namematch(struct addrinfo *ai)
return (0);
}
-void
-checkmntlist(char *name, char **fromname, char **onname, char **type)
+struct statfs *
+checkmntlist(char *name, char **type)
{
+ struct statfs *sfs;
- *fromname = getmntname(name, NULL, MNTFROM, type, NAME);
- if (*fromname == NULL) {
- *onname = getmntname(name, NULL, MNTON, type, NAME);
- if (*onname != NULL)
- *fromname = name;
- } else
- *onname = name;
+ sfs = getmntentry(name, NULL, MNTON, type, NAME);
+ if (sfs == NULL)
+ sfs = getmntentry(name, NULL, MNTFROM, type, NAME);
+ return (sfs);
}
size_t
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