Add a new "-N" option to umount(8), that does a forced dismount of an NFS mount

point.

The new "-N" option does a forced dismount of an NFS mount point, but avoids
doing any checking of the mounted-on path, so that it will not get hung
when a vnode lock is held by another hung process on the mounted-on vnode.
The most common case of this is a "umount" with the "-f" option.
Other than avoiding checking the mounted-on path, it performs the same
forced dismount as a successful "umount -f" would do.

This commit includes a content change to the man page.

Tested by:	pho
Reviewed by:	kib
MFC after:	2 weeks
Relnotes:	yes
Differential Revision:	https://reviews.freebsd.org/D11735
This commit is contained in:
Rick Macklem 2017-07-29 20:08:25 +00:00
parent 47cbff34fa
commit 4261923e76
2 changed files with 54 additions and 8 deletions

View File

@ -28,7 +28,7 @@
.\" @(#)umount.8 8.2 (Berkeley) 5/8/95
.\" $FreeBSD$
.\"
.Dd September 10, 2016
.Dd July 25, 2017
.Dt UMOUNT 8
.Os
.Sh NAME
@ -36,7 +36,7 @@
.Nd unmount file systems
.Sh SYNOPSIS
.Nm
.Op Fl fnv
.Op Fl fNnv
.Ar special ... | node ... | fsid ...
.Nm
.Fl a | A
@ -81,6 +81,15 @@ The root file system cannot be forcibly unmounted.
For NFS, a forced dismount can take up to 1 minute or more to
complete against an unresponsive server and may throw away
data not yet written to the server for this case.
If a process, such as
.Nm
without the
.Fl f
flag is hung on an
.Tn NFS
mount point, use the
.Fl N
flag instead.
Also, doing a forced dismount of an NFSv3 mount when
.Xr rpc.lockd 8
is running is unsafe and can result in a crash.
@ -94,6 +103,24 @@ option and, unless otherwise specified with the
option, will only unmount
.Tn NFS
file systems.
.It Fl N
Do a forced dismount of an
.Tn NFS
mount point without checking the mount path.
This option can only be used with the path to the mount point
.Ar node
and the path must be specified exactly as it was at mount time.
This option is useful when a process is hung waiting for an unresponsive
.Tn NFS
server while holding a vnode lock on the mounted-on vnode, such that
.Nm
with the
.Fl f
flag can't complete.
Using this option can result in a loss of file updates that have not been
flushed to the
.Tn NFS
server.
.It Fl n
Unless the
.Fl f

View File

@ -86,13 +86,13 @@ int xdr_dir (XDR *, char *);
int
main(int argc, char *argv[])
{
int all, errs, ch, mntsize, error;
int all, errs, ch, mntsize, error, nfsforce, ret;
char **typelist = NULL;
struct statfs *mntbuf, *sfs;
struct addrinfo hints;
all = errs = 0;
while ((ch = getopt(argc, argv, "AaF:fh:nt:v")) != -1)
nfsforce = all = errs = 0;
while ((ch = getopt(argc, argv, "AaF:fh:Nnt:v")) != -1)
switch (ch) {
case 'A':
all = 2;
@ -110,6 +110,9 @@ main(int argc, char *argv[])
all = 2;
nfshost = optarg;
break;
case 'N':
nfsforce = 1;
break;
case 'n':
fflag |= MNT_NONBUSY;
break;
@ -132,12 +135,15 @@ main(int argc, char *argv[])
err(1, "-f and -n are mutually exclusive");
/* Start disks transferring immediately. */
if ((fflag & (MNT_FORCE | MNT_NONBUSY)) == 0)
if ((fflag & (MNT_FORCE | MNT_NONBUSY)) == 0 && nfsforce == 0)
sync();
if ((argc == 0 && !all) || (argc != 0 && all))
usage();
if (nfsforce != 0 && (argc == 0 || nfshost != NULL || typelist != NULL))
usage();
/* -h implies "-t nfs" if no -t flag. */
if ((nfshost != NULL) && (typelist == NULL))
typelist = makevfslist("nfs");
@ -175,7 +181,20 @@ main(int argc, char *argv[])
break;
case 0:
for (errs = 0; *argv != NULL; ++argv)
if (checkname(*argv, typelist) != 0)
if (nfsforce != 0) {
/*
* First do the nfssvc() syscall to shut down
* the mount point and then do the forced
* dismount.
*/
ret = nfssvc(NFSSVC_FORCEDISM, *argv);
if (ret >= 0)
ret = unmount(*argv, MNT_FORCE);
if (ret < 0) {
warn("%s", *argv);
errs = 1;
}
} else if (checkname(*argv, typelist) != 0)
errs = 1;
break;
}
@ -635,7 +654,7 @@ usage(void)
{
(void)fprintf(stderr, "%s\n%s\n",
"usage: umount [-fnv] special ... | node ... | fsid ...",
"usage: umount [-fNnv] special ... | node ... | fsid ...",
" umount -a | -A [-F fstab] [-fnv] [-h host] [-t type]");
exit(1);
}