diff options
-rw-r--r-- | drivers/target/target_core_alua.c | 82 | ||||
-rw-r--r-- | drivers/target/target_core_alua.h | 10 | ||||
-rw-r--r-- | drivers/target/target_core_configfs.c | 21 | ||||
-rw-r--r-- | include/target/target_core_base.h | 1 |
4 files changed, 102 insertions, 12 deletions
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index be7251ee8b3a..e624b836469c 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c | |||
@@ -66,18 +66,24 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) | |||
66 | struct t10_alua_tg_pt_gp *tg_pt_gp; | 66 | struct t10_alua_tg_pt_gp *tg_pt_gp; |
67 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; | 67 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; |
68 | unsigned char *buf; | 68 | unsigned char *buf; |
69 | u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first | 69 | u32 rd_len = 0, off; |
70 | Target port group descriptor */ | 70 | int ext_hdr = (cmd->t_task_cdb[1] & 0x20); |
71 | /* | 71 | /* |
72 | * Need at least 4 bytes of response data or else we can't | 72 | * Skip over RESERVED area to first Target port group descriptor |
73 | * even fit the return data length. | 73 | * depending on the PARAMETER DATA FORMAT type.. |
74 | */ | 74 | */ |
75 | if (cmd->data_length < 4) { | 75 | if (ext_hdr != 0) |
76 | pr_warn("REPORT TARGET PORT GROUPS allocation length %u" | 76 | off = 8; |
77 | " too small\n", cmd->data_length); | 77 | else |
78 | off = 4; | ||
79 | |||
80 | if (cmd->data_length < off) { | ||
81 | pr_warn("REPORT TARGET PORT GROUPS allocation length %u too" | ||
82 | " small for %s header\n", cmd->data_length, | ||
83 | (ext_hdr) ? "extended" : "normal"); | ||
84 | cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; | ||
78 | return -EINVAL; | 85 | return -EINVAL; |
79 | } | 86 | } |
80 | |||
81 | buf = transport_kmap_data_sg(cmd); | 87 | buf = transport_kmap_data_sg(cmd); |
82 | 88 | ||
83 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); | 89 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); |
@@ -158,11 +164,31 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) | |||
158 | /* | 164 | /* |
159 | * Set the RETURN DATA LENGTH set in the header of the DataIN Payload | 165 | * Set the RETURN DATA LENGTH set in the header of the DataIN Payload |
160 | */ | 166 | */ |
161 | buf[0] = ((rd_len >> 24) & 0xff); | 167 | put_unaligned_be32(rd_len, &buf[0]); |
162 | buf[1] = ((rd_len >> 16) & 0xff); | ||
163 | buf[2] = ((rd_len >> 8) & 0xff); | ||
164 | buf[3] = (rd_len & 0xff); | ||
165 | 168 | ||
169 | /* | ||
170 | * Fill in the Extended header parameter data format if requested | ||
171 | */ | ||
172 | if (ext_hdr != 0) { | ||
173 | buf[4] = 0x10; | ||
174 | /* | ||
175 | * Set the implict transition time (in seconds) for the application | ||
176 | * client to use as a base for it's transition timeout value. | ||
177 | * | ||
178 | * Use the current tg_pt_gp_mem -> tg_pt_gp membership from the LUN | ||
179 | * this CDB was received upon to determine this value individually | ||
180 | * for ALUA target port group. | ||
181 | */ | ||
182 | port = cmd->se_lun->lun_sep; | ||
183 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; | ||
184 | if (tg_pt_gp_mem) { | ||
185 | spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | ||
186 | tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; | ||
187 | if (tg_pt_gp) | ||
188 | buf[5] = tg_pt_gp->tg_pt_gp_implict_trans_secs; | ||
189 | spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | ||
190 | } | ||
191 | } | ||
166 | transport_kunmap_data_sg(cmd); | 192 | transport_kunmap_data_sg(cmd); |
167 | 193 | ||
168 | target_complete_cmd(cmd, GOOD); | 194 | target_complete_cmd(cmd, GOOD); |
@@ -1355,6 +1381,7 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp( | |||
1355 | */ | 1381 | */ |
1356 | tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS; | 1382 | tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS; |
1357 | tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS; | 1383 | tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS; |
1384 | tg_pt_gp->tg_pt_gp_implict_trans_secs = ALUA_DEFAULT_IMPLICT_TRANS_SECS; | ||
1358 | 1385 | ||
1359 | if (def_group) { | 1386 | if (def_group) { |
1360 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); | 1387 | spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); |
@@ -1851,6 +1878,37 @@ ssize_t core_alua_store_trans_delay_msecs( | |||
1851 | return count; | 1878 | return count; |
1852 | } | 1879 | } |
1853 | 1880 | ||
1881 | ssize_t core_alua_show_implict_trans_secs( | ||
1882 | struct t10_alua_tg_pt_gp *tg_pt_gp, | ||
1883 | char *page) | ||
1884 | { | ||
1885 | return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_implict_trans_secs); | ||
1886 | } | ||
1887 | |||
1888 | ssize_t core_alua_store_implict_trans_secs( | ||
1889 | struct t10_alua_tg_pt_gp *tg_pt_gp, | ||
1890 | const char *page, | ||
1891 | size_t count) | ||
1892 | { | ||
1893 | unsigned long tmp; | ||
1894 | int ret; | ||
1895 | |||
1896 | ret = strict_strtoul(page, 0, &tmp); | ||
1897 | if (ret < 0) { | ||
1898 | pr_err("Unable to extract implict_trans_secs\n"); | ||
1899 | return -EINVAL; | ||
1900 | } | ||
1901 | if (tmp > ALUA_MAX_IMPLICT_TRANS_SECS) { | ||
1902 | pr_err("Passed implict_trans_secs: %lu, exceeds" | ||
1903 | " ALUA_MAX_IMPLICT_TRANS_SECS: %d\n", tmp, | ||
1904 | ALUA_MAX_IMPLICT_TRANS_SECS); | ||
1905 | return -EINVAL; | ||
1906 | } | ||
1907 | tg_pt_gp->tg_pt_gp_implict_trans_secs = (int)tmp; | ||
1908 | |||
1909 | return count; | ||
1910 | } | ||
1911 | |||
1854 | ssize_t core_alua_show_preferred_bit( | 1912 | ssize_t core_alua_show_preferred_bit( |
1855 | struct t10_alua_tg_pt_gp *tg_pt_gp, | 1913 | struct t10_alua_tg_pt_gp *tg_pt_gp, |
1856 | char *page) | 1914 | char *page) |
diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h index e26454324752..f920c170d47b 100644 --- a/drivers/target/target_core_alua.h +++ b/drivers/target/target_core_alua.h | |||
@@ -52,6 +52,12 @@ | |||
52 | #define ALUA_DEFAULT_TRANS_DELAY_MSECS 0 | 52 | #define ALUA_DEFAULT_TRANS_DELAY_MSECS 0 |
53 | #define ALUA_MAX_TRANS_DELAY_MSECS 30000 /* 30 seconds */ | 53 | #define ALUA_MAX_TRANS_DELAY_MSECS 30000 /* 30 seconds */ |
54 | /* | 54 | /* |
55 | * Used for the recommended application client implict transition timeout | ||
56 | * in seconds, returned by the REPORT_TARGET_PORT_GROUPS w/ extended header. | ||
57 | */ | ||
58 | #define ALUA_DEFAULT_IMPLICT_TRANS_SECS 0 | ||
59 | #define ALUA_MAX_IMPLICT_TRANS_SECS 255 | ||
60 | /* | ||
55 | * Used by core_alua_update_tpg_primary_metadata() and | 61 | * Used by core_alua_update_tpg_primary_metadata() and |
56 | * core_alua_update_tpg_secondary_metadata() | 62 | * core_alua_update_tpg_secondary_metadata() |
57 | */ | 63 | */ |
@@ -107,6 +113,10 @@ extern ssize_t core_alua_show_trans_delay_msecs(struct t10_alua_tg_pt_gp *, | |||
107 | char *); | 113 | char *); |
108 | extern ssize_t core_alua_store_trans_delay_msecs(struct t10_alua_tg_pt_gp *, | 114 | extern ssize_t core_alua_store_trans_delay_msecs(struct t10_alua_tg_pt_gp *, |
109 | const char *, size_t); | 115 | const char *, size_t); |
116 | extern ssize_t core_alua_show_implict_trans_secs(struct t10_alua_tg_pt_gp *, | ||
117 | char *); | ||
118 | extern ssize_t core_alua_store_implict_trans_secs(struct t10_alua_tg_pt_gp *, | ||
119 | const char *, size_t); | ||
110 | extern ssize_t core_alua_show_preferred_bit(struct t10_alua_tg_pt_gp *, | 120 | extern ssize_t core_alua_show_preferred_bit(struct t10_alua_tg_pt_gp *, |
111 | char *); | 121 | char *); |
112 | extern ssize_t core_alua_store_preferred_bit(struct t10_alua_tg_pt_gp *, | 122 | extern ssize_t core_alua_store_preferred_bit(struct t10_alua_tg_pt_gp *, |
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 931521cc4e4f..801efa892046 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c | |||
@@ -2447,6 +2447,26 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs( | |||
2447 | SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR); | 2447 | SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR); |
2448 | 2448 | ||
2449 | /* | 2449 | /* |
2450 | * implict_trans_secs | ||
2451 | */ | ||
2452 | static ssize_t target_core_alua_tg_pt_gp_show_attr_implict_trans_secs( | ||
2453 | struct t10_alua_tg_pt_gp *tg_pt_gp, | ||
2454 | char *page) | ||
2455 | { | ||
2456 | return core_alua_show_implict_trans_secs(tg_pt_gp, page); | ||
2457 | } | ||
2458 | |||
2459 | static ssize_t target_core_alua_tg_pt_gp_store_attr_implict_trans_secs( | ||
2460 | struct t10_alua_tg_pt_gp *tg_pt_gp, | ||
2461 | const char *page, | ||
2462 | size_t count) | ||
2463 | { | ||
2464 | return core_alua_store_implict_trans_secs(tg_pt_gp, page, count); | ||
2465 | } | ||
2466 | |||
2467 | SE_DEV_ALUA_TG_PT_ATTR(implict_trans_secs, S_IRUGO | S_IWUSR); | ||
2468 | |||
2469 | /* | ||
2450 | * preferred | 2470 | * preferred |
2451 | */ | 2471 | */ |
2452 | 2472 | ||
@@ -2570,6 +2590,7 @@ static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = { | |||
2570 | &target_core_alua_tg_pt_gp_alua_write_metadata.attr, | 2590 | &target_core_alua_tg_pt_gp_alua_write_metadata.attr, |
2571 | &target_core_alua_tg_pt_gp_nonop_delay_msecs.attr, | 2591 | &target_core_alua_tg_pt_gp_nonop_delay_msecs.attr, |
2572 | &target_core_alua_tg_pt_gp_trans_delay_msecs.attr, | 2592 | &target_core_alua_tg_pt_gp_trans_delay_msecs.attr, |
2593 | &target_core_alua_tg_pt_gp_implict_trans_secs.attr, | ||
2573 | &target_core_alua_tg_pt_gp_preferred.attr, | 2594 | &target_core_alua_tg_pt_gp_preferred.attr, |
2574 | &target_core_alua_tg_pt_gp_tg_pt_gp_id.attr, | 2595 | &target_core_alua_tg_pt_gp_tg_pt_gp_id.attr, |
2575 | &target_core_alua_tg_pt_gp_members.attr, | 2596 | &target_core_alua_tg_pt_gp_members.attr, |
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 1fe9111f4dc1..dc35d8660aa6 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
@@ -330,6 +330,7 @@ struct t10_alua_tg_pt_gp { | |||
330 | int tg_pt_gp_alua_access_type; | 330 | int tg_pt_gp_alua_access_type; |
331 | int tg_pt_gp_nonop_delay_msecs; | 331 | int tg_pt_gp_nonop_delay_msecs; |
332 | int tg_pt_gp_trans_delay_msecs; | 332 | int tg_pt_gp_trans_delay_msecs; |
333 | int tg_pt_gp_implict_trans_secs; | ||
333 | int tg_pt_gp_pref; | 334 | int tg_pt_gp_pref; |
334 | int tg_pt_gp_write_metadata; | 335 | int tg_pt_gp_write_metadata; |
335 | /* Used by struct t10_alua_tg_pt_gp->tg_pt_gp_md_buf_len */ | 336 | /* Used by struct t10_alua_tg_pt_gp->tg_pt_gp_md_buf_len */ |