On 4/10/2015 9:59 PM, Nicholas A. Bellinger wrote:
On Thu, 2015-04-09 at 17:45 -0400, Martin K. Petersen wrote:
"nab" == Nicholas A Bellinger <n...@linux-iscsi.org> writes:

How do you handle RDPROTECT/WRPROTECT values of 3 if the PI is not
persistent?

nab> AFAICT, this would result in cmd->prot_op = TARGET_PROT_*_PASS and
cmd-> prot_checks = 0 for RDPROTECT/WRPROTECT == 0x3 in
nab> sbc_set_prot_op_checks() code.

nab> Do DOUT_STRIP + DIN_INSERT need to be called if a protection buffer
nab> is present when RDPROTECT/WRPROTECT == 0x3 if fabric_prot was
nab> cleared..?  Or should the command be rejected when a protection
nab> buffer is present + RDPROTECT/WRPROTECT is non-zero if fabric_prot
nab> was cleared..?

Depends how compliant you want to be.

You can synthesize PI with RDPROTECT/WRPROTECT=1 as long as the
initiator doesn't rely on app tag escapes (we don't). Most non-HDD/SSD
targets work this way.


<nod>

I would suggest that you return invalid field in CDB for
RDPROTECT/WRPROTECT=3 unless the PI can be made persistent, however.


Ok, after thinking about this some more, here's what I've come up with..

The following incremental patch saves the current sess_prot_type into
se_node_acl, and will always reset sess_prot_type if a previous saved
value exists.  So the PI setting for the fabric's session with backend
devices not supporting PI is persistent across session restart.

I also noticed the internal DIF emulation was not honoring
se_cmd->prot_checks for the WRPROTECT/RDPROTECT == 0x3 case, so
sbc_dif_v1_verify() has been updated to follow which checks have been
calculated based on WRPROTECT/RDPROTECT in sbc_set_prot_op_checks().

Finally in sbc_check_prot(), if PROTECT is non-zero for a backend device
with DIF disabled, and sess_prot_type is not set go ahead and return
INVALID_CDB_FIELD.

WDYT..?

--nab

diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 315ff64..a75512f 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -697,9 +697,13 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, 
unsigned char *cdb,
                        pi_prot_type = cmd->se_sess->sess_prot_type;
                        break;
                }
+               if (!protect)
+                       return TCM_NO_SENSE;
                /* Fallthrough */
        default:
-               return TCM_NO_SENSE;
+               pr_err("Unable to determine pi_prot_type for CDB: 0x%02x "
+                      "PROTECT: 0x%02x\n", cdb[0], protect);
+               return TCM_INVALID_CDB_FIELD;
        }

        if (sbc_set_prot_op_checks(protect, fabric_prot, pi_prot_type, 
is_write, cmd))
@@ -1221,6 +1227,9 @@ sbc_dif_v1_verify(struct se_cmd *cmd, struct 
se_dif_v1_tuple *sdt,
        int block_size = dev->dev_attrib.block_size;
        __be16 csum;

+       if (!(cmd->prot_checks & TARGET_DIF_CHECK_GUARD))
+               goto check_ref;
+
        csum = cpu_to_be16(crc_t10dif(p, block_size));

        if (sdt->guard_tag != csum) {
@@ -1230,6 +1239,10 @@ sbc_dif_v1_verify(struct se_cmd *cmd, struct 
se_dif_v1_tuple *sdt,
                return TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
        }

+check_ref:
+       if (!(cmd->prot_checks & TARGET_DIF_CHECK_REFTAG))
+               return 0;
+
        if (cmd->prot_type == TARGET_DIF_TYPE1_PROT &&
            be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
                pr_err("DIFv1 Type 1 reference failed on sector: %llu tag: 
0x%08x"
diff --git a/drivers/target/target_core_transport.c 
b/drivers/target/target_core_transport.c
index f884198..3ff38b2 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -329,11 +329,17 @@ void __transport_register_session(
        se_sess->fabric_sess_ptr = fabric_sess_ptr;
        /*
         * Determine if fabric allows for T10-PI feature bits to be exposed
-        * to initiators for device backends with !dev->dev_attrib.pi_prot_type
+        * to initiators for device backends with !dev->dev_attrib.pi_prot_type.
+        *
+        * If so, then always save prot_type on a per se_node_acl node basis
+        * and re-instate the previous sess_prot_type to avoid disabling PI
+        * from below any previously initiator side registered LUNs.
         */
-       if (tfo->tpg_check_prot_fabric_only)
-               se_sess->sess_prot_type = 
tfo->tpg_check_prot_fabric_only(se_tpg);
-
+       if (se_nacl->saved_prot_type)
+               se_sess->sess_prot_type = se_nacl->saved_prot_type;
+       else if (tfo->tpg_check_prot_fabric_only)
+               se_sess->sess_prot_type = se_nacl->saved_prot_type =
+                               tfo->tpg_check_prot_fabric_only(se_tpg);
        /*
         * Used by struct se_node_acl's under ConfigFS to locate active 
se_session-t
         *
diff --git a/include/target/target_core_base.h 
b/include/target/target_core_base.h
index 383110d..51dcf2b 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -590,6 +590,7 @@ struct se_node_acl {
        bool                    acl_stop:1;
        u32                     queue_depth;
        u32                     acl_index;
+       enum target_prot_type   saved_prot_type;
  #define MAX_ACL_TAG_SIZE 64
        char                    acl_tag[MAX_ACL_TAG_SIZE];
        /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */




This looks fine to me.

Acked-by: Sagi Grimberg <sa...@mellanox.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to