target/user: PGR Support
authorBryant G. Ly <bryantly@linux.vnet.ibm.com>
Sat, 22 Apr 2017 01:40:50 +0000 (20:40 -0500)
committerNicholas Bellinger <nab@linux-iscsi.org>
Tue, 2 May 2017 05:21:45 +0000 (22:21 -0700)
This adds initial PGR support for just TCMU, since tcmu doesn't
have the necessary IT_NEXUS info to process PGR in userspace,
so have those commands be processed in kernel.

HA support is not available yet, we will work on it if this patch
is acceptable.

Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_pr.c
drivers/target/target_core_pscsi.c
include/target/target_core_backend.h

index a34a86652b96462fb5ba2345210654c5882d675e..e7b62bc239a7a7d9ae1bddfe4b698db888fadbef 100644 (file)
@@ -1400,7 +1400,7 @@ static ssize_t target_pr_res_holder_show(struct config_item *item, char *page)
        struct se_device *dev = pr_to_dev(item);
        int ret;
 
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
                return sprintf(page, "Passthrough\n");
 
        spin_lock(&dev->dev_reservation_lock);
@@ -1540,7 +1540,7 @@ static ssize_t target_pr_res_type_show(struct config_item *item, char *page)
 {
        struct se_device *dev = pr_to_dev(item);
 
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
                return sprintf(page, "SPC_PASSTHROUGH\n");
        else if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
                return sprintf(page, "SPC2_RESERVATIONS\n");
@@ -1553,7 +1553,7 @@ static ssize_t target_pr_res_aptpl_active_show(struct config_item *item,
 {
        struct se_device *dev = pr_to_dev(item);
 
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
                return 0;
 
        return sprintf(page, "APTPL Bit Status: %s\n",
@@ -1565,7 +1565,7 @@ static ssize_t target_pr_res_aptpl_metadata_show(struct config_item *item,
 {
        struct se_device *dev = pr_to_dev(item);
 
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
                return 0;
 
        return sprintf(page, "Ready to process PR APTPL metadata..\n");
@@ -1611,7 +1611,7 @@ static ssize_t target_pr_res_aptpl_metadata_store(struct config_item *item,
        u16 tpgt = 0;
        u8 type = 0;
 
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
                return count;
        if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
                return count;
index c754ae33bf7b154a5ce368c066ad336f2c4ee5d5..c4845678eb918fa0b0ebda6ef5683111af5684d5 100644 (file)
@@ -1045,6 +1045,8 @@ passthrough_parse_cdb(struct se_cmd *cmd,
        sense_reason_t (*exec_cmd)(struct se_cmd *cmd))
 {
        unsigned char *cdb = cmd->t_task_cdb;
+       struct se_device *dev = cmd->se_dev;
+       unsigned int size;
 
        /*
         * Clear a lun set in the cdb if the initiator talking to use spoke
@@ -1076,6 +1078,42 @@ passthrough_parse_cdb(struct se_cmd *cmd,
                return TCM_NO_SENSE;
        }
 
+       /*
+        * For PERSISTENT RESERVE IN/OUT, RELEASE, and RESERVE we need to
+        * emulate the response, since tcmu does not have the information
+        * required to process these commands.
+        */
+       if (!(dev->transport->transport_flags &
+             TRANSPORT_FLAG_PASSTHROUGH_PGR)) {
+               if (cdb[0] == PERSISTENT_RESERVE_IN) {
+                       cmd->execute_cmd = target_scsi3_emulate_pr_in;
+                       size = (cdb[7] << 8) + cdb[8];
+                       return target_cmd_size_check(cmd, size);
+               }
+               if (cdb[0] == PERSISTENT_RESERVE_OUT) {
+                       cmd->execute_cmd = target_scsi3_emulate_pr_out;
+                       size = (cdb[7] << 8) + cdb[8];
+                       return target_cmd_size_check(cmd, size);
+               }
+
+               if (cdb[0] == RELEASE || cdb[0] == RELEASE_10) {
+                       cmd->execute_cmd = target_scsi2_reservation_release;
+                       if (cdb[0] == RELEASE_10)
+                               size = (cdb[7] << 8) | cdb[8];
+                       else
+                               size = cmd->data_length;
+                       return target_cmd_size_check(cmd, size);
+               }
+               if (cdb[0] == RESERVE || cdb[0] == RESERVE_10) {
+                       cmd->execute_cmd = target_scsi2_reservation_reserve;
+                       if (cdb[0] == RESERVE_10)
+                               size = (cdb[7] << 8) | cdb[8];
+                       else
+                               size = cmd->data_length;
+                       return target_cmd_size_check(cmd, size);
+               }
+       }
+
        /* Set DATA_CDB flag for ops that should have it */
        switch (cdb[0]) {
        case READ_6:
index e18051185846ad2824ed7aef82ea66ca2898d83c..129ca572673ceaed2aa6f4ca55d10bfcd6b1620a 100644 (file)
@@ -4147,7 +4147,7 @@ target_check_reservation(struct se_cmd *cmd)
                return 0;
        if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
                return 0;
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
                return 0;
 
        spin_lock(&dev->dev_reservation_lock);
index 94cda7991e80abbffb32941c8d8f5cfcbd262e3f..8943a62eb203a6ecd0cf4a464bdb9d7e443856f8 100644 (file)
@@ -1081,7 +1081,8 @@ static const struct target_backend_ops pscsi_ops = {
        .name                   = "pscsi",
        .owner                  = THIS_MODULE,
        .transport_flags        = TRANSPORT_FLAG_PASSTHROUGH |
-                                 TRANSPORT_FLAG_PASSTHROUGH_ALUA,
+                                 TRANSPORT_FLAG_PASSTHROUGH_ALUA |
+                                 TRANSPORT_FLAG_PASSTHROUGH_PGR,
        .attach_hba             = pscsi_attach_hba,
        .detach_hba             = pscsi_detach_hba,
        .pmode_enable_hba       = pscsi_pmode_enable_hba,
index 1b0f447ce850f015e64dd27e47751fe945cbb2ec..e475531565fdfb6808de54bf9b4c84de7a501584 100644 (file)
@@ -10,6 +10,7 @@
  * backend module.
  */
 #define TRANSPORT_FLAG_PASSTHROUGH_ALUA                0x2
+#define TRANSPORT_FLAG_PASSTHROUGH_PGR          0x4
 
 struct request_queue;
 struct scatterlist;