diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-01-08 13:19:31 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-01-18 04:57:47 -0500 |
commit | 2ed22c9cbca61f0f696a0a1cbbb777da281bd79d (patch) | |
tree | 0cd4084400fedaebb9dd191fcf33c52594d5d71d | |
parent | 0c30f421a7dba0a7ca9a3f67dad15d84d4d61e01 (diff) |
target/configfs: Expose protection device attributes
This patch adds support for exposing DIF protection device
attributes via configfs. This includes:
pi_prot_type: Protection Type (0, 1, 3 currently support)
pi_prot_format: Protection Format Operation (FILEIO only)
Within se_dev_set_pi_prot_type() it also adds the se_subsystem_api
device callbacks to setup per device protection information.
v2 changes:
- Drop pi_guard_type + pi_prot_version related code (MKP)
- Add pi_prot_format logic (Sagi)
- Add ->free_prot callback in target_free_device
- Add hw_pi_prot_type read-only attribute
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Sagi Grimberg <sagig@mellanox.com>
Cc: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r-- | drivers/target/target_core_configfs.c | 12 | ||||
-rw-r--r-- | drivers/target/target_core_device.c | 89 | ||||
-rw-r--r-- | drivers/target/target_core_internal.h | 2 |
3 files changed, 103 insertions, 0 deletions
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 5cf613544eeb..f0e85b119692 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c | |||
@@ -643,6 +643,15 @@ SE_DEV_ATTR(emulate_caw, S_IRUGO | S_IWUSR); | |||
643 | DEF_DEV_ATTRIB(emulate_3pc); | 643 | DEF_DEV_ATTRIB(emulate_3pc); |
644 | SE_DEV_ATTR(emulate_3pc, S_IRUGO | S_IWUSR); | 644 | SE_DEV_ATTR(emulate_3pc, S_IRUGO | S_IWUSR); |
645 | 645 | ||
646 | DEF_DEV_ATTRIB(pi_prot_type); | ||
647 | SE_DEV_ATTR(pi_prot_type, S_IRUGO | S_IWUSR); | ||
648 | |||
649 | DEF_DEV_ATTRIB_RO(hw_pi_prot_type); | ||
650 | SE_DEV_ATTR_RO(hw_pi_prot_type); | ||
651 | |||
652 | DEF_DEV_ATTRIB(pi_prot_format); | ||
653 | SE_DEV_ATTR(pi_prot_format, S_IRUGO | S_IWUSR); | ||
654 | |||
646 | DEF_DEV_ATTRIB(enforce_pr_isids); | 655 | DEF_DEV_ATTRIB(enforce_pr_isids); |
647 | SE_DEV_ATTR(enforce_pr_isids, S_IRUGO | S_IWUSR); | 656 | SE_DEV_ATTR(enforce_pr_isids, S_IRUGO | S_IWUSR); |
648 | 657 | ||
@@ -702,6 +711,9 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = { | |||
702 | &target_core_dev_attrib_emulate_tpws.attr, | 711 | &target_core_dev_attrib_emulate_tpws.attr, |
703 | &target_core_dev_attrib_emulate_caw.attr, | 712 | &target_core_dev_attrib_emulate_caw.attr, |
704 | &target_core_dev_attrib_emulate_3pc.attr, | 713 | &target_core_dev_attrib_emulate_3pc.attr, |
714 | &target_core_dev_attrib_pi_prot_type.attr, | ||
715 | &target_core_dev_attrib_hw_pi_prot_type.attr, | ||
716 | &target_core_dev_attrib_pi_prot_format.attr, | ||
705 | &target_core_dev_attrib_enforce_pr_isids.attr, | 717 | &target_core_dev_attrib_enforce_pr_isids.attr, |
706 | &target_core_dev_attrib_is_nonrot.attr, | 718 | &target_core_dev_attrib_is_nonrot.attr, |
707 | &target_core_dev_attrib_emulate_rest_reord.attr, | 719 | &target_core_dev_attrib_emulate_rest_reord.attr, |
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 32440584ebbb..883099e89020 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
@@ -918,6 +918,90 @@ int se_dev_set_emulate_3pc(struct se_device *dev, int flag) | |||
918 | return 0; | 918 | return 0; |
919 | } | 919 | } |
920 | 920 | ||
921 | int se_dev_set_pi_prot_type(struct se_device *dev, int flag) | ||
922 | { | ||
923 | int rc, old_prot = dev->dev_attrib.pi_prot_type; | ||
924 | |||
925 | if (flag != 0 && flag != 1 && flag != 2 && flag != 3) { | ||
926 | pr_err("Illegal value %d for pi_prot_type\n", flag); | ||
927 | return -EINVAL; | ||
928 | } | ||
929 | if (flag == 2) { | ||
930 | pr_err("DIF TYPE2 protection currently not supported\n"); | ||
931 | return -ENOSYS; | ||
932 | } | ||
933 | if (dev->dev_attrib.hw_pi_prot_type) { | ||
934 | pr_warn("DIF protection enabled on underlying hardware," | ||
935 | " ignoring\n"); | ||
936 | return 0; | ||
937 | } | ||
938 | if (!dev->transport->init_prot || !dev->transport->free_prot) { | ||
939 | pr_err("DIF protection not supported by backend: %s\n", | ||
940 | dev->transport->name); | ||
941 | return -ENOSYS; | ||
942 | } | ||
943 | if (!(dev->dev_flags & DF_CONFIGURED)) { | ||
944 | pr_err("DIF protection requires device to be configured\n"); | ||
945 | return -ENODEV; | ||
946 | } | ||
947 | if (dev->export_count) { | ||
948 | pr_err("dev[%p]: Unable to change SE Device PROT type while" | ||
949 | " export_count is %d\n", dev, dev->export_count); | ||
950 | return -EINVAL; | ||
951 | } | ||
952 | |||
953 | dev->dev_attrib.pi_prot_type = flag; | ||
954 | |||
955 | if (flag && !old_prot) { | ||
956 | rc = dev->transport->init_prot(dev); | ||
957 | if (rc) { | ||
958 | dev->dev_attrib.pi_prot_type = old_prot; | ||
959 | return rc; | ||
960 | } | ||
961 | |||
962 | } else if (!flag && old_prot) { | ||
963 | dev->transport->free_prot(dev); | ||
964 | } | ||
965 | pr_debug("dev[%p]: SE Device Protection Type: %d\n", dev, flag); | ||
966 | |||
967 | return 0; | ||
968 | } | ||
969 | |||
970 | int se_dev_set_pi_prot_format(struct se_device *dev, int flag) | ||
971 | { | ||
972 | int rc; | ||
973 | |||
974 | if (!flag) | ||
975 | return 0; | ||
976 | |||
977 | if (flag != 1) { | ||
978 | pr_err("Illegal value %d for pi_prot_format\n", flag); | ||
979 | return -EINVAL; | ||
980 | } | ||
981 | if (!dev->transport->format_prot) { | ||
982 | pr_err("DIF protection format not supported by backend %s\n", | ||
983 | dev->transport->name); | ||
984 | return -ENOSYS; | ||
985 | } | ||
986 | if (!(dev->dev_flags & DF_CONFIGURED)) { | ||
987 | pr_err("DIF protection format requires device to be configured\n"); | ||
988 | return -ENODEV; | ||
989 | } | ||
990 | if (dev->export_count) { | ||
991 | pr_err("dev[%p]: Unable to format SE Device PROT type while" | ||
992 | " export_count is %d\n", dev, dev->export_count); | ||
993 | return -EINVAL; | ||
994 | } | ||
995 | |||
996 | rc = dev->transport->format_prot(dev); | ||
997 | if (rc) | ||
998 | return rc; | ||
999 | |||
1000 | pr_debug("dev[%p]: SE Device Protection Format complete\n", dev); | ||
1001 | |||
1002 | return 0; | ||
1003 | } | ||
1004 | |||
921 | int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag) | 1005 | int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag) |
922 | { | 1006 | { |
923 | if ((flag != 0) && (flag != 1)) { | 1007 | if ((flag != 0) && (flag != 1)) { |
@@ -1415,6 +1499,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) | |||
1415 | dev->dev_link_magic = SE_DEV_LINK_MAGIC; | 1499 | dev->dev_link_magic = SE_DEV_LINK_MAGIC; |
1416 | dev->se_hba = hba; | 1500 | dev->se_hba = hba; |
1417 | dev->transport = hba->transport; | 1501 | dev->transport = hba->transport; |
1502 | dev->prot_length = sizeof(struct se_dif_v1_tuple); | ||
1418 | 1503 | ||
1419 | INIT_LIST_HEAD(&dev->dev_list); | 1504 | INIT_LIST_HEAD(&dev->dev_list); |
1420 | INIT_LIST_HEAD(&dev->dev_sep_list); | 1505 | INIT_LIST_HEAD(&dev->dev_sep_list); |
@@ -1457,6 +1542,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) | |||
1457 | dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; | 1542 | dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; |
1458 | dev->dev_attrib.emulate_caw = DA_EMULATE_CAW; | 1543 | dev->dev_attrib.emulate_caw = DA_EMULATE_CAW; |
1459 | dev->dev_attrib.emulate_3pc = DA_EMULATE_3PC; | 1544 | dev->dev_attrib.emulate_3pc = DA_EMULATE_3PC; |
1545 | dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE0_PROT; | ||
1460 | dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; | 1546 | dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; |
1461 | dev->dev_attrib.is_nonrot = DA_IS_NONROT; | 1547 | dev->dev_attrib.is_nonrot = DA_IS_NONROT; |
1462 | dev->dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD; | 1548 | dev->dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD; |
@@ -1589,6 +1675,9 @@ void target_free_device(struct se_device *dev) | |||
1589 | core_scsi3_free_all_registrations(dev); | 1675 | core_scsi3_free_all_registrations(dev); |
1590 | se_release_vpd_for_dev(dev); | 1676 | se_release_vpd_for_dev(dev); |
1591 | 1677 | ||
1678 | if (dev->transport->free_prot) | ||
1679 | dev->transport->free_prot(dev); | ||
1680 | |||
1592 | dev->transport->free_device(dev); | 1681 | dev->transport->free_device(dev); |
1593 | } | 1682 | } |
1594 | 1683 | ||
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 1e27614e6bcc..de9cab708f45 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h | |||
@@ -35,6 +35,8 @@ int se_dev_set_emulate_tpu(struct se_device *, int); | |||
35 | int se_dev_set_emulate_tpws(struct se_device *, int); | 35 | int se_dev_set_emulate_tpws(struct se_device *, int); |
36 | int se_dev_set_emulate_caw(struct se_device *, int); | 36 | int se_dev_set_emulate_caw(struct se_device *, int); |
37 | int se_dev_set_emulate_3pc(struct se_device *, int); | 37 | int se_dev_set_emulate_3pc(struct se_device *, int); |
38 | int se_dev_set_pi_prot_type(struct se_device *, int); | ||
39 | int se_dev_set_pi_prot_format(struct se_device *, int); | ||
38 | int se_dev_set_enforce_pr_isids(struct se_device *, int); | 40 | int se_dev_set_enforce_pr_isids(struct se_device *, int); |
39 | int se_dev_set_is_nonrot(struct se_device *, int); | 41 | int se_dev_set_is_nonrot(struct se_device *, int); |
40 | int se_dev_set_emulate_rest_reord(struct se_device *dev, int); | 42 | int se_dev_set_emulate_rest_reord(struct se_device *dev, int); |