[pve-devel] [PATCH zfsonlinux 1/2] Cherry-pick fix for deadlock umount/snapentry_expire

Stoiko Ivanov s.ivanov at proxmox.com
Fri Aug 3 11:51:15 CEST 2018


Signed-off-by: Stoiko Ivanov <s.ivanov at proxmox.com>
---
 ...dlock-between-zfs-umount-snapentry_expire.patch | 59 ++++++++++++++++++++++
 zfs-patches/series                                 |  1 +
 2 files changed, 60 insertions(+)
 create mode 100644 zfs-patches/0005-Fix-deadlock-between-zfs-umount-snapentry_expire.patch

diff --git a/zfs-patches/0005-Fix-deadlock-between-zfs-umount-snapentry_expire.patch b/zfs-patches/0005-Fix-deadlock-between-zfs-umount-snapentry_expire.patch
new file mode 100644
index 0000000..5c090d3
--- /dev/null
+++ b/zfs-patches/0005-Fix-deadlock-between-zfs-umount-snapentry_expire.patch
@@ -0,0 +1,59 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Rohan Puri <rohan.puri15 at gmail.com>
+Date: Sat, 28 Jul 2018 18:32:12 +0530
+Subject: [PATCH] Fix deadlock between zfs umount & snapentry_expire
+
+zfs umount -> zfsctl_destroy() takes the zfs_snapshot_lock as a
+writer and calls zfsctl_snapshot_unmount_cancel(), which waits
+for snapentry_expire() if present (when snap is automounted).
+This snapentry_expire() itself then waits for zfs_snapshot_lock
+as a reader, resulting in a deadlock.
+
+The fix is to only hold the zfs_snapshot_lock over the tree
+lookup and removal.  After a successful lookup the lock can
+be dropped and zfs_snapentry_t will remain valid until the
+reference taken by the lookup is released.
+
+Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
+Signed-off-by: Rohan Puri <rohan.puri15 at gmail.com>
+Closes #7751
+Closes #7752
+
+(Cherry-picked from fd7265c646f40e364396af5014bbb83e809e124a)
+Signed-off-by: Stoiko Ivanov <s.ivanov at proxmox.com>
+---
+ module/zfs/zfs_ctldir.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/module/zfs/zfs_ctldir.c b/module/zfs/zfs_ctldir.c
+index 3b5fb196..14af55c4 100644
+--- a/module/zfs/zfs_ctldir.c
++++ b/module/zfs/zfs_ctldir.c
+@@ -358,8 +358,6 @@ snapentry_expire(void *data)
+ static void
+ zfsctl_snapshot_unmount_cancel(zfs_snapentry_t *se)
+ {
+-	ASSERT(RW_LOCK_HELD(&zfs_snapshot_lock));
+-
+ 	if (taskq_cancel_id(system_delay_taskq, se->se_taskqid) == 0) {
+ 		se->se_taskqid = TASKQID_INVALID;
+ 		zfsctl_snapshot_rele(se);
+@@ -570,13 +568,14 @@ zfsctl_destroy(zfsvfs_t *zfsvfs)
+ 		uint64_t objsetid = dmu_objset_id(zfsvfs->z_os);
+ 
+ 		rw_enter(&zfs_snapshot_lock, RW_WRITER);
+-		if ((se = zfsctl_snapshot_find_by_objsetid(spa, objsetid))
+-		    != NULL) {
+-			zfsctl_snapshot_unmount_cancel(se);
++		se = zfsctl_snapshot_find_by_objsetid(spa, objsetid);
++		if (se != NULL)
+ 			zfsctl_snapshot_remove(se);
++		rw_exit(&zfs_snapshot_lock);
++		if (se != NULL) {
++			zfsctl_snapshot_unmount_cancel(se);
+ 			zfsctl_snapshot_rele(se);
+ 		}
+-		rw_exit(&zfs_snapshot_lock);
+ 	} else if (zfsvfs->z_ctldir) {
+ 		iput(zfsvfs->z_ctldir);
+ 		zfsvfs->z_ctldir = NULL;
diff --git a/zfs-patches/series b/zfs-patches/series
index 815e5cd..5d154db 100644
--- a/zfs-patches/series
+++ b/zfs-patches/series
@@ -2,3 +2,4 @@
 0002-import-with-d-dev-disk-by-id-in-scan-service.patch
 0003-always-load-ZFS-module-on-boot.patch
 0004-Fix-zpl_mount-deadlock.patch
+0005-Fix-deadlock-between-zfs-umount-snapentry_expire.patch
-- 
2.11.0





More information about the pve-devel mailing list