[PATCH 1/2] scsi: scsi_debug: handle protection information for WRITE ATOMIC(16)

From: Tal Zussman

Date: Tue Nov 10 2026 - 15:49:24 EST


resp_atomic_write() writes the data but ignores the protection
information sent with the command, so the blocks keep the tags of their
previous contents and reading them back fails the guard check.

With scsi_debug loaded with dif=1 dix=1 atomic_wr=1, every RWF_ATOMIC
write that overwrites a block makes it unreadable, so xfstests
generic/770 fails on XFS.

Make resp_atomic_write() write through __resp_write_dt0() like WRITE
does, passing a new atomic argument down to do_device_access(). The
protection information is then verified and stored under the meta write
lock before the data is copied, as it is for WRITE.

Fixes: 84f3a3c01d70 ("scsi: scsi_debug: Atomic write support")
Signed-off-by: Tal Zussman <tz2294@xxxxxxxxxxxx>
---
drivers/scsi/scsi_debug.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index a922c8318a2f..7d5065039637 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -5175,7 +5175,8 @@ static int __resp_write_dt0_dix(struct scsi_cmnd *scp,
static int __resp_write_dt0(struct scsi_cmnd *scp,
struct sdebug_dev_info *devip,
struct sdeb_store_info *sip, u64 lba, u32 num,
- u32 ei_lba, u8 group, bool lbp, int *scsi_status)
+ u32 ei_lba, u8 group, bool lbp, bool atomic,
+ int *scsi_status)
{
int ret;

@@ -5191,7 +5192,7 @@ static int __resp_write_dt0(struct scsi_cmnd *scp,
return ret;
}

- ret = do_device_access(sip, scp, 0, lba, num, group, true, false);
+ ret = do_device_access(sip, scp, 0, lba, num, group, true, atomic);
if (ret < 0)
*scsi_status = DID_ERROR << 16;

@@ -5286,11 +5287,11 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
(sdebug_dix && scsi_prot_sg_count(scp)) || lbp) {
sdeb_meta_write_lock(sip);
ret = __resp_write_dt0(scp, devip, sip, lba, num, ei_lba, group,
- lbp, &scsi_status);
+ lbp, false, &scsi_status);
sdeb_meta_write_unlock(sip);
} else {
ret = __resp_write_dt0(scp, devip, sip, lba, num, ei_lba, group,
- lbp, &scsi_status);
+ lbp, false, &scsi_status);
}

if (unlikely(-1 == ret))
@@ -6328,6 +6329,7 @@ static int resp_atomic_write(struct scsi_cmnd *scp,
u16 boundary, len;
u64 lba, lba_tmp;
bool lbp = scsi_debug_lbp();
+ int scsi_status = DID_ERROR << 16;
int ret;

if (!scsi_debug_atomic_write()) {
@@ -6384,17 +6386,18 @@ static int resp_atomic_write(struct scsi_cmnd *scp,
if (scsi_bufflen(scp) < len * sdebug_sector_size)
return DID_ERROR << 16;

- if (lbp) {
+ if ((sdebug_dix && scsi_prot_sg_count(scp)) || lbp) {
sdeb_meta_write_lock(sip);
- ret = do_device_access(sip, scp, 0, lba, len, 0, true, true);
- map_region(sip, lba, len);
+ ret = __resp_write_dt0(scp, devip, sip, lba, len, 0, 0, lbp,
+ true, &scsi_status);
sdeb_meta_write_unlock(sip);
} else {
- ret = do_device_access(sip, scp, 0, lba, len, 0, true, true);
+ ret = __resp_write_dt0(scp, devip, sip, lba, len, 0, 0, lbp,
+ true, &scsi_status);
}

if (unlikely(ret < 0))
- return DID_ERROR << 16;
+ return scsi_status;
if (unlikely(ret != len * sdebug_sector_size))
return DID_ERROR << 16;


--
2.39.5