Author: rmacklem
Date: Sat Jul 29 20:08:25 2017
New Revision: 321689
URL: https://svnweb.freebsd.org/changeset/base/321689

Log:
  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

Modified:
  head/sbin/umount/umount.8
  head/sbin/umount/umount.c

Modified: head/sbin/umount/umount.8
==============================================================================
--- head/sbin/umount/umount.8   Sat Jul 29 19:52:47 2017        (r321688)
+++ head/sbin/umount/umount.8   Sat Jul 29 20:08:25 2017        (r321689)
@@ -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

Modified: head/sbin/umount/umount.c
==============================================================================
--- head/sbin/umount/umount.c   Sat Jul 29 19:52:47 2017        (r321688)
+++ head/sbin/umount/umount.c   Sat Jul 29 20:08:25 2017        (r321689)
@@ -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);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to