diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2015-02-28 01:05:21 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2015-04-08 02:25:59 -0400 |
commit | 38b57f82f66dfb21ebe321d71c84c0e3469980c4 (patch) | |
tree | c5e5727d222617a6c59013f0b597b47e4f3dd9ce /drivers/target | |
parent | 823ddd877f3a5c301490196d369f68baa6c020e4 (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.c | 44 | ||||
-rw-r--r-- | drivers/target/target_core_transport.c | 8 |
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 | ||
583 | static int | 583 | static int |
584 | sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type, | 584 | sbc_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. |