Add path_pr_ops structure with callbacks. Since PR ops are related to mpath_disk, add new structure type scsi_mpath_pr_ops, which allows PR ops be executed for a scsi_device.
Since PR are related to mpath_disk, provide scsi_driver member to allow scsi_disk driver set it PR ops calllback. Signed-off-by: John Garry <[email protected]> --- drivers/scsi/scsi_multipath.c | 110 ++++++++++++++++++++++++++++++++++ include/scsi/scsi_driver.h | 1 + include/scsi/scsi_multipath.h | 17 ++++++ 3 files changed, 128 insertions(+) diff --git a/drivers/scsi/scsi_multipath.c b/drivers/scsi/scsi_multipath.c index 73afcbaf2d7de..1489c7e979167 100644 --- a/drivers/scsi/scsi_multipath.c +++ b/drivers/scsi/scsi_multipath.c @@ -381,6 +381,115 @@ static bool scsi_mpath_available_path(struct mpath_device *mpath_device, bool *a return scsi_device_online(sdev); } +static int scsi_mpath_pr_register(struct mpath_device *mpath_device, + u64 old_key, u64 new_key, u32 flags) +{ + struct scsi_mpath_device *scsi_mpath_dev = + to_scsi_mpath_device(mpath_device); + struct scsi_device *sdev = scsi_mpath_dev->sdev; + struct scsi_driver *drv = to_scsi_driver(sdev->sdev_gendev.driver); + + if (!drv->mpath_pr_ops) + return -EOPNOTSUPP; + + return drv->mpath_pr_ops->pr_register(sdev, old_key, new_key, flags); +} + +static int scsi_mpath_pr_reserve(struct mpath_device *mpath_device, u64 key, + enum pr_type type, u32 flags) +{ + struct scsi_mpath_device *scsi_mpath_dev = + to_scsi_mpath_device(mpath_device); + struct scsi_device *sdev = scsi_mpath_dev->sdev; + struct scsi_driver *drv = to_scsi_driver(sdev->sdev_gendev.driver); + + if (!drv->mpath_pr_ops) + return -EOPNOTSUPP; + + return drv->mpath_pr_ops->pr_reserve(sdev, key, type, flags); +} + +static int scsi_mpath_pr_release(struct mpath_device *mpath_device, u64 key, + enum pr_type type) +{ + struct scsi_mpath_device *scsi_mpath_dev = + to_scsi_mpath_device(mpath_device); + struct scsi_device *sdev = scsi_mpath_dev->sdev; + struct scsi_driver *drv = to_scsi_driver(sdev->sdev_gendev.driver); + + if (!drv->mpath_pr_ops) + return -EOPNOTSUPP; + + return drv->mpath_pr_ops->pr_release(sdev, key, type); +} + +static int scsi_mpath_pr_preempt(struct mpath_device *mpath_device, + u64 old_key, u64 new_key, enum pr_type type, + bool abort) +{ + struct scsi_mpath_device *scsi_mpath_dev = + to_scsi_mpath_device(mpath_device); + struct scsi_device *sdev = scsi_mpath_dev->sdev; + struct scsi_driver *drv = to_scsi_driver(sdev->sdev_gendev.driver); + + if (!drv->mpath_pr_ops) + return -EOPNOTSUPP; + + return drv->mpath_pr_ops->pr_preempt(sdev, old_key, new_key, + type, abort); +} + +static int scsi_mpath_pr_clear(struct mpath_device *mpath_device, u64 key) +{ + struct scsi_mpath_device *scsi_mpath_dev = + to_scsi_mpath_device(mpath_device); + struct scsi_device *sdev = scsi_mpath_dev->sdev; + struct scsi_driver *drv = to_scsi_driver(sdev->sdev_gendev.driver); + + if (!drv->mpath_pr_ops) + return -EOPNOTSUPP; + + return drv->mpath_pr_ops->pr_clear(sdev, key); +} + +static int scsi_mpath_pr_read_keys(struct mpath_device *mpath_device, + struct pr_keys *keys_info) +{ + struct scsi_mpath_device *scsi_mpath_dev = + to_scsi_mpath_device(mpath_device); + struct scsi_device *sdev = scsi_mpath_dev->sdev; + struct scsi_driver *drv = to_scsi_driver(sdev->sdev_gendev.driver); + + if (!drv->mpath_pr_ops) + return -EOPNOTSUPP; + + return drv->mpath_pr_ops->pr_read_keys(sdev, keys_info); +} + +static int scsi_mpath_pr_read_reservation(struct mpath_device *mpath_device, + struct pr_held_reservation *rsv) +{ + struct scsi_mpath_device *scsi_mpath_dev = + to_scsi_mpath_device(mpath_device); + struct scsi_device *sdev = scsi_mpath_dev->sdev; + struct scsi_driver *drv = to_scsi_driver(sdev->sdev_gendev.driver); + + if (!drv->mpath_pr_ops) + return -EOPNOTSUPP; + + return drv->mpath_pr_ops->pr_read_reservation(sdev, rsv); +} + +static const struct mpath_pr_ops scsi_mpath_pr_ops = { + .pr_register = scsi_mpath_pr_register, + .pr_reserve = scsi_mpath_pr_reserve, + .pr_release = scsi_mpath_pr_release, + .pr_preempt = scsi_mpath_pr_preempt, + .pr_clear = scsi_mpath_pr_clear, + .pr_read_keys = scsi_mpath_pr_read_keys, + .pr_read_reservation = scsi_mpath_pr_read_reservation, +}; + struct mpath_head_template smpdt_pr = { .is_disabled = scsi_mpath_is_disabled, .is_optimized = scsi_mpath_is_optimized, @@ -389,6 +498,7 @@ struct mpath_head_template smpdt_pr = { .available_path = scsi_mpath_available_path, .get_iopolicy = scsi_mpath_get_iopolicy, .clone_bio = scsi_mpath_clone_bio, + .pr_ops = &scsi_mpath_pr_ops, .device_groups = mpath_device_groups, }; diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h index 799071b8bdee2..2aaa5d270d818 100644 --- a/include/scsi/scsi_driver.h +++ b/include/scsi/scsi_driver.h @@ -25,6 +25,7 @@ struct scsi_driver { int (*mpath_ioctl)(struct scsi_device *sdev, blk_mode_t mode, unsigned int cmd, unsigned long arg); struct mpath_disk *(*to_mpath_disk)(struct request *); + const struct scsi_mpath_pr_ops *mpath_pr_ops; #endif }; #define to_scsi_driver(drv) \ diff --git a/include/scsi/scsi_multipath.h b/include/scsi/scsi_multipath.h index 6cb3107260952..cb63c6536b854 100644 --- a/include/scsi/scsi_multipath.h +++ b/include/scsi/scsi_multipath.h @@ -40,6 +40,23 @@ struct scsi_mpath_device { char device_id_str[SCSI_MPATH_DEVICE_ID_LEN]; }; + +struct scsi_mpath_pr_ops { + int (*pr_register)(struct scsi_device *, u64 old_key, + u64 new_key, u32 flags); + int (*pr_reserve)(struct scsi_device *e, u64 key, + enum pr_type type, u32 flags); + int (*pr_release)(struct scsi_device *, u64 key, + enum pr_type type); + int (*pr_preempt)(struct scsi_device *, u64 old_key, + u64 new_key, enum pr_type type, bool abort); + int (*pr_clear)(struct scsi_device *, u64 key); + int (*pr_read_keys)(struct scsi_device *, + struct pr_keys *keys_info); + int (*pr_read_reservation)(struct scsi_device *, + struct pr_held_reservation *rsv); +}; + #define to_scsi_mpath_device(d) \ container_of(d, struct scsi_mpath_device, mpath_device) -- 2.43.5

