Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Target/sbc: Set protection operation and relevant checks

SBC-3 mandates the protection checks that must be
performed in the rdprotect/wrprotect field. Use them.
According to backstore device pi_attributes and
cdb rdprotect/wrprotect field.

(Fix incorrect se_cmd->prot_type -> TARGET_PROT_NORMAL
comparision in transport_generic_new_cmd - nab)
(Fix missing break in sbc_set_prot_op_checks - DanC + Sagi)

Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

authored by

Sagi Grimberg and committed by
Nicholas Bellinger
19f9361a acb2bde3

+81 -15
+73 -14
drivers/target/target_core_sbc.c
··· 569 569 return TCM_NO_SENSE; 570 570 } 571 571 572 + static int 573 + sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type, 574 + bool is_write, struct se_cmd *cmd) 575 + { 576 + if (is_write) { 577 + cmd->prot_op = protect ? TARGET_PROT_DOUT_PASS : 578 + TARGET_PROT_DOUT_INSERT; 579 + switch (protect) { 580 + case 0x0: 581 + case 0x3: 582 + cmd->prot_checks = 0; 583 + break; 584 + case 0x1: 585 + case 0x5: 586 + cmd->prot_checks = TARGET_DIF_CHECK_GUARD; 587 + if (prot_type == TARGET_DIF_TYPE1_PROT) 588 + cmd->prot_checks |= TARGET_DIF_CHECK_REFTAG; 589 + break; 590 + case 0x2: 591 + if (prot_type == TARGET_DIF_TYPE1_PROT) 592 + cmd->prot_checks = TARGET_DIF_CHECK_REFTAG; 593 + break; 594 + case 0x4: 595 + cmd->prot_checks = TARGET_DIF_CHECK_GUARD; 596 + break; 597 + default: 598 + pr_err("Unsupported protect field %d\n", protect); 599 + return -EINVAL; 600 + } 601 + } else { 602 + cmd->prot_op = protect ? TARGET_PROT_DIN_PASS : 603 + TARGET_PROT_DIN_STRIP; 604 + switch (protect) { 605 + case 0x0: 606 + case 0x1: 607 + case 0x5: 608 + cmd->prot_checks = TARGET_DIF_CHECK_GUARD; 609 + if (prot_type == TARGET_DIF_TYPE1_PROT) 610 + cmd->prot_checks |= TARGET_DIF_CHECK_REFTAG; 611 + break; 612 + case 0x2: 613 + if (prot_type == TARGET_DIF_TYPE1_PROT) 614 + cmd->prot_checks = TARGET_DIF_CHECK_REFTAG; 615 + break; 616 + case 0x3: 617 + cmd->prot_checks = 0; 618 + break; 619 + case 0x4: 620 + cmd->prot_checks = TARGET_DIF_CHECK_GUARD; 621 + break; 622 + default: 623 + pr_err("Unsupported protect field %d\n", protect); 624 + return -EINVAL; 625 + } 626 + } 627 + 628 + return 0; 629 + } 630 + 572 631 static bool 573 632 sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, 574 - u32 sectors) 633 + u32 sectors, bool is_write) 575 634 { 635 + u8 protect = cdb[1] >> 5; 636 + 576 637 if (!cmd->t_prot_sg || !cmd->t_prot_nents) 577 638 return true; 578 639 579 640 switch (dev->dev_attrib.pi_prot_type) { 580 641 case TARGET_DIF_TYPE3_PROT: 581 - if (!(cdb[1] & 0xe0)) 582 - return true; 583 - 584 642 cmd->reftag_seed = 0xffffffff; 585 643 break; 586 644 case TARGET_DIF_TYPE2_PROT: 587 - if (cdb[1] & 0xe0) 645 + if (protect) 588 646 return false; 589 647 590 648 cmd->reftag_seed = cmd->t_task_lba; 591 649 break; 592 650 case TARGET_DIF_TYPE1_PROT: 593 - if (!(cdb[1] & 0xe0)) 594 - return true; 595 - 596 651 cmd->reftag_seed = cmd->t_task_lba; 597 652 break; 598 653 case TARGET_DIF_TYPE0_PROT: 599 654 default: 600 655 return true; 601 656 } 657 + 658 + if (sbc_set_prot_op_checks(protect, dev->dev_attrib.pi_prot_type, 659 + is_write, cmd)) 660 + return false; 602 661 603 662 cmd->prot_type = dev->dev_attrib.pi_prot_type; 604 663 cmd->prot_length = dev->prot_length * sectors; ··· 687 628 sectors = transport_get_sectors_10(cdb); 688 629 cmd->t_task_lba = transport_lba_32(cdb); 689 630 690 - if (!sbc_check_prot(dev, cmd, cdb, sectors)) 631 + if (!sbc_check_prot(dev, cmd, cdb, sectors, false)) 691 632 return TCM_UNSUPPORTED_SCSI_OPCODE; 692 633 693 634 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; ··· 698 639 sectors = transport_get_sectors_12(cdb); 699 640 cmd->t_task_lba = transport_lba_32(cdb); 700 641 701 - if (!sbc_check_prot(dev, cmd, cdb, sectors)) 642 + if (!sbc_check_prot(dev, cmd, cdb, sectors, false)) 702 643 return TCM_UNSUPPORTED_SCSI_OPCODE; 703 644 704 645 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; ··· 709 650 sectors = transport_get_sectors_16(cdb); 710 651 cmd->t_task_lba = transport_lba_64(cdb); 711 652 712 - if (!sbc_check_prot(dev, cmd, cdb, sectors)) 653 + if (!sbc_check_prot(dev, cmd, cdb, sectors, false)) 713 654 return TCM_UNSUPPORTED_SCSI_OPCODE; 714 655 715 656 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; ··· 728 669 sectors = transport_get_sectors_10(cdb); 729 670 cmd->t_task_lba = transport_lba_32(cdb); 730 671 731 - if (!sbc_check_prot(dev, cmd, cdb, sectors)) 672 + if (!sbc_check_prot(dev, cmd, cdb, sectors, true)) 732 673 return TCM_UNSUPPORTED_SCSI_OPCODE; 733 674 734 675 if (cdb[1] & 0x8) ··· 741 682 sectors = transport_get_sectors_12(cdb); 742 683 cmd->t_task_lba = transport_lba_32(cdb); 743 684 744 - if (!sbc_check_prot(dev, cmd, cdb, sectors)) 685 + if (!sbc_check_prot(dev, cmd, cdb, sectors, true)) 745 686 return TCM_UNSUPPORTED_SCSI_OPCODE; 746 687 747 688 if (cdb[1] & 0x8) ··· 754 695 sectors = transport_get_sectors_16(cdb); 755 696 cmd->t_task_lba = transport_lba_64(cdb); 756 697 757 - if (!sbc_check_prot(dev, cmd, cdb, sectors)) 698 + if (!sbc_check_prot(dev, cmd, cdb, sectors, true)) 758 699 return TCM_UNSUPPORTED_SCSI_OPCODE; 759 700 760 701 if (cdb[1] & 0x8)
+1 -1
drivers/target/target_core_transport.c
··· 2206 2206 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 2207 2207 } 2208 2208 2209 - if (cmd->prot_type != TARGET_PROT_NORMAL) { 2209 + if (cmd->prot_op != TARGET_PROT_NORMAL) { 2210 2210 ret = target_alloc_sgl(&cmd->t_prot_sg, 2211 2211 &cmd->t_prot_nents, 2212 2212 cmd->prot_length, true);
+7
include/target/target_core_base.h
··· 463 463 TARGET_DIF_TYPE3_PROT, 464 464 }; 465 465 466 + enum target_core_dif_check { 467 + TARGET_DIF_CHECK_GUARD = 0x1 << 0, 468 + TARGET_DIF_CHECK_APPTAG = 0x1 << 1, 469 + TARGET_DIF_CHECK_REFTAG = 0x1 << 2, 470 + }; 471 + 466 472 struct se_dif_v1_tuple { 467 473 __be16 guard_tag; 468 474 __be16 app_tag; ··· 562 556 /* DIF related members */ 563 557 enum target_prot_op prot_op; 564 558 enum target_prot_type prot_type; 559 + u8 prot_checks; 565 560 u32 prot_length; 566 561 u32 reftag_seed; 567 562 struct scatterlist *t_prot_sg;