linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] scsi: target: Add WRITE_ATOMIC_16 support
@ 2024-10-08  2:03 Mike Christie
  2024-10-08  2:03 ` [PATCH 1/7] scsi: target: Rename target_configure_unmap_from_queue Mike Christie
                   ` (6 more replies)
  0 siblings, 7 replies; 23+ messages in thread
From: Mike Christie @ 2024-10-08  2:03 UTC (permalink / raw)
  To: martin.petersen, linux-scsi, target-devel

The following patches were made over Linus's current tree and add
WRITE_ATOMIC_16 support to LIO.

In this patchset we only support target_core_iblock. It's implemented
similar to UNMAP where we do not do any emulation and instead pass the
operation to the block layer.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 1/7] scsi: target: Rename target_configure_unmap_from_queue
  2024-10-08  2:03 [PATCH 0/7] scsi: target: Add WRITE_ATOMIC_16 support Mike Christie
@ 2024-10-08  2:03 ` Mike Christie
  2025-05-14 11:11   ` John Garry
  2024-10-08  2:03 ` [PATCH 2/7] scsi: target: Add atomic se_device fields Mike Christie
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 23+ messages in thread
From: Mike Christie @ 2024-10-08  2:03 UTC (permalink / raw)
  To: martin.petersen, linux-scsi, target-devel; +Cc: Mike Christie

Rename target_configure_unmap_from_queue to
target_configure_unmap_from_bdev since it now takes a bdev.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
---
 drivers/target/target_core_device.c  | 6 +++---
 drivers/target/target_core_file.c    | 4 ++--
 drivers/target/target_core_iblock.c  | 4 ++--
 include/target/target_core_backend.h | 4 ++--
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 7d43d92c44d4..b709a64c0ff3 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -797,8 +797,8 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
  * Check if the underlying struct block_device supports discard and if yes
  * configure the UNMAP parameters.
  */
-bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
-				       struct block_device *bdev)
+bool target_configure_unmap_from_bdev(struct se_dev_attrib *attrib,
+				      struct block_device *bdev)
 {
 	int block_size = bdev_logical_block_size(bdev);
 
@@ -816,7 +816,7 @@ bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
 		bdev_discard_alignment(bdev) / block_size;
 	return true;
 }
-EXPORT_SYMBOL(target_configure_unmap_from_queue);
+EXPORT_SYMBOL(target_configure_unmap_from_bdev);
 
 /*
  * Convert from blocksize advertised to the initiator to the 512 byte
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 2d78ef74633c..b2610073e8cc 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -92,8 +92,8 @@ static bool fd_configure_unmap(struct se_device *dev)
 	struct inode *inode = file->f_mapping->host;
 
 	if (S_ISBLK(inode->i_mode))
-		return target_configure_unmap_from_queue(&dev->dev_attrib,
-							 I_BDEV(inode));
+		return target_configure_unmap_from_bdev(&dev->dev_attrib,
+							I_BDEV(inode));
 
 	/* Limit UNMAP emulation to 8k Number of LBAs (NoLB) */
 	dev->dev_attrib.max_unmap_lba_count = 0x2000;
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index c8dc92a7d63e..3a191bc35e04 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -83,8 +83,8 @@ static bool iblock_configure_unmap(struct se_device *dev)
 {
 	struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
 
-	return target_configure_unmap_from_queue(&dev->dev_attrib,
-						 ib_dev->ibd_bd);
+	return target_configure_unmap_from_bdev(&dev->dev_attrib,
+						ib_dev->ibd_bd);
 }
 
 static int iblock_configure_device(struct se_device *dev)
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index 4063a701081b..d394306f8f49 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -121,8 +121,8 @@ sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd,
 
 bool target_sense_desc_format(struct se_device *dev);
 sector_t target_to_linux_sector(struct se_device *dev, sector_t lb);
-bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
-				       struct block_device *bdev);
+bool target_configure_unmap_from_bdev(struct se_dev_attrib *attrib,
+				      struct block_device *bdev);
 
 static inline bool target_dev_configured(struct se_device *se_dev)
 {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 2/7] scsi: target: Add atomic se_device fields
  2024-10-08  2:03 [PATCH 0/7] scsi: target: Add WRITE_ATOMIC_16 support Mike Christie
  2024-10-08  2:03 ` [PATCH 1/7] scsi: target: Rename target_configure_unmap_from_queue Mike Christie
@ 2024-10-08  2:03 ` Mike Christie
  2025-05-14 10:26   ` John Garry
  2024-10-08  2:03 ` [PATCH 3/7] scsi: target: Add helper to setup atomic values from block_device Mike Christie
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 23+ messages in thread
From: Mike Christie @ 2024-10-08  2:03 UTC (permalink / raw)
  To: martin.petersen, linux-scsi, target-devel; +Cc: Mike Christie

This adds atomic fields to the se_device and exports them in configfs.

Initially only target_core_iblock will be supported and we will inherit
all the settings from the block layer except the alignment which userspace
will set.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
---
 drivers/target/target_core_configfs.c | 42 +++++++++++++++++++++++++++
 include/target/target_core_base.h     |  6 ++++
 2 files changed, 48 insertions(+)

diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index c40217f44b1b..f3c7da650f65 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -578,6 +578,12 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data);
 DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len);
 DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc);
 DEF_CONFIGFS_ATTRIB_SHOW(submit_type);
+DEF_CONFIGFS_ATTRIB_SHOW(atomic_supported);
+DEF_CONFIGFS_ATTRIB_SHOW(atomic_alignment);
+DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_len);
+DEF_CONFIGFS_ATTRIB_SHOW(atomic_granularity);
+DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_with_boundary);
+DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_boundary);
 
 #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name)				\
 static ssize_t _name##_store(struct config_item *item, const char *page,\
@@ -1266,6 +1272,30 @@ static ssize_t submit_type_store(struct config_item *item, const char *page,
 	return count;
 }
 
+static ssize_t atomic_alignment_store(struct config_item *item,
+				      const char *page, size_t count)
+{
+	struct se_dev_attrib *da = to_attrib(item);
+	u32 val;
+	int ret;
+
+	ret = kstrtou32(page, 0, &val);
+	if (ret < 0)
+		return ret;
+
+	if (da->da_dev->export_count) {
+		pr_err("dev[%p]: Unable to change SE Device atomic_alignment while export_count is %d\n",
+		       da->da_dev, da->da_dev->export_count);
+		return -EINVAL;
+	}
+
+	da->atomic_alignment = val;
+
+	pr_debug("dev[%p]: SE Device atomic_alignment changed to %u\n",
+		 da->da_dev, val);
+	return count;
+}
+
 CONFIGFS_ATTR(, emulate_model_alias);
 CONFIGFS_ATTR(, emulate_dpo);
 CONFIGFS_ATTR(, emulate_fua_write);
@@ -1302,6 +1332,12 @@ CONFIGFS_ATTR(, max_write_same_len);
 CONFIGFS_ATTR(, alua_support);
 CONFIGFS_ATTR(, pgr_support);
 CONFIGFS_ATTR(, submit_type);
+CONFIGFS_ATTR(, atomic_alignment);
+CONFIGFS_ATTR_RO(, atomic_supported);
+CONFIGFS_ATTR_RO(, atomic_max_len);
+CONFIGFS_ATTR_RO(, atomic_granularity);
+CONFIGFS_ATTR_RO(, atomic_max_with_boundary);
+CONFIGFS_ATTR_RO(, atomic_max_boundary);
 
 /*
  * dev_attrib attributes for devices using the target core SBC/SPC
@@ -1345,6 +1381,12 @@ struct configfs_attribute *sbc_attrib_attrs[] = {
 	&attr_pgr_support,
 	&attr_emulate_rsoc,
 	&attr_submit_type,
+	&attr_atomic_supported,
+	&attr_atomic_alignment,
+	&attr_atomic_max_len,
+	&attr_atomic_granularity,
+	&attr_atomic_max_with_boundary,
+	&attr_atomic_max_boundary,
 	NULL,
 };
 EXPORT_SYMBOL(sbc_attrib_attrs);
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 97099a5e3f6c..6c87bd018983 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -715,6 +715,7 @@ struct se_dev_attrib {
 	bool		is_nonrot;
 	bool		emulate_rest_reord;
 	bool		unmap_zeroes_data;
+	bool		atomic_supported;
 	u32		hw_block_size;
 	u32		block_size;
 	u32		hw_max_sectors;
@@ -726,6 +727,11 @@ struct se_dev_attrib {
 	u32		unmap_granularity;
 	u32		unmap_granularity_alignment;
 	u32		max_write_same_len;
+	u32		atomic_max_len;
+	u32		atomic_alignment;
+	u32		atomic_granularity;
+	u32		atomic_max_with_boundary;
+	u32		atomic_max_boundary;
 	u8		submit_type;
 	struct se_device *da_dev;
 	struct config_group da_group;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 3/7] scsi: target: Add helper to setup atomic values from block_device
  2024-10-08  2:03 [PATCH 0/7] scsi: target: Add WRITE_ATOMIC_16 support Mike Christie
  2024-10-08  2:03 ` [PATCH 1/7] scsi: target: Rename target_configure_unmap_from_queue Mike Christie
  2024-10-08  2:03 ` [PATCH 2/7] scsi: target: Add atomic se_device fields Mike Christie
@ 2024-10-08  2:03 ` Mike Christie
  2025-05-14 10:29   ` John Garry
  2024-10-08  2:03 ` [PATCH 4/7] scsi: target: Add WRITE_ATOMIC_16 handler Mike Christie
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 23+ messages in thread
From: Mike Christie @ 2024-10-08  2:03 UTC (permalink / raw)
  To: martin.petersen, linux-scsi, target-devel; +Cc: Mike Christie

This adds a helper function that sets up the atomic value based on a
block_device similar to what we do for unmap.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
---
 drivers/target/target_core_device.c  | 18 ++++++++++++++++++
 include/target/target_core_backend.h |  2 ++
 2 files changed, 20 insertions(+)

diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index b709a64c0ff3..4741de3d1061 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -793,6 +793,24 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
 	return dev;
 }
 
+void target_configure_write_atomic_from_bdev(struct se_dev_attrib *attrib,
+					     struct block_device *bdev)
+{
+	struct request_queue *q = bdev_get_queue(bdev);
+	int block_size = bdev_logical_block_size(bdev);
+
+	if (!bdev_can_atomic_write(bdev))
+		return;
+
+	attrib->atomic_supported = true;
+	attrib->atomic_max_len = queue_atomic_write_max_bytes(q) / block_size;
+	attrib->atomic_granularity = queue_atomic_write_unit_min_bytes(q) /
+								block_size;
+	attrib->atomic_max_with_boundary = 0;
+	attrib->atomic_max_boundary = 0;
+}
+EXPORT_SYMBOL_GPL(target_configure_write_atomic_from_bdev);
+
 /*
  * Check if the underlying struct block_device supports discard and if yes
  * configure the UNMAP parameters.
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index d394306f8f49..e32de80854b6 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -123,6 +123,8 @@ bool target_sense_desc_format(struct se_device *dev);
 sector_t target_to_linux_sector(struct se_device *dev, sector_t lb);
 bool target_configure_unmap_from_bdev(struct se_dev_attrib *attrib,
 				      struct block_device *bdev);
+void target_configure_write_atomic_from_bdev(struct se_dev_attrib *attrib,
+					     struct block_device *bdev);
 
 static inline bool target_dev_configured(struct se_device *se_dev)
 {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 4/7] scsi: target: Add WRITE_ATOMIC_16 handler
  2024-10-08  2:03 [PATCH 0/7] scsi: target: Add WRITE_ATOMIC_16 support Mike Christie
                   ` (2 preceding siblings ...)
  2024-10-08  2:03 ` [PATCH 3/7] scsi: target: Add helper to setup atomic values from block_device Mike Christie
@ 2024-10-08  2:03 ` Mike Christie
  2024-10-09  6:10   ` kernel test robot
  2025-05-14 10:47   ` John Garry
  2024-10-08  2:03 ` [PATCH 5/7] scsi: target: Report atomic values in INQUIRY Mike Christie
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 23+ messages in thread
From: Mike Christie @ 2024-10-08  2:03 UTC (permalink / raw)
  To: martin.petersen, linux-scsi, target-devel; +Cc: Mike Christie

This adds the core LIO code to process the WRITE_ATOMIC_16 command.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
---
 drivers/target/target_core_sbc.c  | 48 +++++++++++++++++++++++++++++++
 include/target/target_core_base.h |  1 +
 2 files changed, 49 insertions(+)

diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index fe8beb7dbab1..0ae0d4ec0ac3 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -764,6 +764,46 @@ sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
 	return 0;
 }
 
+static int
+sbc_check_atomic(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
+{
+	struct se_dev_attrib *attrib = &dev->dev_attrib;
+	u16 boundary, transfer_len;
+	u32 lba;
+
+	if (!attrib->atomic_supported)
+		return TCM_UNSUPPORTED_SCSI_OPCODE;
+
+	lba = transport_lba_32(cdb);
+	boundary = get_unaligned_be16(&cdb[10]);
+	transfer_len = get_unaligned_be16(&cdb[12]);
+
+	if (!boundary) {
+		if (transfer_len > attrib->atomic_max_len)
+			return TCM_INVALID_CDB_FIELD;
+	} else {
+		if (transfer_len > attrib->atomic_max_with_boundary)
+			return TCM_INVALID_CDB_FIELD;
+
+		if (boundary > attrib->atomic_max_boundary)
+			return TCM_INVALID_CDB_FIELD;
+	}
+
+	if (attrib->atomic_granularity) {
+		if (transfer_len % attrib->atomic_granularity)
+			return TCM_INVALID_CDB_FIELD;
+
+		if (boundary && boundary % attrib->atomic_granularity)
+			return TCM_INVALID_CDB_FIELD;
+	}
+
+	if (dev->dev_attrib.atomic_alignment &&
+	    lba % dev->dev_attrib.atomic_alignment)
+		return TCM_INVALID_CDB_FIELD;
+
+	return 0;
+}
+
 sense_reason_t
 sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops)
 {
@@ -861,6 +901,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops)
 		break;
 	case WRITE_16:
 	case WRITE_VERIFY_16:
+	case WRITE_ATOMIC_16:
 		sectors = transport_get_sectors_16(cdb);
 		cmd->t_task_lba = transport_lba_64(cdb);
 
@@ -872,6 +913,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops)
 			return ret;
 
 		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+		if (cdb[0] == WRITE_ATOMIC_16) {
+			cmd->se_cmd_flags |= SCF_ATOMIC;
+
+			ret = sbc_check_atomic(dev, cmd, cdb);
+			if (ret)
+				return ret;
+		}
 		cmd->execute_cmd = sbc_execute_rw;
 		break;
 	case VARIABLE_LENGTH_CMD:
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 6c87bd018983..7b8ed21bea03 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -157,6 +157,7 @@ enum se_cmd_flags_table {
 	SCF_USE_CPUID				= (1 << 16),
 	SCF_TASK_ATTR_SET			= (1 << 17),
 	SCF_TREAT_READ_AS_NORMAL		= (1 << 18),
+	SCF_ATOMIC				= (1 << 19),
 };
 
 /*
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 5/7] scsi: target: Report atomic values in INQUIRY
  2024-10-08  2:03 [PATCH 0/7] scsi: target: Add WRITE_ATOMIC_16 support Mike Christie
                   ` (3 preceding siblings ...)
  2024-10-08  2:03 ` [PATCH 4/7] scsi: target: Add WRITE_ATOMIC_16 handler Mike Christie
@ 2024-10-08  2:03 ` Mike Christie
  2025-05-14 10:56   ` John Garry
  2024-10-08  2:03 ` [PATCH 6/7] scsi: target: Add WRITE_ATOMIC_16 support to RSOC Mike Christie
  2024-10-08  2:03 ` [PATCH 7/7] scsi: target: Add atomic support to target_core_iblock Mike Christie
  6 siblings, 1 reply; 23+ messages in thread
From: Mike Christie @ 2024-10-08  2:03 UTC (permalink / raw)
  To: martin.petersen, linux-scsi, target-devel; +Cc: Mike Christie

This reports the atomic values in the Block Limits VPD page.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
---
 drivers/target/target_core_spc.c | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index ea14a3835681..ce5eec5c8b8a 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -521,7 +521,6 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 		have_tp = 1;
 
 	buf[0] = dev->transport->get_device_type(dev);
-	buf[3] = have_tp ? 0x3c : 0x10;
 
 	/* Set WSNZ to 1 */
 	buf[4] = 0x01;
@@ -562,11 +561,10 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 	else
 		put_unaligned_be32(dev->dev_attrib.optimal_sectors, &buf[12]);
 
-	/*
-	 * Exit now if we don't support TP.
-	 */
+	put_unaligned_be16(12, &buf[2]);
+
 	if (!have_tp)
-		goto max_write_same;
+		goto try_atomic;
 
 	/*
 	 * Set MAXIMUM UNMAP LBA COUNT
@@ -595,9 +593,29 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 	/*
 	 * MAXIMUM WRITE SAME LENGTH
 	 */
-max_write_same:
 	put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]);
 
+	put_unaligned_be16(40, &buf[2]);
+
+try_atomic:
+	/*
+	 * ATOMIC
+	 */
+	if (!dev->dev_attrib.atomic_supported)
+		goto done;
+
+	if (dev->dev_attrib.atomic_max_len < io_max_blocks)
+		put_unaligned_be32(dev->dev_attrib.atomic_max_len, &buf[44]);
+	else
+		put_unaligned_be32(io_max_blocks, &buf[44]);
+
+	put_unaligned_be32(dev->dev_attrib.atomic_alignment, &buf[48]);
+	put_unaligned_be32(dev->dev_attrib.atomic_granularity, &buf[52]);
+	put_unaligned_be32(dev->dev_attrib.atomic_max_with_boundary, &buf[56]);
+	put_unaligned_be32(dev->dev_attrib.atomic_max_boundary, &buf[60]);
+
+	put_unaligned_be16(60, &buf[2]);
+done:
 	return 0;
 }
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 6/7] scsi: target: Add WRITE_ATOMIC_16 support to RSOC
  2024-10-08  2:03 [PATCH 0/7] scsi: target: Add WRITE_ATOMIC_16 support Mike Christie
                   ` (4 preceding siblings ...)
  2024-10-08  2:03 ` [PATCH 5/7] scsi: target: Report atomic values in INQUIRY Mike Christie
@ 2024-10-08  2:03 ` Mike Christie
  2024-10-08  2:03 ` [PATCH 7/7] scsi: target: Add atomic support to target_core_iblock Mike Christie
  6 siblings, 0 replies; 23+ messages in thread
From: Mike Christie @ 2024-10-08  2:03 UTC (permalink / raw)
  To: martin.petersen, linux-scsi, target-devel; +Cc: Mike Christie

This has us report if the device supports WRITE_ATOMIC_16 in the
REPORT_SUPPORTED_OPERATION_CODES command.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
---
 drivers/target/target_core_spc.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index ce5eec5c8b8a..3c28b0ec5daf 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -1470,6 +1470,24 @@ static struct target_opcode_descriptor tcm_opcode_write_same32 = {
 	.update_usage_bits = set_dpofua_usage_bits32,
 };
 
+static bool tcm_is_atomic_enabled(struct target_opcode_descriptor *descr,
+				  struct se_cmd *cmd)
+{
+	return cmd->se_dev->dev_attrib.atomic_supported;
+}
+
+static struct target_opcode_descriptor tcm_opcode_write_atomic16 = {
+	.support = SCSI_SUPPORT_FULL,
+	.opcode = WRITE_ATOMIC_16,
+	.cdb_size = 16,
+	.usage_bits = {WRITE_ATOMIC_16, 0xf8, 0xff, 0xff,
+		       0xff, 0xff, 0xff, 0xff,
+		       0xff, 0xff, 0xff, 0xff,
+		       0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_atomic_enabled,
+	.update_usage_bits = set_dpofua_usage_bits,
+};
+
 static bool tcm_is_caw_enabled(struct target_opcode_descriptor *descr,
 			       struct se_cmd *cmd)
 {
@@ -2026,6 +2044,7 @@ static struct target_opcode_descriptor *tcm_supported_opcodes[] = {
 	&tcm_opcode_write16,
 	&tcm_opcode_write_verify16,
 	&tcm_opcode_write_same32,
+	&tcm_opcode_write_atomic16,
 	&tcm_opcode_compare_write,
 	&tcm_opcode_read_capacity,
 	&tcm_opcode_read_capacity16,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 7/7] scsi: target: Add atomic support to target_core_iblock
  2024-10-08  2:03 [PATCH 0/7] scsi: target: Add WRITE_ATOMIC_16 support Mike Christie
                   ` (5 preceding siblings ...)
  2024-10-08  2:03 ` [PATCH 6/7] scsi: target: Add WRITE_ATOMIC_16 support to RSOC Mike Christie
@ 2024-10-08  2:03 ` Mike Christie
  2025-05-14 11:01   ` John Garry
  6 siblings, 1 reply; 23+ messages in thread
From: Mike Christie @ 2024-10-08  2:03 UTC (permalink / raw)
  To: martin.petersen, linux-scsi, target-devel; +Cc: Mike Christie

This has target_core_iblock use the LIO helper function to translate its
block_device atomic settings to LIO settings. If we then get a write
that LIO has indicated is atomic via the SCF_ATOMIC flag, we use the
REQ_ATOMIC flag to tell the block layer to perform an atomic write.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
---
 drivers/target/target_core_iblock.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 3a191bc35e04..afcd62f81d20 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -147,6 +147,8 @@ static int iblock_configure_device(struct se_device *dev)
 	if (bdev_nonrot(bd))
 		dev->dev_attrib.is_nonrot = 1;
 
+	target_configure_write_atomic_from_bdev(&dev->dev_attrib, bd);
+
 	bi = bdev_get_integrity(bd);
 	if (!bi)
 		return 0;
@@ -762,6 +764,9 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
 			else if (!bdev_write_cache(ib_dev->ibd_bd))
 				opf |= REQ_FUA;
 		}
+
+		if (cmd->se_cmd_flags & SCF_ATOMIC)
+			opf |= REQ_ATOMIC;
 	} else {
 		opf = REQ_OP_READ;
 		miter_dir = SG_MITER_FROM_SG;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 4/7] scsi: target: Add WRITE_ATOMIC_16 handler
  2024-10-08  2:03 ` [PATCH 4/7] scsi: target: Add WRITE_ATOMIC_16 handler Mike Christie
@ 2024-10-09  6:10   ` kernel test robot
  2025-05-14 10:47   ` John Garry
  1 sibling, 0 replies; 23+ messages in thread
From: kernel test robot @ 2024-10-09  6:10 UTC (permalink / raw)
  To: Mike Christie, martin.petersen, linux-scsi, target-devel
  Cc: oe-kbuild-all, Mike Christie

Hi Mike,

kernel test robot noticed the following build warnings:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on jejb-scsi/for-next linus/master v6.12-rc2 next-20241008]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Mike-Christie/scsi-target-Rename-target_configure_unmap_from_queue/20241008-101218
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
patch link:    https://lore.kernel.org/r/20241008020437.78788-5-michael.christie%40oracle.com
patch subject: [PATCH 4/7] scsi: target: Add WRITE_ATOMIC_16 handler
config: x86_64-randconfig-123-20241009 (https://download.01.org/0day-ci/archive/20241009/202410091340.dQ10fC3u-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241009/202410091340.dQ10fC3u-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410091340.dQ10fC3u-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/target/target_core_sbc.c:775:24: sparse: sparse: incorrect type in return expression (different base types) @@     expected int @@     got restricted sense_reason_t @@
   drivers/target/target_core_sbc.c:775:24: sparse:     expected int
   drivers/target/target_core_sbc.c:775:24: sparse:     got restricted sense_reason_t
   drivers/target/target_core_sbc.c:783:32: sparse: sparse: incorrect type in return expression (different base types) @@     expected int @@     got restricted sense_reason_t @@
   drivers/target/target_core_sbc.c:783:32: sparse:     expected int
   drivers/target/target_core_sbc.c:783:32: sparse:     got restricted sense_reason_t
   drivers/target/target_core_sbc.c:786:32: sparse: sparse: incorrect type in return expression (different base types) @@     expected int @@     got restricted sense_reason_t @@
   drivers/target/target_core_sbc.c:786:32: sparse:     expected int
   drivers/target/target_core_sbc.c:786:32: sparse:     got restricted sense_reason_t
   drivers/target/target_core_sbc.c:789:32: sparse: sparse: incorrect type in return expression (different base types) @@     expected int @@     got restricted sense_reason_t @@
   drivers/target/target_core_sbc.c:789:32: sparse:     expected int
   drivers/target/target_core_sbc.c:789:32: sparse:     got restricted sense_reason_t
   drivers/target/target_core_sbc.c:794:32: sparse: sparse: incorrect type in return expression (different base types) @@     expected int @@     got restricted sense_reason_t @@
   drivers/target/target_core_sbc.c:794:32: sparse:     expected int
   drivers/target/target_core_sbc.c:794:32: sparse:     got restricted sense_reason_t
   drivers/target/target_core_sbc.c:797:32: sparse: sparse: incorrect type in return expression (different base types) @@     expected int @@     got restricted sense_reason_t @@
   drivers/target/target_core_sbc.c:797:32: sparse:     expected int
   drivers/target/target_core_sbc.c:797:32: sparse:     got restricted sense_reason_t
   drivers/target/target_core_sbc.c:802:24: sparse: sparse: incorrect type in return expression (different base types) @@     expected int @@     got restricted sense_reason_t @@
   drivers/target/target_core_sbc.c:802:24: sparse:     expected int
   drivers/target/target_core_sbc.c:802:24: sparse:     got restricted sense_reason_t
>> drivers/target/target_core_sbc.c:919:29: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted sense_reason_t [assigned] [usertype] ret @@     got int @@
   drivers/target/target_core_sbc.c:919:29: sparse:     expected restricted sense_reason_t [assigned] [usertype] ret
   drivers/target/target_core_sbc.c:919:29: sparse:     got int

vim +775 drivers/target/target_core_sbc.c

   766	
   767	static int
   768	sbc_check_atomic(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
   769	{
   770		struct se_dev_attrib *attrib = &dev->dev_attrib;
   771		u16 boundary, transfer_len;
   772		u32 lba;
   773	
   774		if (!attrib->atomic_supported)
 > 775			return TCM_UNSUPPORTED_SCSI_OPCODE;
   776	
   777		lba = transport_lba_32(cdb);
   778		boundary = get_unaligned_be16(&cdb[10]);
   779		transfer_len = get_unaligned_be16(&cdb[12]);
   780	
   781		if (!boundary) {
   782			if (transfer_len > attrib->atomic_max_len)
   783				return TCM_INVALID_CDB_FIELD;
   784		} else {
   785			if (transfer_len > attrib->atomic_max_with_boundary)
   786				return TCM_INVALID_CDB_FIELD;
   787	
   788			if (boundary > attrib->atomic_max_boundary)
   789				return TCM_INVALID_CDB_FIELD;
   790		}
   791	
   792		if (attrib->atomic_granularity) {
   793			if (transfer_len % attrib->atomic_granularity)
   794				return TCM_INVALID_CDB_FIELD;
   795	
   796			if (boundary && boundary % attrib->atomic_granularity)
   797				return TCM_INVALID_CDB_FIELD;
   798		}
   799	
   800		if (dev->dev_attrib.atomic_alignment &&
   801		    lba % dev->dev_attrib.atomic_alignment)
   802			return TCM_INVALID_CDB_FIELD;
   803	
   804		return 0;
   805	}
   806	
   807	sense_reason_t
   808	sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops)
   809	{
   810		struct se_device *dev = cmd->se_dev;
   811		unsigned char *cdb = cmd->t_task_cdb;
   812		unsigned int size;
   813		u32 sectors = 0;
   814		sense_reason_t ret;
   815	
   816		cmd->protocol_data = ops;
   817	
   818		switch (cdb[0]) {
   819		case READ_6:
   820			sectors = transport_get_sectors_6(cdb);
   821			cmd->t_task_lba = transport_lba_21(cdb);
   822			cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
   823			cmd->execute_cmd = sbc_execute_rw;
   824			break;
   825		case READ_10:
   826			sectors = transport_get_sectors_10(cdb);
   827			cmd->t_task_lba = transport_lba_32(cdb);
   828	
   829			if (sbc_check_dpofua(dev, cmd, cdb))
   830				return TCM_INVALID_CDB_FIELD;
   831	
   832			ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, false);
   833			if (ret)
   834				return ret;
   835	
   836			cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
   837			cmd->execute_cmd = sbc_execute_rw;
   838			break;
   839		case READ_12:
   840			sectors = transport_get_sectors_12(cdb);
   841			cmd->t_task_lba = transport_lba_32(cdb);
   842	
   843			if (sbc_check_dpofua(dev, cmd, cdb))
   844				return TCM_INVALID_CDB_FIELD;
   845	
   846			ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, false);
   847			if (ret)
   848				return ret;
   849	
   850			cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
   851			cmd->execute_cmd = sbc_execute_rw;
   852			break;
   853		case READ_16:
   854			sectors = transport_get_sectors_16(cdb);
   855			cmd->t_task_lba = transport_lba_64(cdb);
   856	
   857			if (sbc_check_dpofua(dev, cmd, cdb))
   858				return TCM_INVALID_CDB_FIELD;
   859	
   860			ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, false);
   861			if (ret)
   862				return ret;
   863	
   864			cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
   865			cmd->execute_cmd = sbc_execute_rw;
   866			break;
   867		case WRITE_6:
   868			sectors = transport_get_sectors_6(cdb);
   869			cmd->t_task_lba = transport_lba_21(cdb);
   870			cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
   871			cmd->execute_cmd = sbc_execute_rw;
   872			break;
   873		case WRITE_10:
   874		case WRITE_VERIFY:
   875			sectors = transport_get_sectors_10(cdb);
   876			cmd->t_task_lba = transport_lba_32(cdb);
   877	
   878			if (sbc_check_dpofua(dev, cmd, cdb))
   879				return TCM_INVALID_CDB_FIELD;
   880	
   881			ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, true);
   882			if (ret)
   883				return ret;
   884	
   885			cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
   886			cmd->execute_cmd = sbc_execute_rw;
   887			break;
   888		case WRITE_12:
   889			sectors = transport_get_sectors_12(cdb);
   890			cmd->t_task_lba = transport_lba_32(cdb);
   891	
   892			if (sbc_check_dpofua(dev, cmd, cdb))
   893				return TCM_INVALID_CDB_FIELD;
   894	
   895			ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, true);
   896			if (ret)
   897				return ret;
   898	
   899			cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
   900			cmd->execute_cmd = sbc_execute_rw;
   901			break;
   902		case WRITE_16:
   903		case WRITE_VERIFY_16:
   904		case WRITE_ATOMIC_16:
   905			sectors = transport_get_sectors_16(cdb);
   906			cmd->t_task_lba = transport_lba_64(cdb);
   907	
   908			if (sbc_check_dpofua(dev, cmd, cdb))
   909				return TCM_INVALID_CDB_FIELD;
   910	
   911			ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, true);
   912			if (ret)
   913				return ret;
   914	
   915			cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
   916			if (cdb[0] == WRITE_ATOMIC_16) {
   917				cmd->se_cmd_flags |= SCF_ATOMIC;
   918	
 > 919				ret = sbc_check_atomic(dev, cmd, cdb);
   920				if (ret)
   921					return ret;
   922			}
   923			cmd->execute_cmd = sbc_execute_rw;
   924			break;
   925		case VARIABLE_LENGTH_CMD:
   926		{
   927			u16 service_action = get_unaligned_be16(&cdb[8]);
   928			switch (service_action) {
   929			case WRITE_SAME_32:
   930				sectors = transport_get_sectors_32(cdb);
   931				if (!sectors) {
   932					pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
   933					       " supported\n");
   934					return TCM_INVALID_CDB_FIELD;
   935				}
   936	
   937				size = sbc_get_size(cmd, 1);
   938				cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
   939	
   940				ret = sbc_setup_write_same(cmd, cdb[10], ops);
   941				if (ret)
   942					return ret;
   943				break;
   944			default:
   945				pr_err("VARIABLE_LENGTH_CMD service action"
   946					" 0x%04x not supported\n", service_action);
   947				return TCM_UNSUPPORTED_SCSI_OPCODE;
   948			}
   949			break;
   950		}
   951		case COMPARE_AND_WRITE:
   952			if (!dev->dev_attrib.emulate_caw) {
   953				pr_err_ratelimited("se_device %s/%s (vpd_unit_serial %s) reject COMPARE_AND_WRITE\n",
   954						   dev->se_hba->backend->ops->name,
   955						   config_item_name(&dev->dev_group.cg_item),
   956						   dev->t10_wwn.unit_serial);
   957				return TCM_UNSUPPORTED_SCSI_OPCODE;
   958			}
   959			sectors = cdb[13];
   960			/*
   961			 * Currently enforce COMPARE_AND_WRITE for a single sector
   962			 */
   963			if (sectors > 1) {
   964				pr_err("COMPARE_AND_WRITE contains NoLB: %u greater"
   965				       " than 1\n", sectors);
   966				return TCM_INVALID_CDB_FIELD;
   967			}
   968			if (sbc_check_dpofua(dev, cmd, cdb))
   969				return TCM_INVALID_CDB_FIELD;
   970	
   971			/*
   972			 * Double size because we have two buffers, note that
   973			 * zero is not an error..
   974			 */
   975			size = 2 * sbc_get_size(cmd, sectors);
   976			cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
   977			cmd->t_task_nolb = sectors;
   978			cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB | SCF_COMPARE_AND_WRITE;
   979			cmd->execute_cmd = sbc_compare_and_write;
   980			cmd->transport_complete_callback = compare_and_write_callback;
   981			break;
   982		case READ_CAPACITY:
   983			size = READ_CAP_LEN;
   984			cmd->execute_cmd = sbc_emulate_readcapacity;
   985			break;
   986		case SERVICE_ACTION_IN_16:
   987			switch (cmd->t_task_cdb[1] & 0x1f) {
   988			case SAI_READ_CAPACITY_16:
   989				cmd->execute_cmd = sbc_emulate_readcapacity_16;
   990				break;
   991			case SAI_REPORT_REFERRALS:
   992				cmd->execute_cmd = target_emulate_report_referrals;
   993				break;
   994			default:
   995				pr_err("Unsupported SA: 0x%02x\n",
   996					cmd->t_task_cdb[1] & 0x1f);
   997				return TCM_INVALID_CDB_FIELD;
   998			}
   999			size = get_unaligned_be32(&cdb[10]);
  1000			break;
  1001		case SYNCHRONIZE_CACHE:
  1002		case SYNCHRONIZE_CACHE_16:
  1003			if (cdb[0] == SYNCHRONIZE_CACHE) {
  1004				sectors = transport_get_sectors_10(cdb);
  1005				cmd->t_task_lba = transport_lba_32(cdb);
  1006			} else {
  1007				sectors = transport_get_sectors_16(cdb);
  1008				cmd->t_task_lba = transport_lba_64(cdb);
  1009			}
  1010			if (ops->execute_sync_cache) {
  1011				cmd->execute_cmd = ops->execute_sync_cache;
  1012				goto check_lba;
  1013			}
  1014			size = 0;
  1015			cmd->execute_cmd = sbc_emulate_noop;
  1016			break;
  1017		case UNMAP:
  1018			if (!ops->execute_unmap)
  1019				return TCM_UNSUPPORTED_SCSI_OPCODE;
  1020	
  1021			if (!dev->dev_attrib.emulate_tpu) {
  1022				pr_err("Got UNMAP, but backend device has"
  1023				       " emulate_tpu disabled\n");
  1024				return TCM_UNSUPPORTED_SCSI_OPCODE;
  1025			}
  1026			size = get_unaligned_be16(&cdb[7]);
  1027			cmd->execute_cmd = sbc_execute_unmap;
  1028			break;
  1029		case WRITE_SAME_16:
  1030			sectors = transport_get_sectors_16(cdb);
  1031			if (!sectors) {
  1032				pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
  1033				return TCM_INVALID_CDB_FIELD;
  1034			}
  1035	
  1036			size = sbc_get_size(cmd, 1);
  1037			cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
  1038	
  1039			ret = sbc_setup_write_same(cmd, cdb[1], ops);
  1040			if (ret)
  1041				return ret;
  1042			break;
  1043		case WRITE_SAME:
  1044			sectors = transport_get_sectors_10(cdb);
  1045			if (!sectors) {
  1046				pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
  1047				return TCM_INVALID_CDB_FIELD;
  1048			}
  1049	
  1050			size = sbc_get_size(cmd, 1);
  1051			cmd->t_task_lba = get_unaligned_be32(&cdb[2]);
  1052	
  1053			/*
  1054			 * Follow sbcr26 with WRITE_SAME (10) and check for the existence
  1055			 * of byte 1 bit 3 UNMAP instead of original reserved field
  1056			 */
  1057			ret = sbc_setup_write_same(cmd, cdb[1], ops);
  1058			if (ret)
  1059				return ret;
  1060			break;
  1061		case VERIFY:
  1062		case VERIFY_16:
  1063			size = 0;
  1064			if (cdb[0] == VERIFY) {
  1065				sectors = transport_get_sectors_10(cdb);
  1066				cmd->t_task_lba = transport_lba_32(cdb);
  1067			} else {
  1068				sectors = transport_get_sectors_16(cdb);
  1069				cmd->t_task_lba = transport_lba_64(cdb);
  1070			}
  1071			cmd->execute_cmd = sbc_emulate_noop;
  1072			goto check_lba;
  1073		case REZERO_UNIT:
  1074		case SEEK_6:
  1075		case SEEK_10:
  1076			/*
  1077			 * There are still clients out there which use these old SCSI-2
  1078			 * commands. This mainly happens when running VMs with legacy
  1079			 * guest systems, connected via SCSI command pass-through to
  1080			 * iSCSI targets. Make them happy and return status GOOD.
  1081			 */
  1082			size = 0;
  1083			cmd->execute_cmd = sbc_emulate_noop;
  1084			break;
  1085		case START_STOP:
  1086			size = 0;
  1087			cmd->execute_cmd = sbc_emulate_startstop;
  1088			break;
  1089		default:
  1090			ret = spc_parse_cdb(cmd, &size);
  1091			if (ret)
  1092				return ret;
  1093		}
  1094	
  1095		/* reject any command that we don't have a handler for */
  1096		if (!cmd->execute_cmd)
  1097			return TCM_UNSUPPORTED_SCSI_OPCODE;
  1098	
  1099		if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
  1100			unsigned long long end_lba;
  1101	check_lba:
  1102			end_lba = dev->transport->get_blocks(dev) + 1;
  1103			if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) ||
  1104			    ((cmd->t_task_lba + sectors) > end_lba)) {
  1105				pr_err("cmd exceeds last lba %llu "
  1106					"(lba %llu, sectors %u)\n",
  1107					end_lba, cmd->t_task_lba, sectors);
  1108				return TCM_ADDRESS_OUT_OF_RANGE;
  1109			}
  1110	
  1111			if (!(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE))
  1112				size = sbc_get_size(cmd, sectors);
  1113		}
  1114	
  1115		return target_cmd_size_check(cmd, size);
  1116	}
  1117	EXPORT_SYMBOL(sbc_parse_cdb);
  1118	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/7] scsi: target: Add atomic se_device fields
  2024-10-08  2:03 ` [PATCH 2/7] scsi: target: Add atomic se_device fields Mike Christie
@ 2025-05-14 10:26   ` John Garry
  2025-07-20 22:15     ` Mike Christie
  0 siblings, 1 reply; 23+ messages in thread
From: John Garry @ 2025-05-14 10:26 UTC (permalink / raw)
  To: Mike Christie, martin.petersen, linux-scsi, target-devel

On 08/10/2024 03:03, Mike Christie wrote:
> This adds atomic fields to the se_device and exports them in configfs.
> 
> Initially only target_core_iblock will be supported and we will inherit
> all the settings from the block layer except the alignment which userspace
> will set.
> 
> Signed-off-by: Mike Christie <michael.christie@oracle.com>
> ---
>   drivers/target/target_core_configfs.c | 42 +++++++++++++++++++++++++++
>   include/target/target_core_base.h     |  6 ++++
>   2 files changed, 48 insertions(+)
> 
> diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
> index c40217f44b1b..f3c7da650f65 100644
> --- a/drivers/target/target_core_configfs.c
> +++ b/drivers/target/target_core_configfs.c
> @@ -578,6 +578,12 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data);
>   DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len);
>   DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc);
>   DEF_CONFIGFS_ATTRIB_SHOW(submit_type);
> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_supported);
> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_alignment);
> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_len);
> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_granularity);
> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_with_boundary);
> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_boundary);
>   
>   #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name)				\
>   static ssize_t _name##_store(struct config_item *item, const char *page,\
> @@ -1266,6 +1272,30 @@ static ssize_t submit_type_store(struct config_item *item, const char *page,
>   	return count;
>   }
>   
> +static ssize_t atomic_alignment_store(struct config_item *item,
> +				      const char *page, size_t count)

What is special about alignment that we need to be able to configure this?

Won't that be derived from the block device queue_limits (like granularity)?

> +{
> +	struct se_dev_attrib *da = to_attrib(item);
> +	u32 val;
> +	int ret;
> +
> +	ret = kstrtou32(page, 0, &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (da->da_dev->export_count) {
> +		pr_err("dev[%p]: Unable to change SE Device atomic_alignment while export_count is %d\n",
> +		       da->da_dev, da->da_dev->export_count);
> +		return -EINVAL;
> +	}
> +
> +	da->atomic_alignment = val;
> +
> +	pr_debug("dev[%p]: SE Device atomic_alignment changed to %u\n",
> +		 da->da_dev, val);
> +	return count;
> +}
> +
>   CONFIGFS_ATTR(, emulate_model_alias);
>   CONFIGFS_ATTR(, emulate_dpo);
>   CONFIGFS_ATTR(, emulate_fua_write);
> @@ -1302,6 +1332,12 @@ CONFIGFS_ATTR(, max_write_same_len);
>   CONFIGFS_ATTR(, alua_support);
>   CONFIGFS_ATTR(, pgr_support);
>   CONFIGFS_ATTR(, submit_type);
> +CONFIGFS_ATTR(, atomic_alignment);
> +CONFIGFS_ATTR_RO(, atomic_supported);

isn't a non-zero atomic_max_len the same thing as this?

> +CONFIGFS_ATTR_RO(, atomic_max_len);
> +CONFIGFS_ATTR_RO(, atomic_granularity);
> +CONFIGFS_ATTR_RO(, atomic_max_with_boundary);
> +CONFIGFS_ATTR_RO(, atomic_max_boundary);
>   
>   /*
>    * dev_attrib attributes for devices using the target core SBC/SPC
> @@ -1345,6 +1381,12 @@ struct configfs_attribute *sbc_attrib_attrs[] = {
>   	&attr_pgr_support,
>   	&attr_emulate_rsoc,
>   	&attr_submit_type,
> +	&attr_atomic_supported,
> +	&attr_atomic_alignment,
> +	&attr_atomic_max_len,
> +	&attr_atomic_granularity,
> +	&attr_atomic_max_with_boundary,
> +	&attr_atomic_max_boundary,
>   	NULL,
>   };
>   EXPORT_SYMBOL(sbc_attrib_attrs);
> diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
> index 97099a5e3f6c..6c87bd018983 100644
> --- a/include/target/target_core_base.h
> +++ b/include/target/target_core_base.h
> @@ -715,6 +715,7 @@ struct se_dev_attrib {
>   	bool		is_nonrot;
>   	bool		emulate_rest_reord;
>   	bool		unmap_zeroes_data;
> +	bool		atomic_supported;
>   	u32		hw_block_size;
>   	u32		block_size;
>   	u32		hw_max_sectors;
> @@ -726,6 +727,11 @@ struct se_dev_attrib {
>   	u32		unmap_granularity;
>   	u32		unmap_granularity_alignment;
>   	u32		max_write_same_len;
> +	u32		atomic_max_len;
> +	u32		atomic_alignment;
> +	u32		atomic_granularity;
> +	u32		atomic_max_with_boundary;
> +	u32		atomic_max_boundary;

these will always be zero, right? I don't see much point in even storing 
them.

>   	u8		submit_type;
>   	struct se_device *da_dev;
>   	struct config_group da_group;


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 3/7] scsi: target: Add helper to setup atomic values from block_device
  2024-10-08  2:03 ` [PATCH 3/7] scsi: target: Add helper to setup atomic values from block_device Mike Christie
@ 2025-05-14 10:29   ` John Garry
  0 siblings, 0 replies; 23+ messages in thread
From: John Garry @ 2025-05-14 10:29 UTC (permalink / raw)
  To: Mike Christie, martin.petersen, linux-scsi, target-devel

On 08/10/2024 03:03, Mike Christie wrote:
> This adds a helper function that sets up the atomic value based on a
> block_device similar to what we do for unmap.

looks ok, apart from earlier query on alignment

> 
> Signed-off-by: Mike Christie <michael.christie@oracle.com>
> ---
>   drivers/target/target_core_device.c  | 18 ++++++++++++++++++
>   include/target/target_core_backend.h |  2 ++
>   2 files changed, 20 insertions(+)
> 
> diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
> index b709a64c0ff3..4741de3d1061 100644
> --- a/drivers/target/target_core_device.c
> +++ b/drivers/target/target_core_device.c
> @@ -793,6 +793,24 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
>   	return dev;
>   }
>   
> +void target_configure_write_atomic_from_bdev(struct se_dev_attrib *attrib,
> +					     struct block_device *bdev)
> +{
> +	struct request_queue *q = bdev_get_queue(bdev);
> +	int block_size = bdev_logical_block_size(bdev);
> +
> +	if (!bdev_can_atomic_write(bdev))
> +		return;
> +
> +	attrib->atomic_supported = true;
> +	attrib->atomic_max_len = queue_atomic_write_max_bytes(q) / block_size;
> +	attrib->atomic_granularity = queue_atomic_write_unit_min_bytes(q) /
> +								block_size;
> +	attrib->atomic_max_with_boundary = 0;
> +	attrib->atomic_max_boundary = 0;
> +}
> +EXPORT_SYMBOL_GPL(target_configure_write_atomic_from_bdev);
> +
>   /*
>    * Check if the underlying struct block_device supports discard and if yes
>    * configure the UNMAP parameters.
> diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
> index d394306f8f49..e32de80854b6 100644
> --- a/include/target/target_core_backend.h
> +++ b/include/target/target_core_backend.h
> @@ -123,6 +123,8 @@ bool target_sense_desc_format(struct se_device *dev);
>   sector_t target_to_linux_sector(struct se_device *dev, sector_t lb);
>   bool target_configure_unmap_from_bdev(struct se_dev_attrib *attrib,
>   				      struct block_device *bdev);
> +void target_configure_write_atomic_from_bdev(struct se_dev_attrib *attrib,
> +					     struct block_device *bdev);
>   
>   static inline bool target_dev_configured(struct se_device *se_dev)
>   {


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 4/7] scsi: target: Add WRITE_ATOMIC_16 handler
  2024-10-08  2:03 ` [PATCH 4/7] scsi: target: Add WRITE_ATOMIC_16 handler Mike Christie
  2024-10-09  6:10   ` kernel test robot
@ 2025-05-14 10:47   ` John Garry
  2025-07-20 22:44     ` Mike Christie
  1 sibling, 1 reply; 23+ messages in thread
From: John Garry @ 2025-05-14 10:47 UTC (permalink / raw)
  To: Mike Christie, martin.petersen, linux-scsi, target-devel

On 08/10/2024 03:03, Mike Christie wrote:
> This adds the core LIO code to process the WRITE_ATOMIC_16 command.
> 
> Signed-off-by: Mike Christie <michael.christie@oracle.com>
> ---
>   drivers/target/target_core_sbc.c  | 48 +++++++++++++++++++++++++++++++
>   include/target/target_core_base.h |  1 +
>   2 files changed, 49 insertions(+)
> 
> diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
> index fe8beb7dbab1..0ae0d4ec0ac3 100644
> --- a/drivers/target/target_core_sbc.c
> +++ b/drivers/target/target_core_sbc.c
> @@ -764,6 +764,46 @@ sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
>   	return 0;
>   }
>   
> +static int
> +sbc_check_atomic(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
> +{
> +	struct se_dev_attrib *attrib = &dev->dev_attrib;
> +	u16 boundary, transfer_len;
> +	u32 lba;
> +
> +	if (!attrib->atomic_supported)
> +		return TCM_UNSUPPORTED_SCSI_OPCODE;
> +
> +	lba = transport_lba_32(cdb);

should this be 64, not 32?

> +	boundary = get_unaligned_be16(&cdb[10]);
> +	transfer_len = get_unaligned_be16(&cdb[12]);
> +
> +	if (!boundary) {
> +		if (transfer_len > attrib->atomic_max_len)
> +			return TCM_INVALID_CDB_FIELD;

from sbc4r22 4.29.1, the key is ILLEGAL_REQUEST and sense code is 
INVALID CDB FIELD, but is it possible to have the field pointer set to 
the TRANSFER LENGTH in the CDB?

> +	} else {

earlier we have no boundary support, so we should reject any IO with a 
boundary set, right? From a glance at sbc4r22 4.29.1, that's my take

> +		if (transfer_len > attrib->atomic_max_with_boundary)
> +			return TCM_INVALID_CDB_FIELD;
> +
> +		if (boundary > attrib->atomic_max_boundary)
> +			return TCM_INVALID_CDB_FIELD;
> +	}
> +
> +	if (attrib->atomic_granularity) {
> +		if (transfer_len % attrib->atomic_granularity)
> +			return TCM_INVALID_CDB_FIELD;
> +
> +		if (boundary && boundary % attrib->atomic_granularity)
> +			return TCM_INVALID_CDB_FIELD;
> +	}
> +
> +	if (dev->dev_attrib.atomic_alignment &&
> +	    lba % dev->dev_attrib.atomic_alignment)
> +		return TCM_INVALID_CDB_FIELD;
> +
> +	return 0;
> +}
> +
>   sense_reason_t
>   sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops)
>   {
> @@ -861,6 +901,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops)
>   		break;
>   	case WRITE_16:
>   	case WRITE_VERIFY_16:
> +	case WRITE_ATOMIC_16:
>   		sectors = transport_get_sectors_16(cdb);
>   		cmd->t_task_lba = transport_lba_64(cdb);
>   
> @@ -872,6 +913,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops)
>   			return ret;
>   
>   		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
> +		if (cdb[0] == WRITE_ATOMIC_16) {
> +			cmd->se_cmd_flags |= SCF_ATOMIC;
> +
> +			ret = sbc_check_atomic(dev, cmd, cdb);
> +			if (ret)
> +				return ret;
> +		}
>   		cmd->execute_cmd = sbc_execute_rw;
>   		break;
>   	case VARIABLE_LENGTH_CMD:
> diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
> index 6c87bd018983..7b8ed21bea03 100644
> --- a/include/target/target_core_base.h
> +++ b/include/target/target_core_base.h
> @@ -157,6 +157,7 @@ enum se_cmd_flags_table {
>   	SCF_USE_CPUID				= (1 << 16),
>   	SCF_TASK_ATTR_SET			= (1 << 17),
>   	SCF_TREAT_READ_AS_NORMAL		= (1 << 18),
> +	SCF_ATOMIC				= (1 << 19),
>   };
>   
>   /*


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 5/7] scsi: target: Report atomic values in INQUIRY
  2024-10-08  2:03 ` [PATCH 5/7] scsi: target: Report atomic values in INQUIRY Mike Christie
@ 2025-05-14 10:56   ` John Garry
  2025-07-20 22:42     ` Mike Christie
  0 siblings, 1 reply; 23+ messages in thread
From: John Garry @ 2025-05-14 10:56 UTC (permalink / raw)
  To: Mike Christie, martin.petersen, linux-scsi, target-devel

> -	 */
> +	put_unaligned_be16(12, &buf[2]);
> +
>   	if (!have_tp)
> -		goto max_write_same;
> +		goto try_atomic;
>   
>   	/*
>   	 * Set MAXIMUM UNMAP LBA COUNT
> @@ -595,9 +593,29 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
>   	/*
>   	 * MAXIMUM WRITE SAME LENGTH
>   	 */
> -max_write_same:
>   	put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]);
>   
> +	put_unaligned_be16(40, &buf[2]);
> +
> +try_atomic:
> +	/*
> +	 * ATOMIC
> +	 */
> +	if (!dev->dev_attrib.atomic_supported)
> +		goto done;
 > +> +	if (dev->dev_attrib.atomic_max_len < io_max_blocks)
> +		put_unaligned_be32(dev->dev_attrib.atomic_max_len, &buf[44]);
> +	else
> +		put_unaligned_be32(io_max_blocks, &buf[44]);
> +
> +	put_unaligned_be32(dev->dev_attrib.atomic_alignment, &buf[48]);
> +	put_unaligned_be32(dev->dev_attrib.atomic_granularity, &buf[52]);
> +	put_unaligned_be32(dev->dev_attrib.atomic_max_with_boundary, &buf[56]);
> +	put_unaligned_be32(dev->dev_attrib.atomic_max_boundary, &buf[60]);
> +
> +	put_unaligned_be16(60, &buf[2]);

this is the page length, right? if so, can we always report 60 and 
ensure that the atomics and other fields are 0 when they should be? Or 
does that violate the spec?

> +done:
>   	return 0;
>   }
>   


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 7/7] scsi: target: Add atomic support to target_core_iblock
  2024-10-08  2:03 ` [PATCH 7/7] scsi: target: Add atomic support to target_core_iblock Mike Christie
@ 2025-05-14 11:01   ` John Garry
  0 siblings, 0 replies; 23+ messages in thread
From: John Garry @ 2025-05-14 11:01 UTC (permalink / raw)
  To: Mike Christie, martin.petersen, linux-scsi, target-devel

On 08/10/2024 03:03, Mike Christie wrote:
> This has target_core_iblock use the LIO helper function to translate its
> block_device atomic settings to LIO settings. If we then get a write
> that LIO has indicated is atomic via the SCF_ATOMIC flag, we use the
> REQ_ATOMIC flag to tell the block layer to perform an atomic write.
> 
> Signed-off-by: Mike Christie<michael.christie@oracle.com>

Reviewed-by: John Garry <john.g.garry@oracle.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/7] scsi: target: Rename target_configure_unmap_from_queue
  2024-10-08  2:03 ` [PATCH 1/7] scsi: target: Rename target_configure_unmap_from_queue Mike Christie
@ 2025-05-14 11:11   ` John Garry
  0 siblings, 0 replies; 23+ messages in thread
From: John Garry @ 2025-05-14 11:11 UTC (permalink / raw)
  To: Mike Christie, martin.petersen, linux-scsi, target-devel

On 08/10/2024 03:03, Mike Christie wrote:
> Rename target_configure_unmap_from_queue to
> target_configure_unmap_from_bdev since it now takes a bdev.
> 
> Signed-off-by: Mike Christie<michael.christie@oracle.com>

Reviewed-by: John Garry <john.g.garry@oracle.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/7] scsi: target: Add atomic se_device fields
  2025-05-14 10:26   ` John Garry
@ 2025-07-20 22:15     ` Mike Christie
  2025-07-23 11:28       ` John Garry
  0 siblings, 1 reply; 23+ messages in thread
From: Mike Christie @ 2025-07-20 22:15 UTC (permalink / raw)
  To: John Garry, martin.petersen, linux-scsi, target-devel

On 5/14/25 5:26 AM, John Garry wrote:
> On 08/10/2024 03:03, Mike Christie wrote:
>> This adds atomic fields to the se_device and exports them in configfs.
>>
>> Initially only target_core_iblock will be supported and we will inherit
>> all the settings from the block layer except the alignment which userspace
>> will set.
>>
>> Signed-off-by: Mike Christie <michael.christie@oracle.com>
>> ---
>>   drivers/target/target_core_configfs.c | 42 +++++++++++++++++++++++++++
>>   include/target/target_core_base.h     |  6 ++++
>>   2 files changed, 48 insertions(+)
>>
>> diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
>> index c40217f44b1b..f3c7da650f65 100644
>> --- a/drivers/target/target_core_configfs.c
>> +++ b/drivers/target/target_core_configfs.c
>> @@ -578,6 +578,12 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data);
>>   DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len);
>>   DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc);
>>   DEF_CONFIGFS_ATTRIB_SHOW(submit_type);
>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_supported);
>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_alignment);
>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_len);
>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_granularity);
>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_with_boundary);
>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_boundary);
>>     #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name)                \
>>   static ssize_t _name##_store(struct config_item *item, const char *page,\
>> @@ -1266,6 +1272,30 @@ static ssize_t submit_type_store(struct config_item *item, const char *page,
>>       return count;
>>   }
>>   +static ssize_t atomic_alignment_store(struct config_item *item,
>> +                      const char *page, size_t count)
> 
> What is special about alignment that we need to be able to configure this?
> 
> Won't that be derived from the block device queue_limits (like granularity)?

What if you are not using a physical block device like using LIO's ramdisk mode
to perform testing?

> 
>> +{
>> +    struct se_dev_attrib *da = to_attrib(item);
>> +    u32 val;
>> +    int ret;
>> +
>> +    ret = kstrtou32(page, 0, &val);
>> +    if (ret < 0)
>> +        return ret;
>> +
>> +    if (da->da_dev->export_count) {
>> +        pr_err("dev[%p]: Unable to change SE Device atomic_alignment while export_count is %d\n",
>> +               da->da_dev, da->da_dev->export_count);
>> +        return -EINVAL;
>> +    }
>> +
>> +    da->atomic_alignment = val;
>> +
>> +    pr_debug("dev[%p]: SE Device atomic_alignment changed to %u\n",
>> +         da->da_dev, val);
>> +    return count;
>> +}
>> +
>>   CONFIGFS_ATTR(, emulate_model_alias);
>>   CONFIGFS_ATTR(, emulate_dpo);
>>   CONFIGFS_ATTR(, emulate_fua_write);
>> @@ -1302,6 +1332,12 @@ CONFIGFS_ATTR(, max_write_same_len);
>>   CONFIGFS_ATTR(, alua_support);
>>   CONFIGFS_ATTR(, pgr_support);
>>   CONFIGFS_ATTR(, submit_type);
>> +CONFIGFS_ATTR(, atomic_alignment);
>> +CONFIGFS_ATTR_RO(, atomic_supported);
> 
> isn't a non-zero atomic_max_len the same thing as this?


I separated it because like above I was thinking maybe users will want to
use this to do some testing. So I tried to make it more generic.



> 
>> +CONFIGFS_ATTR_RO(, atomic_max_len);
>> +CONFIGFS_ATTR_RO(, atomic_granularity);
>> +CONFIGFS_ATTR_RO(, atomic_max_with_boundary);
>> +CONFIGFS_ATTR_RO(, atomic_max_boundary);
>>     /*
>>    * dev_attrib attributes for devices using the target core SBC/SPC
>> @@ -1345,6 +1381,12 @@ struct configfs_attribute *sbc_attrib_attrs[] = {
>>       &attr_pgr_support,
>>       &attr_emulate_rsoc,
>>       &attr_submit_type,
>> +    &attr_atomic_supported,
>> +    &attr_atomic_alignment,
>> +    &attr_atomic_max_len,
>> +    &attr_atomic_granularity,
>> +    &attr_atomic_max_with_boundary,
>> +    &attr_atomic_max_boundary,
>>       NULL,
>>   };
>>   EXPORT_SYMBOL(sbc_attrib_attrs);
>> diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
>> index 97099a5e3f6c..6c87bd018983 100644
>> --- a/include/target/target_core_base.h
>> +++ b/include/target/target_core_base.h
>> @@ -715,6 +715,7 @@ struct se_dev_attrib {
>>       bool        is_nonrot;
>>       bool        emulate_rest_reord;
>>       bool        unmap_zeroes_data;
>> +    bool        atomic_supported;
>>       u32        hw_block_size;
>>       u32        block_size;
>>       u32        hw_max_sectors;
>> @@ -726,6 +727,11 @@ struct se_dev_attrib {
>>       u32        unmap_granularity;
>>       u32        unmap_granularity_alignment;
>>       u32        max_write_same_len;
>> +    u32        atomic_max_len;
>> +    u32        atomic_alignment;
>> +    u32        atomic_granularity;
>> +    u32        atomic_max_with_boundary;
>> +    u32        atomic_max_boundary;
> 
> these will always be zero, right? I don't see much point in even storing them.
> 
If you use target_core_iblock yes. If you use some other backend then
it will be what's set in configfs.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 5/7] scsi: target: Report atomic values in INQUIRY
  2025-05-14 10:56   ` John Garry
@ 2025-07-20 22:42     ` Mike Christie
  0 siblings, 0 replies; 23+ messages in thread
From: Mike Christie @ 2025-07-20 22:42 UTC (permalink / raw)
  To: John Garry, martin.petersen, linux-scsi, target-devel

On 5/14/25 5:56 AM, John Garry wrote:
>>
>> +    put_unaligned_be16(60, &buf[2]);
> 
> this is the page length, right? if so, can we always report 60 and ensure that the atomics and other fields are 0 when they should be? Or does that violate the spec?

I think it was something on the initiator side does not like that
where it uses 0 for the value instead of a OS's default.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 4/7] scsi: target: Add WRITE_ATOMIC_16 handler
  2025-05-14 10:47   ` John Garry
@ 2025-07-20 22:44     ` Mike Christie
  0 siblings, 0 replies; 23+ messages in thread
From: Mike Christie @ 2025-07-20 22:44 UTC (permalink / raw)
  To: John Garry, martin.petersen, linux-scsi, target-devel

On 5/14/25 5:47 AM, John Garry wrote:
> On 08/10/2024 03:03, Mike Christie wrote:
>> This adds the core LIO code to process the WRITE_ATOMIC_16 command.
>>
>> Signed-off-by: Mike Christie <michael.christie@oracle.com>
>> ---
>>   drivers/target/target_core_sbc.c  | 48 +++++++++++++++++++++++++++++++
>>   include/target/target_core_base.h |  1 +
>>   2 files changed, 49 insertions(+)
>>
>> diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
>> index fe8beb7dbab1..0ae0d4ec0ac3 100644
>> --- a/drivers/target/target_core_sbc.c
>> +++ b/drivers/target/target_core_sbc.c
>> @@ -764,6 +764,46 @@ sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
>>       return 0;
>>   }
>>   +static int
>> +sbc_check_atomic(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
>> +{
>> +    struct se_dev_attrib *attrib = &dev->dev_attrib;
>> +    u16 boundary, transfer_len;
>> +    u32 lba;
>> +
>> +    if (!attrib->atomic_supported)
>> +        return TCM_UNSUPPORTED_SCSI_OPCODE;
>> +
>> +    lba = transport_lba_32(cdb);
> 
> should this be 64, not 32?
> 

Yeah will fix.

>> +    boundary = get_unaligned_be16(&cdb[10]);
>> +    transfer_len = get_unaligned_be16(&cdb[12]);
>> +
>> +    if (!boundary) {
>> +        if (transfer_len > attrib->atomic_max_len)
>> +            return TCM_INVALID_CDB_FIELD;
> 
> from sbc4r22 4.29.1, the key is ILLEGAL_REQUEST and sense code is INVALID CDB FIELD, but is it possible to have the field pointer set to the TRANSFER LENGTH in the CDB?

I can. Will do.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/7] scsi: target: Add atomic se_device fields
  2025-07-20 22:15     ` Mike Christie
@ 2025-07-23 11:28       ` John Garry
  2025-07-23 15:10         ` michael.christie
  0 siblings, 1 reply; 23+ messages in thread
From: John Garry @ 2025-07-23 11:28 UTC (permalink / raw)
  To: Mike Christie, martin.petersen, linux-scsi, target-devel

On 20/07/2025 23:15, Mike Christie wrote:
> On 5/14/25 5:26 AM, John Garry wrote:
>> On 08/10/2024 03:03, Mike Christie wrote:
>>> This adds atomic fields to the se_device and exports them in configfs.
>>>
>>> Initially only target_core_iblock will be supported and we will inherit
>>> all the settings from the block layer except the alignment which userspace
>>> will set.
>>>
>>> Signed-off-by: Mike Christie <michael.christie@oracle.com>
>>> ---
>>>    drivers/target/target_core_configfs.c | 42 +++++++++++++++++++++++++++
>>>    include/target/target_core_base.h     |  6 ++++
>>>    2 files changed, 48 insertions(+)
>>>
>>> diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
>>> index c40217f44b1b..f3c7da650f65 100644
>>> --- a/drivers/target/target_core_configfs.c
>>> +++ b/drivers/target/target_core_configfs.c
>>> @@ -578,6 +578,12 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data);
>>>    DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len);
>>>    DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc);
>>>    DEF_CONFIGFS_ATTRIB_SHOW(submit_type);
>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_supported);
>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_alignment);
>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_len);
>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_granularity);
>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_with_boundary);
>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_boundary);
>>>      #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name)                \
>>>    static ssize_t _name##_store(struct config_item *item, const char *page,\
>>> @@ -1266,6 +1272,30 @@ static ssize_t submit_type_store(struct config_item *item, const char *page,
>>>        return count;
>>>    }
>>>    +static ssize_t atomic_alignment_store(struct config_item *item,
>>> +                      const char *page, size_t count)
>>
>> What is special about alignment that we need to be able to configure this?
>>
>> Won't that be derived from the block device queue_limits (like granularity)?
> 
> What if you are not using a physical block device like using LIO's ramdisk mode
> to perform testing?

But would this non-physical device still need to support atomics? I 
would assume so.



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/7] scsi: target: Add atomic se_device fields
  2025-07-23 11:28       ` John Garry
@ 2025-07-23 15:10         ` michael.christie
  2025-07-23 15:48           ` michael.christie
  0 siblings, 1 reply; 23+ messages in thread
From: michael.christie @ 2025-07-23 15:10 UTC (permalink / raw)
  To: John Garry, martin.petersen, linux-scsi, target-devel

On 7/23/25 6:28 AM, John Garry wrote:
> On 20/07/2025 23:15, Mike Christie wrote:
>> On 5/14/25 5:26 AM, John Garry wrote:
>>> On 08/10/2024 03:03, Mike Christie wrote:
>>>> This adds atomic fields to the se_device and exports them in configfs.
>>>>
>>>> Initially only target_core_iblock will be supported and we will inherit
>>>> all the settings from the block layer except the alignment which
>>>> userspace
>>>> will set.
>>>>
>>>> Signed-off-by: Mike Christie <michael.christie@oracle.com>
>>>> ---
>>>>    drivers/target/target_core_configfs.c | 42 ++++++++++++++++++++++
>>>> +++++
>>>>    include/target/target_core_base.h     |  6 ++++
>>>>    2 files changed, 48 insertions(+)
>>>>
>>>> diff --git a/drivers/target/target_core_configfs.c b/drivers/target/
>>>> target_core_configfs.c
>>>> index c40217f44b1b..f3c7da650f65 100644
>>>> --- a/drivers/target/target_core_configfs.c
>>>> +++ b/drivers/target/target_core_configfs.c
>>>> @@ -578,6 +578,12 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data);
>>>>    DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len);
>>>>    DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc);
>>>>    DEF_CONFIGFS_ATTRIB_SHOW(submit_type);
>>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_supported);
>>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_alignment);
>>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_len);
>>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_granularity);
>>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_with_boundary);
>>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_boundary);
>>>>      #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name)                \
>>>>    static ssize_t _name##_store(struct config_item *item, const char
>>>> *page,\
>>>> @@ -1266,6 +1272,30 @@ static ssize_t submit_type_store(struct
>>>> config_item *item, const char *page,
>>>>        return count;
>>>>    }
>>>>    +static ssize_t atomic_alignment_store(struct config_item *item,
>>>> +                      const char *page, size_t count)
>>>
>>> What is special about alignment that we need to be able to configure
>>> this?
>>>
>>> Won't that be derived from the block device queue_limits (like
>>> granularity)?
>>
>> What if you are not using a physical block device like using LIO's
>> ramdisk mode
>> to perform testing?
> 
> But would this non-physical device still need to support atomics? I
> would assume so.

It depends. For just a testing mode not necessarily. It can be relaxed
so you can test different scenarios like you want to test when atomics
are not supported correctly. For real support yes.

But just to be clear for either case, there won't always be a
request_queue/block_device. For example, rd and tcmu don't use
target_configure_write_atomic_from_bdev, so the atomic values can be
whatever they want to support.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/7] scsi: target: Add atomic se_device fields
  2025-07-23 15:10         ` michael.christie
@ 2025-07-23 15:48           ` michael.christie
  2025-07-23 16:21             ` John Garry
  0 siblings, 1 reply; 23+ messages in thread
From: michael.christie @ 2025-07-23 15:48 UTC (permalink / raw)
  To: John Garry, martin.petersen, linux-scsi, target-devel

On 7/23/25 10:10 AM, michael.christie@oracle.com wrote:
> On 7/23/25 6:28 AM, John Garry wrote:
>> On 20/07/2025 23:15, Mike Christie wrote:
>>> On 5/14/25 5:26 AM, John Garry wrote:
>>>> On 08/10/2024 03:03, Mike Christie wrote:
>>>>> This adds atomic fields to the se_device and exports them in configfs.
>>>>>
>>>>> Initially only target_core_iblock will be supported and we will inherit
>>>>> all the settings from the block layer except the alignment which
>>>>> userspace
>>>>> will set.
>>>>>
>>>>> Signed-off-by: Mike Christie <michael.christie@oracle.com>
>>>>> ---
>>>>>    drivers/target/target_core_configfs.c | 42 ++++++++++++++++++++++
>>>>> +++++
>>>>>    include/target/target_core_base.h     |  6 ++++
>>>>>    2 files changed, 48 insertions(+)
>>>>>
>>>>> diff --git a/drivers/target/target_core_configfs.c b/drivers/target/
>>>>> target_core_configfs.c
>>>>> index c40217f44b1b..f3c7da650f65 100644
>>>>> --- a/drivers/target/target_core_configfs.c
>>>>> +++ b/drivers/target/target_core_configfs.c
>>>>> @@ -578,6 +578,12 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data);
>>>>>    DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len);
>>>>>    DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc);
>>>>>    DEF_CONFIGFS_ATTRIB_SHOW(submit_type);
>>>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_supported);
>>>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_alignment);
>>>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_len);
>>>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_granularity);
>>>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_with_boundary);
>>>>> +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_boundary);
>>>>>      #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name)                \
>>>>>    static ssize_t _name##_store(struct config_item *item, const char
>>>>> *page,\
>>>>> @@ -1266,6 +1272,30 @@ static ssize_t submit_type_store(struct
>>>>> config_item *item, const char *page,
>>>>>        return count;
>>>>>    }
>>>>>    +static ssize_t atomic_alignment_store(struct config_item *item,
>>>>> +                      const char *page, size_t count)
>>>>
>>>> What is special about alignment that we need to be able to configure
>>>> this?
>>>>
>>>> Won't that be derived from the block device queue_limits (like
>>>> granularity)?
>>>
>>> What if you are not using a physical block device like using LIO's
>>> ramdisk mode
>>> to perform testing?
>>
>> But would this non-physical device still need to support atomics? I
>> would assume so.
> 
> It depends. For just a testing mode not necessarily. It can be relaxed
> so you can test different scenarios like you want to test when atomics
> are not supported correctly. For real support yes.
> 
> But just to be clear for either case, there won't always be a
> request_queue/block_device. For example, rd and tcmu don't use
> target_configure_write_atomic_from_bdev, so the atomic values can be
> whatever they want to support.

I think I misunderstood the last comment.

I'm trying to make sure I can support a broken device for testing so I
tried to make as flexible as possible.

With the code as is though I think your concern in the last comment is
that a user could set some valid settings, use rd/tcmu, and think they
were safe when they are not. If so, then I agree that can happen.

Or are you saying even for broken device simulation that we will never
need to set values like alignment above?

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/7] scsi: target: Add atomic se_device fields
  2025-07-23 15:48           ` michael.christie
@ 2025-07-23 16:21             ` John Garry
  2025-07-23 19:38               ` michael.christie
  0 siblings, 1 reply; 23+ messages in thread
From: John Garry @ 2025-07-23 16:21 UTC (permalink / raw)
  To: michael.christie, martin.petersen, linux-scsi, target-devel

On 23/07/2025 16:48, michael.christie@oracle.com wrote:
>>>> What if you are not using a physical block device like using LIO's
>>>> ramdisk mode
>>>> to perform testing?
>>> But would this non-physical device still need to support atomics? I
>>> would assume so.
>> It depends. For just a testing mode not necessarily. It can be relaxed
>> so you can test different scenarios like you want to test when atomics
>> are not supported correctly. For real support yes.
>>
>> But just to be clear for either case, there won't always be a
>> request_queue/block_device. For example, rd and tcmu don't use
>> target_configure_write_atomic_from_bdev, so the atomic values can be
>> whatever they want to support.

If that is acceptable, then I am curious why only make alignment 
configurable (and not the other params)? From below, it seems that you 
have some special device to support.

> I think I misunderstood the last comment.
> 
> I'm trying to make sure I can support a broken device for testing so I
> tried to make as flexible as possible.
> 
> With the code as is though I think your concern in the last comment is
> that a user could set some valid settings, use rd/tcmu, and think they
> were safe when they are not. If so, then I agree that can happen.
> 
> Or are you saying even for broken device simulation that we will never
> need to set values like alignment above?

I suppose that we can set alignment for broken devices, yes.

I'll make a couple of points about scsi alignment as it is a bit 
special. Firstly the alignment should be compatible with the atomic 
write unit min. atomic write unit min comes from the granularity/pbs. So 
the granularity/pbs needs to be compatible with alignment.

A further point is that if a partition is not aligned on the atomic 
write unit min boundary, then atomic writes are disabled for that bdev 
partition.



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/7] scsi: target: Add atomic se_device fields
  2025-07-23 16:21             ` John Garry
@ 2025-07-23 19:38               ` michael.christie
  0 siblings, 0 replies; 23+ messages in thread
From: michael.christie @ 2025-07-23 19:38 UTC (permalink / raw)
  To: John Garry, martin.petersen, linux-scsi, target-devel

On 7/23/25 11:21 AM, John Garry wrote:
> On 23/07/2025 16:48, michael.christie@oracle.com wrote:
>>>>> What if you are not using a physical block device like using LIO's
>>>>> ramdisk mode
>>>>> to perform testing?
>>>> But would this non-physical device still need to support atomics? I
>>>> would assume so.
>>> It depends. For just a testing mode not necessarily. It can be relaxed
>>> so you can test different scenarios like you want to test when atomics
>>> are not supported correctly. For real support yes.
>>>
>>> But just to be clear for either case, there won't always be a
>>> request_queue/block_device. For example, rd and tcmu don't use
>>> target_configure_write_atomic_from_bdev, so the atomic values can be
>>> whatever they want to support.
> 
> If that is acceptable, then I am curious why only make alignment
> configurable (and not the other params)? From below, it seems that you
> have some special device to support.
> 

Oh I completely misunderstood you :) I see what you were asking. I think
it was just a mistake.

>> I think I misunderstood the last comment.
>>
>> I'm trying to make sure I can support a broken device for testing so I
>> tried to make as flexible as possible.
>>
>> With the code as is though I think your concern in the last comment is
>> that a user could set some valid settings, use rd/tcmu, and think they
>> were safe when they are not. If so, then I agree that can happen.
>>
>> Or are you saying even for broken device simulation that we will never
>> need to set values like alignment above?
> 
> I suppose that we can set alignment for broken devices, yes.
> 
> I'll make a couple of points about scsi alignment as it is a bit
> special. Firstly the alignment should be compatible with the atomic
> write unit min. atomic write unit min comes from the granularity/pbs. So
> the granularity/pbs needs to be compatible with alignment.
> 
> A further point is that if a partition is not aligned on the atomic
> write unit min boundary, then atomic writes are disabled for that bdev
> partition.

I didn't completely understand these 2 paragraphs. Are you saying you
want me to enforce this type of thing somewhere. How does the info above
come into play if we are testing against other OSs for example?

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2025-07-23 19:38 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-08  2:03 [PATCH 0/7] scsi: target: Add WRITE_ATOMIC_16 support Mike Christie
2024-10-08  2:03 ` [PATCH 1/7] scsi: target: Rename target_configure_unmap_from_queue Mike Christie
2025-05-14 11:11   ` John Garry
2024-10-08  2:03 ` [PATCH 2/7] scsi: target: Add atomic se_device fields Mike Christie
2025-05-14 10:26   ` John Garry
2025-07-20 22:15     ` Mike Christie
2025-07-23 11:28       ` John Garry
2025-07-23 15:10         ` michael.christie
2025-07-23 15:48           ` michael.christie
2025-07-23 16:21             ` John Garry
2025-07-23 19:38               ` michael.christie
2024-10-08  2:03 ` [PATCH 3/7] scsi: target: Add helper to setup atomic values from block_device Mike Christie
2025-05-14 10:29   ` John Garry
2024-10-08  2:03 ` [PATCH 4/7] scsi: target: Add WRITE_ATOMIC_16 handler Mike Christie
2024-10-09  6:10   ` kernel test robot
2025-05-14 10:47   ` John Garry
2025-07-20 22:44     ` Mike Christie
2024-10-08  2:03 ` [PATCH 5/7] scsi: target: Report atomic values in INQUIRY Mike Christie
2025-05-14 10:56   ` John Garry
2025-07-20 22:42     ` Mike Christie
2024-10-08  2:03 ` [PATCH 6/7] scsi: target: Add WRITE_ATOMIC_16 support to RSOC Mike Christie
2024-10-08  2:03 ` [PATCH 7/7] scsi: target: Add atomic support to target_core_iblock Mike Christie
2025-05-14 11:01   ` John Garry

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).