Cherry-pick fix for deadlock umount/snapentry_expire
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
This commit is contained in:
parent
afa7541760
commit
76a4c29ab5
@ -0,0 +1,59 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rohan Puri <rohan.puri15@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@llnl.gov>
|
||||||
|
Signed-off-by: Rohan Puri <rohan.puri15@gmail.com>
|
||||||
|
Closes #7751
|
||||||
|
Closes #7752
|
||||||
|
|
||||||
|
(Cherry-picked from fd7265c646f40e364396af5014bbb83e809e124a)
|
||||||
|
Signed-off-by: Stoiko Ivanov <s.ivanov@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;
|
@ -2,3 +2,4 @@
|
|||||||
0002-import-with-d-dev-disk-by-id-in-scan-service.patch
|
0002-import-with-d-dev-disk-by-id-in-scan-service.patch
|
||||||
0003-always-load-ZFS-module-on-boot.patch
|
0003-always-load-ZFS-module-on-boot.patch
|
||||||
0004-Fix-zpl_mount-deadlock.patch
|
0004-Fix-zpl_mount-deadlock.patch
|
||||||
|
0005-Fix-deadlock-between-zfs-umount-snapentry_expire.patch
|
||||||
|
Loading…
Reference in New Issue
Block a user