aboutsummaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
Diffstat (limited to 'sbin')
-rw-r--r--sbin/umount/umount.831
-rw-r--r--sbin/umount/umount.c31
2 files changed, 54 insertions, 8 deletions
diff --git a/sbin/umount/umount.8 b/sbin/umount/umount.8
index 8288c1a7da7a..5543820ce185 100644
--- a/sbin/umount/umount.8
+++ b/sbin/umount/umount.8
@@ -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
diff --git a/sbin/umount/umount.c b/sbin/umount/umount.c
index bc7dbcd02d61..f2829a4f9429 100644
--- a/sbin/umount/umount.c
+++ b/sbin/umount/umount.c
@@ -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);
}