Index: sys/sys/mount.h =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/sys/mount.h,v retrieving revision 1.147 diff -u -r1.147 mount.h --- sys/sys/mount.h 26 Mar 2003 22:15:58 -0000 1.147 +++ sys/sys/mount.h 1 Apr 2003 12:32:39 -0000 @@ -224,12 +224,9 @@ #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. * Index: sys/kern/vfs_mount.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/kern/vfs_mount.c,v retrieving revision 1.106 diff -u -r1.106 vfs_mount.c --- sys/kern/vfs_mount.c 24 Apr 2003 08:16:06 -0000 1.106 +++ sys/kern/vfs_mount.c 10 May 2003 03:47:58 -0000 @@ -1223,17 +1223,42 @@ int flags; } */ *uap; { - register struct vnode *vp; + fsid_t fsid; struct mount *mp; + char *p1, *p2, *pathbuf; int error; - struct nameidata nd; - 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 "%d %d" filesystem ID. */ + fsid.val[0] = strtol(pathbuf, &p1, 0); + fsid.val[1] = strtol(p1, &p2, 0); + if (*p1 != ' ' || *p2 != '\0' || p1 == pathbuf || p1 == p2) { + free(pathbuf, M_TEMP); + return (EINVAL); + } + + mtx_lock(&mountlist_mtx); + TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) + if (bcmp(&mp->mnt_stat.f_fsid, &fsid, + sizeof(fsid)) == 0) + 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 @@ -1241,28 +1266,17 @@ */ if (mp->mnt_cred->cr_uid != td->td_ucred->cr_uid) { error = suser(td); - if (error) { - vput(vp); + if (error) return (error); - } } +#if 0 /* * Don't allow unmounting the root filesystem. */ - if (mp->mnt_flag & MNT_ROOTFS) { - vput(vp); - return (EINVAL); - } - - /* - * Must be the root of the filesystem - */ - if ((vp->v_vflag & VV_ROOT) == 0) { - vput(vp); + if (mp->mnt_flag & MNT_ROOTFS) return (EINVAL); - } - vput(vp); +#endif return (dounmount(mp, uap->flags, td)); } Index: sbin/umount/umount.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sbin/umount/umount.c,v retrieving revision 1.34 diff -u -r1.34 umount.c --- sbin/umount/umount.c 7 Apr 2003 12:56:01 -0000 1.34 +++ sbin/umount/umount.c 18 May 2003 02:56:48 -0000 @@ -54,6 +54,7 @@ #include #include +#include #include #include #include @@ -72,10 +73,10 @@ 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 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 @@ { 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 @@ */ 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 @@ errs = 1; break; } - (void)getmntname(NULL, NULL, NOTHING, NULL, FREE); + (void)getmntentry(NULL, NULL, NOTHING, NULL, FREE); exit(errs); } @@ -258,29 +257,29 @@ { 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 @@ * 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 @@ 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 @@ * 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 @@ * 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 @@ * 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 @@ * 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 filesystem ID. */ + if (fsid != NULL) { + snprintf(fsidbuf, sizeof(fsidbuf), "%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 filesystem ID"); + fsid = NULL; + } + } + if (fsid == NULL && unmount(mntonname, fflag) != 0) { warn("unmount of %s failed", mntonname); return (1); } @@ -490,9 +499,9 @@ 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 @@ 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 @@ (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 @@ (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 @@ } } if (count <= 1) - return (mntbuf[i].f_mntonname); + return (&mntbuf[i]); else return (NULL); case FREE: @@ -646,17 +649,15 @@ 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