[PATCH 15/24] scsi: sd: refactor PR ops

From: John Garry

Date: Wed Feb 25 2026 - 10:50:22 EST


Refactor each PR op into a helper which accepts a scsi_disk, as this is
require for supporting scsi-multipath PR ops. For scsi-multipath, the
multipath PR ops are passed a mpath_device, which can be converted to
a scsi_disk pointer (which we are providing an API for here).

Signed-off-by: John Garry <john.g.garry@xxxxxxxxxx>
---
drivers/scsi/sd.c | 88 ++++++++++++++++++++++++++++++++++++++---------
1 file changed, 71 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index f50b92e632018..cea3ab54c4417 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1958,10 +1958,9 @@ static int sd_scsi_to_pr_err(struct scsi_sense_hdr *sshdr, int result)
}
}

-static int sd_pr_in_command(struct block_device *bdev, u8 sa,
+static int sd_pr_in_command(struct scsi_disk *sdkp, u8 sa,
unsigned char *data, int data_len)
{
- struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
struct scsi_device *sdev = sdkp->device;
struct scsi_sense_hdr sshdr;
u8 cmd[10] = { PERSISTENT_RESERVE_IN, sa };
@@ -2000,7 +1999,8 @@ static int sd_pr_in_command(struct block_device *bdev, u8 sa,
return sd_scsi_to_pr_err(&sshdr, result);
}

-static int sd_pr_read_keys(struct block_device *bdev, struct pr_keys *keys_info)
+static int sd_pr_read_keys_disk(struct scsi_disk *sdkp,
+ struct pr_keys *keys_info)
{
int result, i, data_offset, num_copy_keys;
u32 num_keys = keys_info->num_keys;
@@ -2021,7 +2021,7 @@ static int sd_pr_read_keys(struct block_device *bdev, struct pr_keys *keys_info)
if (!data)
return -ENOMEM;

- result = sd_pr_in_command(bdev, READ_KEYS, data, data_len);
+ result = sd_pr_in_command(sdkp, READ_KEYS, data, data_len);
if (result)
goto free_data;

@@ -2041,15 +2041,22 @@ static int sd_pr_read_keys(struct block_device *bdev, struct pr_keys *keys_info)
return result;
}

-static int sd_pr_read_reservation(struct block_device *bdev,
- struct pr_held_reservation *rsv)
+static int sd_pr_read_keys(struct block_device *bdev,
+ struct pr_keys *keys_info)
{
struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
+
+ return sd_pr_read_keys_disk(sdkp, keys_info);
+}
+
+static int sd_pr_read_reservation_disk(struct scsi_disk *sdkp,
+ struct pr_held_reservation *rsv)
+{
struct scsi_device *sdev = sdkp->device;
u8 data[24] = { };
int result, len;

- result = sd_pr_in_command(bdev, READ_RESERVATION, data, sizeof(data));
+ result = sd_pr_in_command(sdkp, READ_RESERVATION, data, sizeof(data));
if (result)
return result;

@@ -2070,11 +2077,17 @@ static int sd_pr_read_reservation(struct block_device *bdev,
rsv->type = scsi_pr_type_to_block(data[21] & 0x0f);
return 0;
}
+static int sd_pr_read_reservation(struct block_device *bdev,
+ struct pr_held_reservation *rsv)
+{
+ struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);

-static int sd_pr_out_command(struct block_device *bdev, u8 sa, u64 key,
+ return sd_pr_read_reservation_disk(sdkp, rsv);
+}
+
+static int sd_pr_out_command(struct scsi_disk *sdkp, u8 sa, u64 key,
u64 sa_key, enum scsi_pr_type type, u8 flags)
{
- struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
struct scsi_device *sdev = sdkp->device;
struct scsi_sense_hdr sshdr;
struct scsi_failure failure_defs[] = {
@@ -2123,41 +2136,82 @@ static int sd_pr_out_command(struct block_device *bdev, u8 sa, u64 key,
return sd_scsi_to_pr_err(&sshdr, result);
}

-static int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
+static int sd_pr_register_disk(struct scsi_disk *sdkp, u64 old_key, u64 new_key,
u32 flags)
{
if (flags & ~PR_FL_IGNORE_KEY)
return -EOPNOTSUPP;
- return sd_pr_out_command(bdev, (flags & PR_FL_IGNORE_KEY) ? 0x06 : 0x00,
+
+ return sd_pr_out_command(sdkp,
+ (flags & PR_FL_IGNORE_KEY) ? 0x06 : 0x00,
old_key, new_key, 0,
(1 << 0) /* APTPL */);
}

-static int sd_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type,
+static int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
u32 flags)
+{
+ struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
+
+ return sd_pr_register_disk(sdkp, old_key, new_key, flags);
+}
+
+static int sd_pr_reserve_disk(struct scsi_disk *sdkp, u64 key,
+ enum pr_type type, u32 flags)
{
if (flags)
return -EOPNOTSUPP;
- return sd_pr_out_command(bdev, 0x01, key, 0,
+ return sd_pr_out_command(sdkp, 0x01, key, 0,
+ block_pr_type_to_scsi(type), 0);
+}
+
+static int sd_pr_reserve(struct block_device *bdev, u64 key,
+ enum pr_type type, u32 flags)
+{
+ struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
+
+ return sd_pr_reserve_disk(sdkp, key, type, flags);
+}
+
+static int sd_pr_release_disk(struct scsi_disk *sdkp, u64 key,
+ enum pr_type type)
+{
+ return sd_pr_out_command(sdkp, 0x02, key, 0,
block_pr_type_to_scsi(type), 0);
}

static int sd_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
{
- return sd_pr_out_command(bdev, 0x02, key, 0,
+ struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
+
+ return sd_pr_release_disk(sdkp, key, type);
+}
+
+static int sd_pr_preempt_disk(struct scsi_disk *sdkp, u64 old_key, u64 new_key,
+ enum pr_type type, bool abort)
+{
+ return sd_pr_out_command(sdkp, abort ? 0x05 : 0x04, old_key, new_key,
block_pr_type_to_scsi(type), 0);
}

static int sd_pr_preempt(struct block_device *bdev, u64 old_key, u64 new_key,
enum pr_type type, bool abort)
{
- return sd_pr_out_command(bdev, abort ? 0x05 : 0x04, old_key, new_key,
- block_pr_type_to_scsi(type), 0);
+ struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
+
+ return sd_pr_preempt_disk(sdkp, old_key, new_key, type, abort);
+}
+
+static int sd_pr_clear_disk(struct scsi_disk *sdkp, u64 key)
+{
+ return sd_pr_out_command(sdkp, 0x03, key, 0, 0, 0);
}

static int sd_pr_clear(struct block_device *bdev, u64 key)
{
- return sd_pr_out_command(bdev, 0x03, key, 0, 0, 0);
+ struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
+
+ return sd_pr_clear_disk(sdkp, key);
}

static const struct pr_ops sd_pr_ops = {
--
2.43.5