Add new unmount(2) flag, MNT_NONBUSY, to check whether there are
any open vnodes before proceeding. Make autounmound(8) use this flag. Without it, even an unsuccessfull unmount causes filesystem flush, which interferes with normal operation. Reviewed by: kib@ Approved by: re (gjb@) MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D7047
This commit is contained in:
parent
af625dc998
commit
debc480e03
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=302388
@ -28,7 +28,7 @@
|
|||||||
.\" @(#)umount.8 8.2 (Berkeley) 5/8/95
|
.\" @(#)umount.8 8.2 (Berkeley) 5/8/95
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd June 17, 2015
|
.Dd July 7, 2016
|
||||||
.Dt UMOUNT 8
|
.Dt UMOUNT 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -36,12 +36,12 @@
|
|||||||
.Nd unmount file systems
|
.Nd unmount file systems
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl fv
|
.Op Fl fnv
|
||||||
.Ar special ... | node ... | fsid ...
|
.Ar special ... | node ... | fsid ...
|
||||||
.Nm
|
.Nm
|
||||||
.Fl a | A
|
.Fl a | A
|
||||||
.Op Fl F Ar fstab
|
.Op Fl F Ar fstab
|
||||||
.Op Fl fv
|
.Op Fl fnv
|
||||||
.Op Fl h Ar host
|
.Op Fl h Ar host
|
||||||
.Op Fl t Ar type
|
.Op Fl t Ar type
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
@ -94,6 +94,15 @@ option and, unless otherwise specified with the
|
|||||||
option, will only unmount
|
option, will only unmount
|
||||||
.Tn NFS
|
.Tn NFS
|
||||||
file systems.
|
file systems.
|
||||||
|
.It Fl n
|
||||||
|
Unless the
|
||||||
|
.Fl f
|
||||||
|
is used, the
|
||||||
|
.Nm
|
||||||
|
will not unmount an active file system.
|
||||||
|
It will, however, perform a flush.
|
||||||
|
This flag disables this behaviour, preventing the flush
|
||||||
|
if there are any files open.
|
||||||
.It Fl t Ar type
|
.It Fl t Ar type
|
||||||
Is used to indicate the actions should only be taken on
|
Is used to indicate the actions should only be taken on
|
||||||
file systems of the specified type.
|
file systems of the specified type.
|
||||||
|
@ -91,7 +91,7 @@ main(int argc, char *argv[])
|
|||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
|
|
||||||
all = errs = 0;
|
all = errs = 0;
|
||||||
while ((ch = getopt(argc, argv, "AaF:fh:t:v")) != -1)
|
while ((ch = getopt(argc, argv, "AaF:fh:nt:v")) != -1)
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'A':
|
case 'A':
|
||||||
all = 2;
|
all = 2;
|
||||||
@ -103,12 +103,15 @@ main(int argc, char *argv[])
|
|||||||
setfstab(optarg);
|
setfstab(optarg);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
fflag = MNT_FORCE;
|
fflag |= MNT_FORCE;
|
||||||
break;
|
break;
|
||||||
case 'h': /* -h implies -A. */
|
case 'h': /* -h implies -A. */
|
||||||
all = 2;
|
all = 2;
|
||||||
nfshost = optarg;
|
nfshost = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'n':
|
||||||
|
fflag |= MNT_NONBUSY;
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
if (typelist != NULL)
|
if (typelist != NULL)
|
||||||
err(1, "only one -t option may be specified");
|
err(1, "only one -t option may be specified");
|
||||||
@ -124,8 +127,11 @@ main(int argc, char *argv[])
|
|||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
|
if ((fflag & MNT_FORCE) != 0 && (fflag & MNT_NONBUSY) != 0)
|
||||||
|
err(1, "-f and -n are mutually exclusive");
|
||||||
|
|
||||||
/* Start disks transferring immediately. */
|
/* Start disks transferring immediately. */
|
||||||
if ((fflag & MNT_FORCE) == 0)
|
if ((fflag & (MNT_FORCE | MNT_NONBUSY)) == 0)
|
||||||
sync();
|
sync();
|
||||||
|
|
||||||
if ((argc == 0 && !all) || (argc != 0 && all))
|
if ((argc == 0 && !all) || (argc != 0 && all))
|
||||||
@ -609,7 +615,7 @@ usage(void)
|
|||||||
{
|
{
|
||||||
|
|
||||||
(void)fprintf(stderr, "%s\n%s\n",
|
(void)fprintf(stderr, "%s\n%s\n",
|
||||||
"usage: umount [-fv] special ... | node ... | fsid ...",
|
"usage: umount [-fnv] special ... | node ... | fsid ...",
|
||||||
" umount -a | -A [-F fstab] [-fv] [-h host] [-t type]");
|
" umount -a | -A [-F fstab] [-fnv] [-h host] [-t type]");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -1204,6 +1204,28 @@ sys_unmount(struct thread *td, struct unmount_args *uap)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return error if any of the vnodes, ignoring the root vnode
|
||||||
|
* and the syncer vnode, have non-zero usecount.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
vfs_check_usecounts(struct mount *mp)
|
||||||
|
{
|
||||||
|
struct vnode *vp, *mvp;
|
||||||
|
|
||||||
|
MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
|
||||||
|
if ((vp->v_vflag & VV_ROOT) == 0 && vp->v_type != VNON &&
|
||||||
|
vp->v_usecount != 0) {
|
||||||
|
VI_UNLOCK(vp);
|
||||||
|
MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
|
||||||
|
return (EBUSY);
|
||||||
|
}
|
||||||
|
VI_UNLOCK(vp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the actual filesystem unmount.
|
* Do the actual filesystem unmount.
|
||||||
*/
|
*/
|
||||||
@ -1260,6 +1282,21 @@ dounmount(struct mount *mp, int flags, struct thread *td)
|
|||||||
return (EBUSY);
|
return (EBUSY);
|
||||||
}
|
}
|
||||||
mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_NOINSMNTQ;
|
mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_NOINSMNTQ;
|
||||||
|
if (flags & MNT_NONBUSY) {
|
||||||
|
MNT_IUNLOCK(mp);
|
||||||
|
error = vfs_check_usecounts(mp);
|
||||||
|
MNT_ILOCK(mp);
|
||||||
|
if (error != 0) {
|
||||||
|
mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_NOINSMNTQ);
|
||||||
|
MNT_IUNLOCK(mp);
|
||||||
|
if (coveredvp != NULL) {
|
||||||
|
VOP_UNLOCK(coveredvp, 0);
|
||||||
|
vdrop(coveredvp);
|
||||||
|
}
|
||||||
|
vn_finished_write(mp);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Allow filesystems to detect that a forced unmount is in progress. */
|
/* Allow filesystems to detect that a forced unmount is in progress. */
|
||||||
if (flags & MNT_FORCE) {
|
if (flags & MNT_FORCE) {
|
||||||
mp->mnt_kern_flag |= MNTK_UNMOUNTF;
|
mp->mnt_kern_flag |= MNTK_UNMOUNTF;
|
||||||
|
@ -312,17 +312,21 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *);
|
|||||||
* External filesystem command modifier flags.
|
* External filesystem command modifier flags.
|
||||||
* Unmount can use the MNT_FORCE flag.
|
* Unmount can use the MNT_FORCE flag.
|
||||||
* XXX: These are not STATES and really should be somewhere else.
|
* XXX: These are not STATES and really should be somewhere else.
|
||||||
* XXX: MNT_BYFSID collides with MNT_ACLS, but because MNT_ACLS is only used for
|
* XXX: MNT_BYFSID and MNT_NONBUSY collide with MNT_ACLS and MNT_MULTILABEL,
|
||||||
* mount(2) and MNT_BYFSID is only used for unmount(2) it's harmless.
|
* but because MNT_ACLS and MNT_MULTILABEL are only used for mount(2),
|
||||||
|
* and MNT_BYFSID and MNT_NONBUSY are only used for unmount(2),
|
||||||
|
* it's harmless.
|
||||||
*/
|
*/
|
||||||
#define MNT_UPDATE 0x0000000000010000ULL /* not real mount, just update */
|
#define MNT_UPDATE 0x0000000000010000ULL /* not real mount, just update */
|
||||||
#define MNT_DELEXPORT 0x0000000000020000ULL /* delete export host lists */
|
#define MNT_DELEXPORT 0x0000000000020000ULL /* delete export host lists */
|
||||||
#define MNT_RELOAD 0x0000000000040000ULL /* reload filesystem data */
|
#define MNT_RELOAD 0x0000000000040000ULL /* reload filesystem data */
|
||||||
#define MNT_FORCE 0x0000000000080000ULL /* force unmount or readonly */
|
#define MNT_FORCE 0x0000000000080000ULL /* force unmount or readonly */
|
||||||
#define MNT_SNAPSHOT 0x0000000001000000ULL /* snapshot the filesystem */
|
#define MNT_SNAPSHOT 0x0000000001000000ULL /* snapshot the filesystem */
|
||||||
|
#define MNT_NONBUSY 0x0000000004000000ULL /* check vnode use counts. */
|
||||||
#define MNT_BYFSID 0x0000000008000000ULL /* specify filesystem by ID. */
|
#define MNT_BYFSID 0x0000000008000000ULL /* specify filesystem by ID. */
|
||||||
#define MNT_CMDFLAGS (MNT_UPDATE | MNT_DELEXPORT | MNT_RELOAD | \
|
#define MNT_CMDFLAGS (MNT_UPDATE | MNT_DELEXPORT | MNT_RELOAD | \
|
||||||
MNT_FORCE | MNT_SNAPSHOT | MNT_BYFSID)
|
MNT_FORCE | MNT_SNAPSHOT | MNT_NONBUSY | \
|
||||||
|
MNT_BYFSID)
|
||||||
/*
|
/*
|
||||||
* Internal filesystem control flags stored in mnt_kern_flag.
|
* Internal filesystem control flags stored in mnt_kern_flag.
|
||||||
*
|
*
|
||||||
|
@ -161,7 +161,7 @@ unmount_by_fsid(const fsid_t fsid, const char *mountpoint)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
log_err(1, "asprintf");
|
log_err(1, "asprintf");
|
||||||
|
|
||||||
error = unmount(fsid_str, MNT_BYFSID);
|
error = unmount(fsid_str, MNT_NONBUSY | MNT_BYFSID);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
if (errno == EBUSY) {
|
if (errno == EBUSY) {
|
||||||
log_debugx("cannot unmount %s (%s): %s",
|
log_debugx("cannot unmount %s (%s): %s",
|
||||||
|
Loading…
Reference in New Issue
Block a user