target/pr: add target_pr_ops release hook
authorDavid Disseldorp <ddiss@suse.de>
Wed, 26 Aug 2015 18:58:42 +0000 (20:58 +0200)
committerDavid Disseldorp <ddiss@suse.de>
Wed, 26 Aug 2015 20:50:59 +0000 (22:50 +0200)
The new pr_release hook is conditionally invoked on incoming PERSISTENT
RESERVE OUT command with a RELEASE service action. As with RESERVE, the
reservation scope is not passed through to the backend - LU_SCOPE is
validated beforehand.

Signed-off-by: David Disseldorp <ddiss@suse.de>
drivers/target/target_core_pr.c
include/target/target_core_backend.h

index c5f596fac042dc8e112ed6a55b3c3e63accfe435..296877133551031b02424a511fb843ab83345389 100644 (file)
@@ -2554,7 +2554,7 @@ out:
 }
 
 static sense_reason_t
-core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
+core_scsi3_emulate_pro_release_execute(struct se_cmd *cmd, int type, int scope,
                u64 res_key)
 {
        struct se_device *dev = cmd->se_dev;
@@ -2710,6 +2710,26 @@ out_put_pr_reg:
        return ret;
 }
 
+static sense_reason_t
+core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
+               u64 res_key)
+{
+       struct se_device *dev = cmd->se_dev;
+       sense_reason_t ret;
+
+       if (dev->transport->pr_ops && dev->transport->pr_ops->pr_release) {
+               if (scope != PR_SCOPE_LU_SCOPE) {
+                       pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope);
+                       return TCM_INVALID_PARAMETER_LIST;
+               }
+               ret = dev->transport->pr_ops->pr_release(cmd, type, res_key);
+       } else {
+               ret = core_scsi3_emulate_pro_release_execute(cmd, type, scope,
+                                                            res_key);
+       }
+       return ret;
+}
+
 static sense_reason_t
 core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key)
 {
index b61723acf60a4c769f0df148e9d9d9dec02ea7b8..fd1fc37a76f8d3b5a6c1697f99e3827ad69f0782 100644 (file)
@@ -21,6 +21,7 @@ struct target_pr_ops {
                                      u64 new_key, bool aptpl, bool all_tg_pt,
                                      bool spec_i_pt, bool ignore_existing);
        sense_reason_t (*pr_reserve)(struct se_cmd *cmd, int type, u64 key);
+       sense_reason_t (*pr_release)(struct se_cmd *cmd, int type, u64 key);
        /* persistent reservation (in) API not proposed for block layer yet */
        sense_reason_t (*pr_read_keys)(struct se_cmd *cmd, unsigned char *buf,
                                       u32 buf_len);