aboutsummaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authoryouzhongyang <[email protected]>2020-08-24 20:33:02 -0400
committerGitHub <[email protected]>2020-08-24 17:33:02 -0700
commitb9007997682fac4a4272f2d59fc3df4875db2df0 (patch)
treec21d07b52101b9bf019d87b452e1aee24516c40c /module
parent184df27eef0abdc7ab2105b21257f753834b936b (diff)
Fix inability to destroy snapshot used over NFS
The cache of struct svc_export and struct svc_expkey by nfsd and rpc.mountd for the snapshot holds references to the mount point. We need to flush them out before unmounting, otherwise umount would fail with EBUSY. Reviewed-by: Don Brady <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Youzhong Yang <[email protected]> Closes #6000 Closes #10783
Diffstat (limited to 'module')
-rw-r--r--module/os/linux/zfs/zfs_ctldir.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/module/os/linux/zfs/zfs_ctldir.c b/module/os/linux/zfs/zfs_ctldir.c
index c2748ce45..26e785a0d 100644
--- a/module/os/linux/zfs/zfs_ctldir.c
+++ b/module/os/linux/zfs/zfs_ctldir.c
@@ -31,6 +31,7 @@
* Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
* Copyright (c) 2018 George Melikov. All Rights Reserved.
* Copyright (c) 2019 Datto, Inc. All rights reserved.
+ * Copyright (c) 2020 The MathWorks, Inc. All rights reserved.
*/
/*
@@ -978,6 +979,22 @@ out:
}
/*
+ * Flush everything out of the kernel's export table and such.
+ * This is needed as once the snapshot is used over NFS, its
+ * entries in svc_export and svc_expkey caches hold reference
+ * to the snapshot mount point. There is no known way of flushing
+ * only the entries related to the snapshot.
+ */
+static void
+exportfs_flush(void)
+{
+ char *argv[] = { "/usr/sbin/exportfs", "-f", NULL };
+ char *envp[] = { NULL };
+
+ (void) call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
+}
+
+/*
* Attempt to unmount a snapshot by making a call to user space.
* There is no assurance that this can or will succeed, is just a
* best effort. In the case where it does fail, perhaps because
@@ -999,6 +1016,8 @@ zfsctl_snapshot_unmount(char *snapname, int flags)
}
rw_exit(&zfs_snapshot_lock);
+ exportfs_flush();
+
if (flags & MNT_FORCE)
argv[4] = "-fn";
argv[5] = se->se_path;