Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144391088
D11735.id31279.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D11735.id31279.diff
View Options
Index: sbin/umount/umount.8
===================================================================
--- sbin/umount/umount.8
+++ sbin/umount/umount.8
@@ -28,7 +28,7 @@
.\" @(#)umount.8 8.2 (Berkeley) 5/8/95
.\" $FreeBSD: head/sbin/umount/umount.8 314436 2017-02-28 23:42:47Z imp $
.\"
-.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,17 @@
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
+.Xr df 1
+or
+.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 +105,20 @@
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.
.It Fl n
Unless the
.Fl f
Index: sbin/umount/umount.c
===================================================================
--- sbin/umount/umount.c
+++ sbin/umount/umount.c
@@ -86,13 +86,13 @@
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 @@
all = 2;
nfshost = optarg;
break;
+ case 'N':
+ nfsforce = 1;
+ break;
case 'n':
fflag |= MNT_NONBUSY;
break;
@@ -138,6 +141,9 @@
if ((argc == 0 && !all) || (argc != 0 && all))
usage();
+ if (argc == 0 && nfsforce != 0)
+ usage();
+
/* -h implies "-t nfs" if no -t flag. */
if ((nfshost != NULL) && (typelist == NULL))
typelist = makevfslist("nfs");
@@ -175,7 +181,20 @@
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 @@
{
(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);
}
Index: sys/fs/nfs/nfscl.h
===================================================================
--- sys/fs/nfs/nfscl.h
+++ sys/fs/nfs/nfscl.h
@@ -60,7 +60,8 @@
#define NFSCL_LEASE(r) ((r) * 2)
/* This macro checks to see if a forced dismount is about to occur. */
-#define NFSCL_FORCEDISM(m) (((m)->mnt_kern_flag & MNTK_UNMOUNTF) != 0)
+#define NFSCL_FORCEDISM(m) (((m)->mnt_kern_flag & MNTK_UNMOUNTF) != 0 || \
+ (VFSTONFS(m)->nm_privflag & NFSMNTP_FORCEDISM) != 0)
/*
* These flag bits are used for the argument to nfscl_fillsattr() to
Index: sys/fs/nfsclient/nfs_clport.c
===================================================================
--- sys/fs/nfsclient/nfs_clport.c
+++ sys/fs/nfsclient/nfs_clport.c
@@ -1311,6 +1311,8 @@
cap_rights_t rights;
char *buf;
int error;
+ struct mount *mp;
+ struct nfsmount *nmp;
if (uap->flag & NFSSVC_CBADDSOCK) {
error = copyin(uap->argp, (caddr_t)&nfscbdarg, sizeof(nfscbdarg));
@@ -1365,6 +1367,56 @@
dumpmntopts.ndmnt_blen);
free(buf, M_TEMP);
}
+ } else if (uap->flag & NFSSVC_FORCEDISM) {
+ buf = malloc(MNAMELEN + 1, M_TEMP, M_WAITOK);
+ error = copyinstr(uap->argp, buf, MNAMELEN + 1, NULL);
+ if (error == 0) {
+ nmp = NULL;
+ mtx_lock(&mountlist_mtx);
+ TAILQ_FOREACH(mp, &mountlist, mnt_list) {
+ if (strcmp(mp->mnt_stat.f_mntonname, buf) ==
+ 0 && strcmp(mp->mnt_stat.f_fstypename,
+ "nfs") == 0 && mp->mnt_data != NULL) {
+ nmp = VFSTONFS(mp);
+ mtx_lock(&nmp->nm_mtx);
+ if ((nmp->nm_privflag &
+ NFSMNTP_FORCEDISM) == 0) {
+ nmp->nm_privflag |=
+ (NFSMNTP_FORCEDISM |
+ NFSMNTP_CANCELRPCS);
+ mtx_unlock(&nmp->nm_mtx);
+ } else {
+ nmp = NULL;
+ mtx_unlock(&nmp->nm_mtx);
+ }
+ break;
+ }
+ }
+ mtx_unlock(&mountlist_mtx);
+
+ if (nmp != NULL) {
+ /*
+ * Call newnfs_nmcancelreqs() to cause
+ * any RPCs in progress on the mount point to
+ * fail.
+ * This will cause any process waiting for an
+ * RPC to complete while holding a vnode lock
+ * on the mounted-on vnode (such as "df" or
+ * a non-forced "umount") to fail.
+ * This will unlock the mounted-on vnode so
+ * a forced dismount can succeed.
+ * Then clear NFSMNTP_CANCELRPCS and wakeup(),
+ * so that nfs_unmount() can complete.
+ */
+ newnfs_nmcancelreqs(nmp);
+ mtx_lock(&nmp->nm_mtx);
+ nmp->nm_privflag &= ~NFSMNTP_CANCELRPCS;
+ wakeup(nmp);
+ mtx_unlock(&nmp->nm_mtx);
+ } else
+ error = EINVAL;
+ }
+ free(buf, M_TEMP);
} else {
error = EINVAL;
}
Index: sys/fs/nfsclient/nfs_clvfsops.c
===================================================================
--- sys/fs/nfsclient/nfs_clvfsops.c
+++ sys/fs/nfsclient/nfs_clvfsops.c
@@ -1698,6 +1698,11 @@
*/
if ((mntflags & MNT_FORCE) == 0)
nfscl_umount(nmp, td);
+ else {
+ mtx_lock(&nmp->nm_mtx);
+ nmp->nm_privflag |= NFSMNTP_FORCEDISM;
+ mtx_unlock(&nmp->nm_mtx);
+ }
/* Make sure no nfsiods are assigned to this mount. */
mtx_lock(&ncl_iod_mutex);
for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
@@ -1706,6 +1711,19 @@
ncl_iodmount[i] = NULL;
}
mtx_unlock(&ncl_iod_mutex);
+
+ /*
+ * We can now set mnt_data to NULL and wait for
+ * nfssvc(NFSSVC_FORCEDISM) to complete.
+ */
+ mtx_lock(&mountlist_mtx);
+ mtx_lock(&nmp->nm_mtx);
+ mp->mnt_data = NULL;
+ mtx_unlock(&mountlist_mtx);
+ while ((nmp->nm_privflag & NFSMNTP_CANCELRPCS) != 0)
+ msleep(nmp, &nmp->nm_mtx, PVFS, "nfsfdism", 0);
+ mtx_unlock(&nmp->nm_mtx);
+
newnfs_disconnect(&nmp->nm_sockreq);
crfree(nmp->nm_sockreq.nr_cred);
FREE(nmp->nm_nam, M_SONAME);
Index: sys/fs/nfsclient/nfsmount.h
===================================================================
--- sys/fs/nfsclient/nfsmount.h
+++ sys/fs/nfsclient/nfsmount.h
@@ -44,6 +44,7 @@
*/
struct nfsmount {
struct nfsmount_common nm_com; /* Common fields for nlm */
+ uint32_t nm_privflag; /* Private flags */
int nm_numgrps; /* Max. size of groupslist */
u_char nm_fh[NFSX_FHMAX]; /* File handle of root dir */
int nm_fhsize; /* Size of root file handle */
@@ -99,6 +100,10 @@
#define nm_getinfo nm_com.nmcom_getinfo
#define nm_vinvalbuf nm_com.nmcom_vinvalbuf
+/* Private flags. */
+#define NFSMNTP_FORCEDISM 0x00000001
+#define NFSMNTP_CANCELRPCS 0x00000002
+
#define NFSMNT_DIRPATH(m) (&((m)->nm_name[(m)->nm_krbnamelen + 1]))
#define NFSMNT_SRVKRBNAME(m) \
(&((m)->nm_name[(m)->nm_krbnamelen + (m)->nm_dirpathlen + 2]))
Index: sys/nfs/nfs_nfssvc.c
===================================================================
--- sys/nfs/nfs_nfssvc.c
+++ sys/nfs/nfs_nfssvc.c
@@ -92,7 +92,7 @@
nfsd_call_nfsserver != NULL)
error = (*nfsd_call_nfsserver)(td, uap);
else if ((uap->flag & (NFSSVC_CBADDSOCK | NFSSVC_NFSCBD |
- NFSSVC_DUMPMNTOPTS)) && nfsd_call_nfscl != NULL)
+ NFSSVC_DUMPMNTOPTS | NFSSVC_FORCEDISM)) && nfsd_call_nfscl != NULL)
error = (*nfsd_call_nfscl)(td, uap);
else if ((uap->flag & (NFSSVC_IDNAME | NFSSVC_GETSTATS |
NFSSVC_GSSDADDPORT | NFSSVC_GSSDADDFIRST | NFSSVC_GSSDDELETEALL |
Index: sys/nfs/nfssvc.h
===================================================================
--- sys/nfs/nfssvc.h
+++ sys/nfs/nfssvc.h
@@ -70,6 +70,7 @@
#define NFSSVC_RESUMENFSD 0x08000000
#define NFSSVC_DUMPMNTOPTS 0x10000000
#define NFSSVC_NEWSTRUCT 0x20000000
+#define NFSSVC_FORCEDISM 0x40000000
/* Argument structure for NFSSVC_DUMPMNTOPTS. */
struct nfscl_dumpmntopts {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 5:03 AM (20 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28540220
Default Alt Text
D11735.id31279.diff (8 KB)
Attached To
Mode
D11735: Add an NFS forced dismount option to umount(8)
Attached
Detach File
Event Timeline
Log In to Comment