aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2015-02-28 01:05:21 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2015-04-08 02:25:59 -0400
commit38b57f82f66dfb21ebe321d71c84c0e3469980c4 (patch)
treec5e5727d222617a6c59013f0b597b47e4f3dd9ce /drivers/target
parent823ddd877f3a5c301490196d369f68baa6c020e4 (diff)
target: Add protected fabric + unprotected device support
This patch adds a new target_core_fabric_ops callback for allowing fabric drivers to expose a TPG attribute for signaling when a T10-PI protected fabric wants to function with an un-protected device without T10-PI. This specifically is to allow LIO to perform WRITE_STRIP + READ_INSERT operations when functioning with non T10-PI enabled devices, seperate from any available hw offloads the fabric supports. This is done using a new se_sess->sess_prot_type that is set at fabric session creation time based upon the TPG attribute. It currently cannot be changed for individual sessions after initial creation. Also, update existing target_core_sbc.c code to honor sess_prot_type when setting up cmd->prot_op + cmd->prot_type assignments. (Add unlikely and !! boolean conversion in sbc_check_prot - Sagi) Cc: Martin Petersen <martin.petersen@oracle.com> Cc: Sagi Grimberg <sagig@mellanox.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Doug Gilbert <dgilbert@interlog.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_sbc.c44
-rw-r--r--drivers/target/target_core_transport.c8
2 files changed, 41 insertions, 11 deletions
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 95a7a7444965..9efd1fd985ee 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -581,12 +581,13 @@ sbc_compare_and_write(struct se_cmd *cmd)
581} 581}
582 582
583static int 583static int
584sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type, 584sbc_set_prot_op_checks(u8 protect, bool fabric_prot, enum target_prot_type prot_type,
585 bool is_write, struct se_cmd *cmd) 585 bool is_write, struct se_cmd *cmd)
586{ 586{
587 if (is_write) { 587 if (is_write) {
588 cmd->prot_op = protect ? TARGET_PROT_DOUT_PASS : 588 cmd->prot_op = fabric_prot ? TARGET_PROT_DOUT_STRIP :
589 TARGET_PROT_DOUT_INSERT; 589 protect ? TARGET_PROT_DOUT_PASS :
590 TARGET_PROT_DOUT_INSERT;
590 switch (protect) { 591 switch (protect) {
591 case 0x0: 592 case 0x0:
592 case 0x3: 593 case 0x3:
@@ -610,8 +611,9 @@ sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type,
610 return -EINVAL; 611 return -EINVAL;
611 } 612 }
612 } else { 613 } else {
613 cmd->prot_op = protect ? TARGET_PROT_DIN_PASS : 614 cmd->prot_op = fabric_prot ? TARGET_PROT_DIN_INSERT :
614 TARGET_PROT_DIN_STRIP; 615 protect ? TARGET_PROT_DIN_PASS :
616 TARGET_PROT_DIN_STRIP;
615 switch (protect) { 617 switch (protect) {
616 case 0x0: 618 case 0x0:
617 case 0x1: 619 case 0x1:
@@ -644,11 +646,15 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
644 u32 sectors, bool is_write) 646 u32 sectors, bool is_write)
645{ 647{
646 u8 protect = cdb[1] >> 5; 648 u8 protect = cdb[1] >> 5;
649 int sp_ops = cmd->se_sess->sup_prot_ops;
650 int pi_prot_type = dev->dev_attrib.pi_prot_type;
651 bool fabric_prot = false;
647 652
648 if (!cmd->t_prot_sg || !cmd->t_prot_nents) { 653 if (!cmd->t_prot_sg || !cmd->t_prot_nents) {
649 if (protect && !dev->dev_attrib.pi_prot_type) { 654 if (unlikely(protect &&
650 pr_err("CDB contains protect bit, but device does not" 655 !dev->dev_attrib.pi_prot_type && !cmd->se_sess->sess_prot_type)) {
651 " advertise PROTECT=1 feature bit\n"); 656 pr_err("CDB contains protect bit, but device + fabric does"
657 " not advertise PROTECT=1 feature bit\n");
652 return TCM_INVALID_CDB_FIELD; 658 return TCM_INVALID_CDB_FIELD;
653 } 659 }
654 if (cmd->prot_pto) 660 if (cmd->prot_pto)
@@ -669,15 +675,28 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
669 cmd->reftag_seed = cmd->t_task_lba; 675 cmd->reftag_seed = cmd->t_task_lba;
670 break; 676 break;
671 case TARGET_DIF_TYPE0_PROT: 677 case TARGET_DIF_TYPE0_PROT:
678 /*
679 * See if the fabric supports T10-PI, and the session has been
680 * configured to allow export PROTECT=1 feature bit with backend
681 * devices that don't support T10-PI.
682 */
683 fabric_prot = is_write ?
684 !!(sp_ops & (TARGET_PROT_DOUT_PASS | TARGET_PROT_DOUT_STRIP)) :
685 !!(sp_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DIN_INSERT));
686
687 if (fabric_prot && cmd->se_sess->sess_prot_type) {
688 pi_prot_type = cmd->se_sess->sess_prot_type;
689 break;
690 }
691 /* Fallthrough */
672 default: 692 default:
673 return TCM_NO_SENSE; 693 return TCM_NO_SENSE;
674 } 694 }
675 695
676 if (sbc_set_prot_op_checks(protect, dev->dev_attrib.pi_prot_type, 696 if (sbc_set_prot_op_checks(protect, fabric_prot, pi_prot_type, is_write, cmd))
677 is_write, cmd))
678 return TCM_INVALID_CDB_FIELD; 697 return TCM_INVALID_CDB_FIELD;
679 698
680 cmd->prot_type = dev->dev_attrib.pi_prot_type; 699 cmd->prot_type = pi_prot_type;
681 cmd->prot_length = dev->prot_length * sectors; 700 cmd->prot_length = dev->prot_length * sectors;
682 701
683 /** 702 /**
@@ -1231,6 +1250,9 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read,
1231 unsigned int i, len, left; 1250 unsigned int i, len, left;
1232 unsigned int offset = sg_off; 1251 unsigned int offset = sg_off;
1233 1252
1253 if (!sg)
1254 return;
1255
1234 left = sectors * dev->prot_length; 1256 left = sectors * dev->prot_length;
1235 1257
1236 for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) { 1258 for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) {
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 4a00ed5c1880..aef989e165ed 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -322,11 +322,19 @@ void __transport_register_session(
322 struct se_session *se_sess, 322 struct se_session *se_sess,
323 void *fabric_sess_ptr) 323 void *fabric_sess_ptr)
324{ 324{
325 struct target_core_fabric_ops *tfo = se_tpg->se_tpg_tfo;
325 unsigned char buf[PR_REG_ISID_LEN]; 326 unsigned char buf[PR_REG_ISID_LEN];
326 327
327 se_sess->se_tpg = se_tpg; 328 se_sess->se_tpg = se_tpg;
328 se_sess->fabric_sess_ptr = fabric_sess_ptr; 329 se_sess->fabric_sess_ptr = fabric_sess_ptr;
329 /* 330 /*
331 * Determine if fabric allows for T10-PI feature bits to be exposed
332 * to initiators for device backends with !dev->dev_attrib.pi_prot_type
333 */
334 if (tfo->tpg_check_prot_fabric_only)
335 se_sess->sess_prot_type = tfo->tpg_check_prot_fabric_only(se_tpg);
336
337 /*
330 * Used by struct se_node_acl's under ConfigFS to locate active se_session-t 338 * Used by struct se_node_acl's under ConfigFS to locate active se_session-t
331 * 339 *
332 * Only set for struct se_session's that will actually be moving I/O. 340 * Only set for struct se_session's that will actually be moving I/O.