a010b40938
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
125 lines
3.7 KiB
Diff
125 lines
3.7 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Boris Protopopov <bprotopopov@users.noreply.github.com>
|
|
Date: Wed, 9 Aug 2017 14:10:47 -0400
|
|
Subject: [PATCH] zv_suspend_lock in zvol_open()/zvol_release()
|
|
|
|
Acquire zv_suspend_lock on first open and last close only.
|
|
|
|
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
|
|
Signed-off-by: Boris Protopopov <boris.protopopov@actifio.com>
|
|
Closes #6342
|
|
|
|
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
|
|
---
|
|
module/zfs/zvol.c | 64 +++++++++++++++++++++++++++++++++++--------------------
|
|
1 file changed, 41 insertions(+), 23 deletions(-)
|
|
|
|
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
|
|
index 3e7059b3..ffa5fac7 100644
|
|
--- a/module/zfs/zvol.c
|
|
+++ b/module/zfs/zvol.c
|
|
@@ -1347,9 +1347,9 @@ zvol_open(struct block_device *bdev, fmode_t flag)
|
|
{
|
|
zvol_state_t *zv;
|
|
int error = 0;
|
|
- boolean_t drop_suspend = B_FALSE;
|
|
+ boolean_t drop_suspend = B_TRUE;
|
|
|
|
- ASSERT(!mutex_owned(&zvol_state_lock));
|
|
+ ASSERT(!MUTEX_HELD(&zvol_state_lock));
|
|
|
|
mutex_enter(&zvol_state_lock);
|
|
/*
|
|
@@ -1364,23 +1364,31 @@ zvol_open(struct block_device *bdev, fmode_t flag)
|
|
return (SET_ERROR(-ENXIO));
|
|
}
|
|
|
|
- /* take zv_suspend_lock before zv_state_lock */
|
|
- rw_enter(&zv->zv_suspend_lock, RW_READER);
|
|
-
|
|
mutex_enter(&zv->zv_state_lock);
|
|
-
|
|
/*
|
|
* make sure zvol is not suspended during first open
|
|
- * (hold zv_suspend_lock), otherwise, drop the lock
|
|
+ * (hold zv_suspend_lock) and respect proper lock acquisition
|
|
+ * ordering - zv_suspend_lock before zv_state_lock
|
|
*/
|
|
if (zv->zv_open_count == 0) {
|
|
- drop_suspend = B_TRUE;
|
|
+ if (!rw_tryenter(&zv->zv_suspend_lock, RW_READER)) {
|
|
+ mutex_exit(&zv->zv_state_lock);
|
|
+ rw_enter(&zv->zv_suspend_lock, RW_READER);
|
|
+ mutex_enter(&zv->zv_state_lock);
|
|
+ /* check to see if zv_suspend_lock is needed */
|
|
+ if (zv->zv_open_count != 0) {
|
|
+ rw_exit(&zv->zv_suspend_lock);
|
|
+ drop_suspend = B_FALSE;
|
|
+ }
|
|
+ }
|
|
} else {
|
|
- rw_exit(&zv->zv_suspend_lock);
|
|
+ drop_suspend = B_FALSE;
|
|
}
|
|
-
|
|
mutex_exit(&zvol_state_lock);
|
|
|
|
+ ASSERT(MUTEX_HELD(&zv->zv_state_lock));
|
|
+ ASSERT(zv->zv_open_count != 0 || RW_READ_HELD(&zv->zv_suspend_lock));
|
|
+
|
|
if (zv->zv_open_count == 0) {
|
|
error = zvol_first_open(zv);
|
|
if (error)
|
|
@@ -1417,28 +1425,38 @@ static int
|
|
zvol_release(struct gendisk *disk, fmode_t mode)
|
|
{
|
|
zvol_state_t *zv;
|
|
- boolean_t drop_suspend = B_FALSE;
|
|
+ boolean_t drop_suspend = B_TRUE;
|
|
|
|
- ASSERT(!mutex_owned(&zvol_state_lock));
|
|
+ ASSERT(!MUTEX_HELD(&zvol_state_lock));
|
|
|
|
mutex_enter(&zvol_state_lock);
|
|
zv = disk->private_data;
|
|
- ASSERT(zv && zv->zv_open_count > 0);
|
|
-
|
|
- /* take zv_suspend_lock before zv_state_lock */
|
|
- rw_enter(&zv->zv_suspend_lock, RW_READER);
|
|
|
|
mutex_enter(&zv->zv_state_lock);
|
|
- mutex_exit(&zvol_state_lock);
|
|
-
|
|
+ ASSERT(zv->zv_open_count > 0);
|
|
/*
|
|
* make sure zvol is not suspended during last close
|
|
- * (hold zv_suspend_lock), otherwise, drop the lock
|
|
+ * (hold zv_suspend_lock) and respect proper lock acquisition
|
|
+ * ordering - zv_suspend_lock before zv_state_lock
|
|
*/
|
|
- if (zv->zv_open_count == 1)
|
|
- drop_suspend = B_TRUE;
|
|
- else
|
|
- rw_exit(&zv->zv_suspend_lock);
|
|
+ if (zv->zv_open_count == 1) {
|
|
+ if (!rw_tryenter(&zv->zv_suspend_lock, RW_READER)) {
|
|
+ mutex_exit(&zv->zv_state_lock);
|
|
+ rw_enter(&zv->zv_suspend_lock, RW_READER);
|
|
+ mutex_enter(&zv->zv_state_lock);
|
|
+ /* check to see if zv_suspend_lock is needed */
|
|
+ if (zv->zv_open_count != 1) {
|
|
+ rw_exit(&zv->zv_suspend_lock);
|
|
+ drop_suspend = B_FALSE;
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ drop_suspend = B_FALSE;
|
|
+ }
|
|
+ mutex_exit(&zvol_state_lock);
|
|
+
|
|
+ ASSERT(MUTEX_HELD(&zv->zv_state_lock));
|
|
+ ASSERT(zv->zv_open_count != 1 || RW_READ_HELD(&zv->zv_suspend_lock));
|
|
|
|
zv->zv_open_count--;
|
|
if (zv->zv_open_count == 0)
|