@@ -2064,6 +2064,21 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
sense_reason_t ret = TCM_NO_SENSE;
int pr_holder = 0, type;
+ if (dev->transport->pr_ops && dev->transport->pr_ops->pr_register
+ && dev->passthrough_pr) {
+ bool ignore_existing;
+
+ if (register_type == REGISTER_AND_IGNORE_EXISTING_KEY)
+ ignore_existing = true;
+ else
+ ignore_existing = false;
+ ret = dev->transport->pr_ops->pr_register(cmd, res_key,
+ sa_res_key, aptpl,
+ all_tg_pt, spec_i_pt,
+ ignore_existing);
+ return ret;
+ }
+
if (!se_sess || !se_lun) {
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -3707,6 +3722,7 @@ core_scsi3_pri_read_keys(struct se_cmd *cmd)
struct t10_pr_registration *pr_reg;
unsigned char *buf;
u32 add_len = 0, off = 8;
+ sense_reason_t ret = 0;
if (cmd->data_length < 8) {
pr_err("PRIN SA READ_KEYS SCSI Data Length: %u"
@@ -3718,6 +3734,13 @@ core_scsi3_pri_read_keys(struct se_cmd *cmd)
if (!buf)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ if (dev->transport->pr_ops && dev->transport->pr_ops->pr_read_keys
+ && dev->passthrough_pr) {
+ ret = dev->transport->pr_ops->pr_read_keys(cmd, buf,
+ cmd->data_length);
+ return ret;
+ }
+
put_unaligned_be32(dev->t10_pr.pr_generation, buf);
spin_lock(&dev->t10_pr.registration_lock);
@@ -49,6 +49,8 @@
#define PR_APTPL_MAX_IPORT_LEN 256
#define PR_APTPL_MAX_TPORT_LEN 256
+#define PASSTHROUGH_PR_SUPPORT 1
+
/*
* Function defined in target_core_spc.c
*/
@@ -2955,6 +2955,21 @@ tcmu_execute_pr_read_keys(struct se_cmd *cmd, unsigned char *buf, u32 buf_len)
return TCM_NO_SENSE;
}
+/*
+ * This function can help to check wheterh the device support
+ * pass through PR operations. Now only Ceph RBD support
+ * passthrough PR. When someday we have another kind of
+ * device can support passthrough PR, we can easily add
+ * a line like ret |= !strncmp(udev->dev_config, "qcow/", 5);
+ */
+static int is_passthrough_pr_supportive_dev(struct tcmu_dev *udev)
+{
+ int ret = 0;
+
+ ret |= !strncmp(udev->dev_config, "rbd/", 4);
+ return ret;
+}
+
static int tcmu_configure_device(struct se_device *dev)
{
struct tcmu_dev *udev = TCMU_DEV(dev);
@@ -3046,6 +3061,11 @@ static int tcmu_configure_device(struct se_device *dev)
list_add(&udev->node, &root_udev);
mutex_unlock(&root_udev_mutex);
+ if (is_passthrough_pr_supportive_dev(udev) && dev->transport->pr_ops) {
+ mutex_init(&udev->pr_info.pr_info_lock);
+ dev->passthrough_pr = PASSTHROUGH_PR_SUPPORT;
+ }
+
return 0;
err_netlink:
@@ -825,6 +825,13 @@ struct se_device {
/* For se_lun->lun_se_dev RCU read-side critical access */
u32 hba_index;
struct rcu_head rcu_head;
+ /*
+ * For now, only Ceph RBD support pass through PR operations,
+ * others like QCOW can not support this yet, so we need this
+ * int to indicate whether we can send pass through PR message
+ * to userspace.
+ */
+ int passthrough_pr;
};
struct se_hba {
This patch added a function is_passthrough_pr_supportive_dev() to tell whether the device can support passthrough Persistent Reservation, if supported, tcmu_configure_device() will set 1 to dev->passthrough_pr to indicate it. If dev->passthrough_pr is 1, both dev->transport->pr_ops and dev->transport->pr_ops->pr_register are not NULL, core_scsi3_emulate_pro_register() will call dev->transport->pr_ops->pr_register, this means call tcmu_execute_pr_register(). It is the same way how core_scsi3_pri_read_keys() can call tcmu_execute_pr_read_keys. Signed-off-by: Zhu Lingshan <lszhu@suse.com> --- drivers/target/target_core_pr.c | 23 +++++++++++++++++++++++ drivers/target/target_core_pr.h | 2 ++ drivers/target/target_core_user.c | 20 ++++++++++++++++++++ include/target/target_core_base.h | 7 +++++++ 4 files changed, 52 insertions(+)