diff mbox series

[RFC,10/48] scsi: target/core: Unlock PR generation bump

Message ID 20220803162857.27770-11-d.bogdanov@yadro.com (mailing list archive)
State New, archived
Headers show
Series Target cluster implementation over DLM | expand

Commit Message

Dmitry Bogdanov April 30, 2020, 2:16 p.m. UTC
From: Konstantin Shelekhin <k.shelekhin@yadro.com>

Get rid of spinlock and bump PR generation atomically. This is required
to prevent deadlock later on.

Signed-off-by: Konstantin Shelekhin <k.shelekhin@yadro.com>
Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
---
 drivers/target/target_core_configfs.c |  3 ++-
 drivers/target/target_core_pr.c       | 25 ++++++-------------------
 include/target/target_core_base.h     |  2 +-
 3 files changed, 9 insertions(+), 21 deletions(-)
diff mbox series

Patch

diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 40b9808738d2..610de251994e 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -1814,7 +1814,8 @@  static ssize_t target_pr_res_pr_all_tgt_pts_show(struct config_item *item,
 static ssize_t target_pr_res_pr_generation_show(struct config_item *item,
 		char *page)
 {
-	return sprintf(page, "0x%08x\n", pr_to_dev(item)->t10_pr.pr_generation);
+	return sprintf(page, "0x%08x\n",
+			atomic_read(&pr_to_dev(item)->t10_pr.pr_generation));
 }
 
 
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index 668670b1414a..8f3d920d2590 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -594,8 +594,6 @@  target_scsi3_pr_reservation_check(struct se_cmd *cmd)
 
 static u32 core_scsi3_pr_generation(struct se_device *dev)
 {
-	u32 prg;
-
 	/*
 	 * PRGeneration field shall contain the value of a 32-bit wrapping
 	 * counter mainted by the device server.
@@ -605,11 +603,7 @@  static u32 core_scsi3_pr_generation(struct se_device *dev)
 	 *
 	 * See spc4r17 section 6.3.12 READ_KEYS service action
 	 */
-	spin_lock(&dev->dev_reservation_lock);
-	prg = dev->t10_pr.pr_generation++;
-	spin_unlock(&dev->dev_reservation_lock);
-
-	return prg;
+	return atomic_inc_return(&dev->t10_pr.pr_generation);
 }
 
 static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
@@ -1057,15 +1051,8 @@  static void __core_scsi3_add_registration(
 	/*
 	 * Increment PRgeneration counter for struct se_device upon a successful
 	 * REGISTER, see spc4r17 section 6.3.2 READ_KEYS service action
-	 *
-	 * Also, when register_move = 1 for PROUT REGISTER_AND_MOVE service
-	 * action, the struct se_device->dev_reservation_lock will already be held,
-	 * so we do not call core_scsi3_pr_generation() which grabs the lock
-	 * for the REGISTER.
 	 */
-	pr_reg->pr_res_generation = (register_move) ?
-			dev->t10_pr.pr_generation++ :
-			core_scsi3_pr_generation(dev);
+	pr_reg->pr_res_generation = core_scsi3_pr_generation(dev);
 
 	spin_lock(&pr_tmpl->registration_lock);
 	list_add_tail(&pr_reg->pr_reg_list, &pr_tmpl->registration_list);
@@ -3481,7 +3468,7 @@  core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
 	 * Increment PRGeneration for existing registrations..
 	 */
 	if (!new_reg)
-		dest_pr_reg->pr_res_generation = pr_tmpl->pr_generation++;
+		dest_pr_reg->pr_res_generation = core_scsi3_pr_generation(dev);
 	spin_unlock(&dev->dev_reservation_lock);
 
 	pr_debug("SPC-3 PR [%s] Service Action: REGISTER_AND_MOVE"
@@ -3703,7 +3690,7 @@  core_scsi3_pri_read_keys(struct se_cmd *cmd)
 	if (!buf)
 		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-	put_unaligned_be32(dev->t10_pr.pr_generation, buf);
+	put_unaligned_be32(atomic_read(&dev->t10_pr.pr_generation), buf);
 
 	spin_lock(&dev->t10_pr.registration_lock);
 	list_for_each_entry(pr_reg, &dev->t10_pr.registration_list,
@@ -3758,7 +3745,7 @@  core_scsi3_pri_read_reservation(struct se_cmd *cmd)
 	if (!buf)
 		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-	put_unaligned_be32(dev->t10_pr.pr_generation, &buf[0]);
+	put_unaligned_be32(atomic_read(&dev->t10_pr.pr_generation), &buf[0]);
 
 	spin_lock(&dev->dev_reservation_lock);
 	pr_reg = dev->dev_pr_res_holder;
@@ -3900,7 +3887,7 @@  core_scsi3_pri_read_full_status(struct se_cmd *cmd)
 	if (!buf)
 		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-	put_unaligned_be32(dev->t10_pr.pr_generation, &buf[0]);
+	put_unaligned_be32(atomic_read(&dev->t10_pr.pr_generation), &buf[0]);
 
 	spin_lock(&dev->dev_reservation_lock);
 	if (dev->dev_pr_res_holder) {
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 6ed484683ab6..7e13db647faa 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -385,7 +385,7 @@  struct t10_reservation {
 	 * for SCSI device */
 	int pr_aptpl_active;
 #define PR_APTPL_BUF_LEN			262144
-	u32 pr_generation;
+	atomic_t pr_generation;
 	spinlock_t registration_lock;
 	spinlock_t aptpl_reg_lock;
 	/*