diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2010-12-17 14:11:26 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-01-14 11:12:29 -0500 |
commit | c66ac9db8d4ad9994a02b3e933ea2ccc643e1fe5 (patch) | |
tree | 71c6344688bf56ea6aaf18c586ab69ff4f077ade /drivers/target/target_core_cdb.c | |
parent | f4013c3879d1bbd9f3ab8351185decd049502368 (diff) |
[SCSI] target: Add LIO target core v4.0.0-rc6
LIO target is a full featured in-kernel target framework with the
following feature set:
High-performance, non-blocking, multithreaded architecture with SIMD
support.
Advanced SCSI feature set:
* Persistent Reservations (PRs)
* Asymmetric Logical Unit Assignment (ALUA)
* Protocol and intra-nexus multiplexing, load-balancing and failover (MC/S)
* Full Error Recovery (ERL=0,1,2)
* Active/active task migration and session continuation (ERL=2)
* Thin LUN provisioning (UNMAP and WRITE_SAMExx)
Multiprotocol target plugins
Storage media independence:
* Virtualization of all storage media; transparent mapping of IO to LUNs
* No hard limits on number of LUNs per Target; maximum LUN size ~750 TB
* Backstores: SATA, SAS, SCSI, BluRay, DVD, FLASH, USB, ramdisk, etc.
Standards compliance:
* Full compliance with IETF (RFC 3720)
* Full implementation of SPC-4 PRs and ALUA
Significant code cleanups done by Christoph Hellwig.
[jejb: fix up for new block bdev exclusive interface. Minor fixes from
Randy Dunlap and Dan Carpenter.]
Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/target/target_core_cdb.c')
-rw-r--r-- | drivers/target/target_core_cdb.c | 1131 |
1 files changed, 1131 insertions, 0 deletions
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c new file mode 100644 index 000000000000..366080baf474 --- /dev/null +++ b/drivers/target/target_core_cdb.c | |||
@@ -0,0 +1,1131 @@ | |||
1 | /* | ||
2 | * CDB emulation for non-READ/WRITE commands. | ||
3 | * | ||
4 | * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc. | ||
5 | * Copyright (c) 2005, 2006, 2007 SBE, Inc. | ||
6 | * Copyright (c) 2007-2010 Rising Tide Systems | ||
7 | * Copyright (c) 2008-2010 Linux-iSCSI.org | ||
8 | * | ||
9 | * Nicholas A. Bellinger <nab@kernel.org> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
24 | */ | ||
25 | |||
26 | #include <asm/unaligned.h> | ||
27 | #include <scsi/scsi.h> | ||
28 | |||
29 | #include <target/target_core_base.h> | ||
30 | #include <target/target_core_transport.h> | ||
31 | #include <target/target_core_fabric_ops.h> | ||
32 | #include "target_core_ua.h" | ||
33 | |||
34 | static void | ||
35 | target_fill_alua_data(struct se_port *port, unsigned char *buf) | ||
36 | { | ||
37 | struct t10_alua_tg_pt_gp *tg_pt_gp; | ||
38 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; | ||
39 | |||
40 | /* | ||
41 | * Set SCCS for MAINTENANCE_IN + REPORT_TARGET_PORT_GROUPS. | ||
42 | */ | ||
43 | buf[5] = 0x80; | ||
44 | |||
45 | /* | ||
46 | * Set TPGS field for explict and/or implict ALUA access type | ||
47 | * and opteration. | ||
48 | * | ||
49 | * See spc4r17 section 6.4.2 Table 135 | ||
50 | */ | ||
51 | if (!port) | ||
52 | return; | ||
53 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; | ||
54 | if (!tg_pt_gp_mem) | ||
55 | return; | ||
56 | |||
57 | spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | ||
58 | tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; | ||
59 | if (tg_pt_gp) | ||
60 | buf[5] |= tg_pt_gp->tg_pt_gp_alua_access_type; | ||
61 | spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | ||
62 | } | ||
63 | |||
64 | static int | ||
65 | target_emulate_inquiry_std(struct se_cmd *cmd) | ||
66 | { | ||
67 | struct se_lun *lun = SE_LUN(cmd); | ||
68 | struct se_device *dev = SE_DEV(cmd); | ||
69 | unsigned char *buf = cmd->t_task->t_task_buf; | ||
70 | |||
71 | /* | ||
72 | * Make sure we at least have 6 bytes of INQUIRY response | ||
73 | * payload going back for EVPD=0 | ||
74 | */ | ||
75 | if (cmd->data_length < 6) { | ||
76 | printk(KERN_ERR "SCSI Inquiry payload length: %u" | ||
77 | " too small for EVPD=0\n", cmd->data_length); | ||
78 | return -1; | ||
79 | } | ||
80 | |||
81 | buf[0] = dev->transport->get_device_type(dev); | ||
82 | if (buf[0] == TYPE_TAPE) | ||
83 | buf[1] = 0x80; | ||
84 | buf[2] = dev->transport->get_device_rev(dev); | ||
85 | |||
86 | /* | ||
87 | * Enable SCCS and TPGS fields for Emulated ALUA | ||
88 | */ | ||
89 | if (T10_ALUA(dev->se_sub_dev)->alua_type == SPC3_ALUA_EMULATED) | ||
90 | target_fill_alua_data(lun->lun_sep, buf); | ||
91 | |||
92 | if (cmd->data_length < 8) { | ||
93 | buf[4] = 1; /* Set additional length to 1 */ | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | buf[7] = 0x32; /* Sync=1 and CmdQue=1 */ | ||
98 | |||
99 | /* | ||
100 | * Do not include vendor, product, reversion info in INQUIRY | ||
101 | * response payload for cdbs with a small allocation length. | ||
102 | */ | ||
103 | if (cmd->data_length < 36) { | ||
104 | buf[4] = 3; /* Set additional length to 3 */ | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | snprintf((unsigned char *)&buf[8], 8, "LIO-ORG"); | ||
109 | snprintf((unsigned char *)&buf[16], 16, "%s", | ||
110 | &DEV_T10_WWN(dev)->model[0]); | ||
111 | snprintf((unsigned char *)&buf[32], 4, "%s", | ||
112 | &DEV_T10_WWN(dev)->revision[0]); | ||
113 | buf[4] = 31; /* Set additional length to 31 */ | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | /* supported vital product data pages */ | ||
118 | static int | ||
119 | target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) | ||
120 | { | ||
121 | buf[1] = 0x00; | ||
122 | if (cmd->data_length < 8) | ||
123 | return 0; | ||
124 | |||
125 | buf[4] = 0x0; | ||
126 | /* | ||
127 | * Only report the INQUIRY EVPD=1 pages after a valid NAA | ||
128 | * Registered Extended LUN WWN has been set via ConfigFS | ||
129 | * during device creation/restart. | ||
130 | */ | ||
131 | if (SE_DEV(cmd)->se_sub_dev->su_dev_flags & | ||
132 | SDF_EMULATED_VPD_UNIT_SERIAL) { | ||
133 | buf[3] = 3; | ||
134 | buf[5] = 0x80; | ||
135 | buf[6] = 0x83; | ||
136 | buf[7] = 0x86; | ||
137 | } | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | /* unit serial number */ | ||
143 | static int | ||
144 | target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) | ||
145 | { | ||
146 | struct se_device *dev = SE_DEV(cmd); | ||
147 | u16 len = 0; | ||
148 | |||
149 | buf[1] = 0x80; | ||
150 | if (dev->se_sub_dev->su_dev_flags & | ||
151 | SDF_EMULATED_VPD_UNIT_SERIAL) { | ||
152 | u32 unit_serial_len; | ||
153 | |||
154 | unit_serial_len = | ||
155 | strlen(&DEV_T10_WWN(dev)->unit_serial[0]); | ||
156 | unit_serial_len++; /* For NULL Terminator */ | ||
157 | |||
158 | if (((len + 4) + unit_serial_len) > cmd->data_length) { | ||
159 | len += unit_serial_len; | ||
160 | buf[2] = ((len >> 8) & 0xff); | ||
161 | buf[3] = (len & 0xff); | ||
162 | return 0; | ||
163 | } | ||
164 | len += sprintf((unsigned char *)&buf[4], "%s", | ||
165 | &DEV_T10_WWN(dev)->unit_serial[0]); | ||
166 | len++; /* Extra Byte for NULL Terminator */ | ||
167 | buf[3] = len; | ||
168 | } | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Device identification VPD, for a complete list of | ||
174 | * DESIGNATOR TYPEs see spc4r17 Table 459. | ||
175 | */ | ||
176 | static int | ||
177 | target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) | ||
178 | { | ||
179 | struct se_device *dev = SE_DEV(cmd); | ||
180 | struct se_lun *lun = SE_LUN(cmd); | ||
181 | struct se_port *port = NULL; | ||
182 | struct se_portal_group *tpg = NULL; | ||
183 | struct t10_alua_lu_gp_member *lu_gp_mem; | ||
184 | struct t10_alua_tg_pt_gp *tg_pt_gp; | ||
185 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; | ||
186 | unsigned char binary, binary_new; | ||
187 | unsigned char *prod = &DEV_T10_WWN(dev)->model[0]; | ||
188 | u32 prod_len; | ||
189 | u32 unit_serial_len, off = 0; | ||
190 | int i; | ||
191 | u16 len = 0, id_len; | ||
192 | |||
193 | buf[1] = 0x83; | ||
194 | off = 4; | ||
195 | |||
196 | /* | ||
197 | * NAA IEEE Registered Extended Assigned designator format, see | ||
198 | * spc4r17 section 7.7.3.6.5 | ||
199 | * | ||
200 | * We depend upon a target_core_mod/ConfigFS provided | ||
201 | * /sys/kernel/config/target/core/$HBA/$DEV/wwn/vpd_unit_serial | ||
202 | * value in order to return the NAA id. | ||
203 | */ | ||
204 | if (!(dev->se_sub_dev->su_dev_flags & SDF_EMULATED_VPD_UNIT_SERIAL)) | ||
205 | goto check_t10_vend_desc; | ||
206 | |||
207 | if (off + 20 > cmd->data_length) | ||
208 | goto check_t10_vend_desc; | ||
209 | |||
210 | /* CODE SET == Binary */ | ||
211 | buf[off++] = 0x1; | ||
212 | |||
213 | /* Set ASSOICATION == addressed logical unit: 0)b */ | ||
214 | buf[off] = 0x00; | ||
215 | |||
216 | /* Identifier/Designator type == NAA identifier */ | ||
217 | buf[off++] = 0x3; | ||
218 | off++; | ||
219 | |||
220 | /* Identifier/Designator length */ | ||
221 | buf[off++] = 0x10; | ||
222 | |||
223 | /* | ||
224 | * Start NAA IEEE Registered Extended Identifier/Designator | ||
225 | */ | ||
226 | buf[off++] = (0x6 << 4); | ||
227 | |||
228 | /* | ||
229 | * Use OpenFabrics IEEE Company ID: 00 14 05 | ||
230 | */ | ||
231 | buf[off++] = 0x01; | ||
232 | buf[off++] = 0x40; | ||
233 | buf[off] = (0x5 << 4); | ||
234 | |||
235 | /* | ||
236 | * Return ConfigFS Unit Serial Number information for | ||
237 | * VENDOR_SPECIFIC_IDENTIFIER and | ||
238 | * VENDOR_SPECIFIC_IDENTIFIER_EXTENTION | ||
239 | */ | ||
240 | binary = transport_asciihex_to_binaryhex( | ||
241 | &DEV_T10_WWN(dev)->unit_serial[0]); | ||
242 | buf[off++] |= (binary & 0xf0) >> 4; | ||
243 | for (i = 0; i < 24; i += 2) { | ||
244 | binary_new = transport_asciihex_to_binaryhex( | ||
245 | &DEV_T10_WWN(dev)->unit_serial[i+2]); | ||
246 | buf[off] = (binary & 0x0f) << 4; | ||
247 | buf[off++] |= (binary_new & 0xf0) >> 4; | ||
248 | binary = binary_new; | ||
249 | } | ||
250 | len = 20; | ||
251 | off = (len + 4); | ||
252 | |||
253 | check_t10_vend_desc: | ||
254 | /* | ||
255 | * T10 Vendor Identifier Page, see spc4r17 section 7.7.3.4 | ||
256 | */ | ||
257 | id_len = 8; /* For Vendor field */ | ||
258 | prod_len = 4; /* For VPD Header */ | ||
259 | prod_len += 8; /* For Vendor field */ | ||
260 | prod_len += strlen(prod); | ||
261 | prod_len++; /* For : */ | ||
262 | |||
263 | if (dev->se_sub_dev->su_dev_flags & | ||
264 | SDF_EMULATED_VPD_UNIT_SERIAL) { | ||
265 | unit_serial_len = | ||
266 | strlen(&DEV_T10_WWN(dev)->unit_serial[0]); | ||
267 | unit_serial_len++; /* For NULL Terminator */ | ||
268 | |||
269 | if ((len + (id_len + 4) + | ||
270 | (prod_len + unit_serial_len)) > | ||
271 | cmd->data_length) { | ||
272 | len += (prod_len + unit_serial_len); | ||
273 | goto check_port; | ||
274 | } | ||
275 | id_len += sprintf((unsigned char *)&buf[off+12], | ||
276 | "%s:%s", prod, | ||
277 | &DEV_T10_WWN(dev)->unit_serial[0]); | ||
278 | } | ||
279 | buf[off] = 0x2; /* ASCII */ | ||
280 | buf[off+1] = 0x1; /* T10 Vendor ID */ | ||
281 | buf[off+2] = 0x0; | ||
282 | memcpy((unsigned char *)&buf[off+4], "LIO-ORG", 8); | ||
283 | /* Extra Byte for NULL Terminator */ | ||
284 | id_len++; | ||
285 | /* Identifier Length */ | ||
286 | buf[off+3] = id_len; | ||
287 | /* Header size for Designation descriptor */ | ||
288 | len += (id_len + 4); | ||
289 | off += (id_len + 4); | ||
290 | /* | ||
291 | * struct se_port is only set for INQUIRY VPD=1 through $FABRIC_MOD | ||
292 | */ | ||
293 | check_port: | ||
294 | port = lun->lun_sep; | ||
295 | if (port) { | ||
296 | struct t10_alua_lu_gp *lu_gp; | ||
297 | u32 padding, scsi_name_len; | ||
298 | u16 lu_gp_id = 0; | ||
299 | u16 tg_pt_gp_id = 0; | ||
300 | u16 tpgt; | ||
301 | |||
302 | tpg = port->sep_tpg; | ||
303 | /* | ||
304 | * Relative target port identifer, see spc4r17 | ||
305 | * section 7.7.3.7 | ||
306 | * | ||
307 | * Get the PROTOCOL IDENTIFIER as defined by spc4r17 | ||
308 | * section 7.5.1 Table 362 | ||
309 | */ | ||
310 | if (((len + 4) + 8) > cmd->data_length) { | ||
311 | len += 8; | ||
312 | goto check_tpgi; | ||
313 | } | ||
314 | buf[off] = | ||
315 | (TPG_TFO(tpg)->get_fabric_proto_ident(tpg) << 4); | ||
316 | buf[off++] |= 0x1; /* CODE SET == Binary */ | ||
317 | buf[off] = 0x80; /* Set PIV=1 */ | ||
318 | /* Set ASSOICATION == target port: 01b */ | ||
319 | buf[off] |= 0x10; | ||
320 | /* DESIGNATOR TYPE == Relative target port identifer */ | ||
321 | buf[off++] |= 0x4; | ||
322 | off++; /* Skip over Reserved */ | ||
323 | buf[off++] = 4; /* DESIGNATOR LENGTH */ | ||
324 | /* Skip over Obsolete field in RTPI payload | ||
325 | * in Table 472 */ | ||
326 | off += 2; | ||
327 | buf[off++] = ((port->sep_rtpi >> 8) & 0xff); | ||
328 | buf[off++] = (port->sep_rtpi & 0xff); | ||
329 | len += 8; /* Header size + Designation descriptor */ | ||
330 | /* | ||
331 | * Target port group identifier, see spc4r17 | ||
332 | * section 7.7.3.8 | ||
333 | * | ||
334 | * Get the PROTOCOL IDENTIFIER as defined by spc4r17 | ||
335 | * section 7.5.1 Table 362 | ||
336 | */ | ||
337 | check_tpgi: | ||
338 | if (T10_ALUA(dev->se_sub_dev)->alua_type != | ||
339 | SPC3_ALUA_EMULATED) | ||
340 | goto check_scsi_name; | ||
341 | |||
342 | if (((len + 4) + 8) > cmd->data_length) { | ||
343 | len += 8; | ||
344 | goto check_lu_gp; | ||
345 | } | ||
346 | tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; | ||
347 | if (!tg_pt_gp_mem) | ||
348 | goto check_lu_gp; | ||
349 | |||
350 | spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | ||
351 | tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; | ||
352 | if (!(tg_pt_gp)) { | ||
353 | spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | ||
354 | goto check_lu_gp; | ||
355 | } | ||
356 | tg_pt_gp_id = tg_pt_gp->tg_pt_gp_id; | ||
357 | spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); | ||
358 | |||
359 | buf[off] = | ||
360 | (TPG_TFO(tpg)->get_fabric_proto_ident(tpg) << 4); | ||
361 | buf[off++] |= 0x1; /* CODE SET == Binary */ | ||
362 | buf[off] = 0x80; /* Set PIV=1 */ | ||
363 | /* Set ASSOICATION == target port: 01b */ | ||
364 | buf[off] |= 0x10; | ||
365 | /* DESIGNATOR TYPE == Target port group identifier */ | ||
366 | buf[off++] |= 0x5; | ||
367 | off++; /* Skip over Reserved */ | ||
368 | buf[off++] = 4; /* DESIGNATOR LENGTH */ | ||
369 | off += 2; /* Skip over Reserved Field */ | ||
370 | buf[off++] = ((tg_pt_gp_id >> 8) & 0xff); | ||
371 | buf[off++] = (tg_pt_gp_id & 0xff); | ||
372 | len += 8; /* Header size + Designation descriptor */ | ||
373 | /* | ||
374 | * Logical Unit Group identifier, see spc4r17 | ||
375 | * section 7.7.3.8 | ||
376 | */ | ||
377 | check_lu_gp: | ||
378 | if (((len + 4) + 8) > cmd->data_length) { | ||
379 | len += 8; | ||
380 | goto check_scsi_name; | ||
381 | } | ||
382 | lu_gp_mem = dev->dev_alua_lu_gp_mem; | ||
383 | if (!(lu_gp_mem)) | ||
384 | goto check_scsi_name; | ||
385 | |||
386 | spin_lock(&lu_gp_mem->lu_gp_mem_lock); | ||
387 | lu_gp = lu_gp_mem->lu_gp; | ||
388 | if (!(lu_gp)) { | ||
389 | spin_unlock(&lu_gp_mem->lu_gp_mem_lock); | ||
390 | goto check_scsi_name; | ||
391 | } | ||
392 | lu_gp_id = lu_gp->lu_gp_id; | ||
393 | spin_unlock(&lu_gp_mem->lu_gp_mem_lock); | ||
394 | |||
395 | buf[off++] |= 0x1; /* CODE SET == Binary */ | ||
396 | /* DESIGNATOR TYPE == Logical Unit Group identifier */ | ||
397 | buf[off++] |= 0x6; | ||
398 | off++; /* Skip over Reserved */ | ||
399 | buf[off++] = 4; /* DESIGNATOR LENGTH */ | ||
400 | off += 2; /* Skip over Reserved Field */ | ||
401 | buf[off++] = ((lu_gp_id >> 8) & 0xff); | ||
402 | buf[off++] = (lu_gp_id & 0xff); | ||
403 | len += 8; /* Header size + Designation descriptor */ | ||
404 | /* | ||
405 | * SCSI name string designator, see spc4r17 | ||
406 | * section 7.7.3.11 | ||
407 | * | ||
408 | * Get the PROTOCOL IDENTIFIER as defined by spc4r17 | ||
409 | * section 7.5.1 Table 362 | ||
410 | */ | ||
411 | check_scsi_name: | ||
412 | scsi_name_len = strlen(TPG_TFO(tpg)->tpg_get_wwn(tpg)); | ||
413 | /* UTF-8 ",t,0x<16-bit TPGT>" + NULL Terminator */ | ||
414 | scsi_name_len += 10; | ||
415 | /* Check for 4-byte padding */ | ||
416 | padding = ((-scsi_name_len) & 3); | ||
417 | if (padding != 0) | ||
418 | scsi_name_len += padding; | ||
419 | /* Header size + Designation descriptor */ | ||
420 | scsi_name_len += 4; | ||
421 | |||
422 | if (((len + 4) + scsi_name_len) > cmd->data_length) { | ||
423 | len += scsi_name_len; | ||
424 | goto set_len; | ||
425 | } | ||
426 | buf[off] = | ||
427 | (TPG_TFO(tpg)->get_fabric_proto_ident(tpg) << 4); | ||
428 | buf[off++] |= 0x3; /* CODE SET == UTF-8 */ | ||
429 | buf[off] = 0x80; /* Set PIV=1 */ | ||
430 | /* Set ASSOICATION == target port: 01b */ | ||
431 | buf[off] |= 0x10; | ||
432 | /* DESIGNATOR TYPE == SCSI name string */ | ||
433 | buf[off++] |= 0x8; | ||
434 | off += 2; /* Skip over Reserved and length */ | ||
435 | /* | ||
436 | * SCSI name string identifer containing, $FABRIC_MOD | ||
437 | * dependent information. For LIO-Target and iSCSI | ||
438 | * Target Port, this means "<iSCSI name>,t,0x<TPGT> in | ||
439 | * UTF-8 encoding. | ||
440 | */ | ||
441 | tpgt = TPG_TFO(tpg)->tpg_get_tag(tpg); | ||
442 | scsi_name_len = sprintf(&buf[off], "%s,t,0x%04x", | ||
443 | TPG_TFO(tpg)->tpg_get_wwn(tpg), tpgt); | ||
444 | scsi_name_len += 1 /* Include NULL terminator */; | ||
445 | /* | ||
446 | * The null-terminated, null-padded (see 4.4.2) SCSI | ||
447 | * NAME STRING field contains a UTF-8 format string. | ||
448 | * The number of bytes in the SCSI NAME STRING field | ||
449 | * (i.e., the value in the DESIGNATOR LENGTH field) | ||
450 | * shall be no larger than 256 and shall be a multiple | ||
451 | * of four. | ||
452 | */ | ||
453 | if (padding) | ||
454 | scsi_name_len += padding; | ||
455 | |||
456 | buf[off-1] = scsi_name_len; | ||
457 | off += scsi_name_len; | ||
458 | /* Header size + Designation descriptor */ | ||
459 | len += (scsi_name_len + 4); | ||
460 | } | ||
461 | set_len: | ||
462 | buf[2] = ((len >> 8) & 0xff); | ||
463 | buf[3] = (len & 0xff); /* Page Length for VPD 0x83 */ | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | /* Extended INQUIRY Data VPD Page */ | ||
468 | static int | ||
469 | target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) | ||
470 | { | ||
471 | if (cmd->data_length < 60) | ||
472 | return 0; | ||
473 | |||
474 | buf[1] = 0x86; | ||
475 | buf[2] = 0x3c; | ||
476 | /* Set HEADSUP, ORDSUP, SIMPSUP */ | ||
477 | buf[5] = 0x07; | ||
478 | |||
479 | /* If WriteCache emulation is enabled, set V_SUP */ | ||
480 | if (DEV_ATTRIB(SE_DEV(cmd))->emulate_write_cache > 0) | ||
481 | buf[6] = 0x01; | ||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | /* Block Limits VPD page */ | ||
486 | static int | ||
487 | target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) | ||
488 | { | ||
489 | struct se_device *dev = SE_DEV(cmd); | ||
490 | int have_tp = 0; | ||
491 | |||
492 | /* | ||
493 | * Following sbc3r22 section 6.5.3 Block Limits VPD page, when | ||
494 | * emulate_tpu=1 or emulate_tpws=1 we will be expect a | ||
495 | * different page length for Thin Provisioning. | ||
496 | */ | ||
497 | if (DEV_ATTRIB(dev)->emulate_tpu || DEV_ATTRIB(dev)->emulate_tpws) | ||
498 | have_tp = 1; | ||
499 | |||
500 | if (cmd->data_length < (0x10 + 4)) { | ||
501 | printk(KERN_INFO "Received data_length: %u" | ||
502 | " too small for EVPD 0xb0\n", | ||
503 | cmd->data_length); | ||
504 | return -1; | ||
505 | } | ||
506 | |||
507 | if (have_tp && cmd->data_length < (0x3c + 4)) { | ||
508 | printk(KERN_INFO "Received data_length: %u" | ||
509 | " too small for TPE=1 EVPD 0xb0\n", | ||
510 | cmd->data_length); | ||
511 | have_tp = 0; | ||
512 | } | ||
513 | |||
514 | buf[0] = dev->transport->get_device_type(dev); | ||
515 | buf[1] = 0xb0; | ||
516 | buf[3] = have_tp ? 0x3c : 0x10; | ||
517 | |||
518 | /* | ||
519 | * Set OPTIMAL TRANSFER LENGTH GRANULARITY | ||
520 | */ | ||
521 | put_unaligned_be16(1, &buf[6]); | ||
522 | |||
523 | /* | ||
524 | * Set MAXIMUM TRANSFER LENGTH | ||
525 | */ | ||
526 | put_unaligned_be32(DEV_ATTRIB(dev)->max_sectors, &buf[8]); | ||
527 | |||
528 | /* | ||
529 | * Set OPTIMAL TRANSFER LENGTH | ||
530 | */ | ||
531 | put_unaligned_be32(DEV_ATTRIB(dev)->optimal_sectors, &buf[12]); | ||
532 | |||
533 | /* | ||
534 | * Exit now if we don't support TP or the initiator sent a too | ||
535 | * short buffer. | ||
536 | */ | ||
537 | if (!have_tp || cmd->data_length < (0x3c + 4)) | ||
538 | return 0; | ||
539 | |||
540 | /* | ||
541 | * Set MAXIMUM UNMAP LBA COUNT | ||
542 | */ | ||
543 | put_unaligned_be32(DEV_ATTRIB(dev)->max_unmap_lba_count, &buf[20]); | ||
544 | |||
545 | /* | ||
546 | * Set MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT | ||
547 | */ | ||
548 | put_unaligned_be32(DEV_ATTRIB(dev)->max_unmap_block_desc_count, | ||
549 | &buf[24]); | ||
550 | |||
551 | /* | ||
552 | * Set OPTIMAL UNMAP GRANULARITY | ||
553 | */ | ||
554 | put_unaligned_be32(DEV_ATTRIB(dev)->unmap_granularity, &buf[28]); | ||
555 | |||
556 | /* | ||
557 | * UNMAP GRANULARITY ALIGNMENT | ||
558 | */ | ||
559 | put_unaligned_be32(DEV_ATTRIB(dev)->unmap_granularity_alignment, | ||
560 | &buf[32]); | ||
561 | if (DEV_ATTRIB(dev)->unmap_granularity_alignment != 0) | ||
562 | buf[32] |= 0x80; /* Set the UGAVALID bit */ | ||
563 | |||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | /* Thin Provisioning VPD */ | ||
568 | static int | ||
569 | target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) | ||
570 | { | ||
571 | struct se_device *dev = SE_DEV(cmd); | ||
572 | |||
573 | /* | ||
574 | * From sbc3r22 section 6.5.4 Thin Provisioning VPD page: | ||
575 | * | ||
576 | * The PAGE LENGTH field is defined in SPC-4. If the DP bit is set to | ||
577 | * zero, then the page length shall be set to 0004h. If the DP bit | ||
578 | * is set to one, then the page length shall be set to the value | ||
579 | * defined in table 162. | ||
580 | */ | ||
581 | buf[0] = dev->transport->get_device_type(dev); | ||
582 | buf[1] = 0xb2; | ||
583 | |||
584 | /* | ||
585 | * Set Hardcoded length mentioned above for DP=0 | ||
586 | */ | ||
587 | put_unaligned_be16(0x0004, &buf[2]); | ||
588 | |||
589 | /* | ||
590 | * The THRESHOLD EXPONENT field indicates the threshold set size in | ||
591 | * LBAs as a power of 2 (i.e., the threshold set size is equal to | ||
592 | * 2(threshold exponent)). | ||
593 | * | ||
594 | * Note that this is currently set to 0x00 as mkp says it will be | ||
595 | * changing again. We can enable this once it has settled in T10 | ||
596 | * and is actually used by Linux/SCSI ML code. | ||
597 | */ | ||
598 | buf[4] = 0x00; | ||
599 | |||
600 | /* | ||
601 | * A TPU bit set to one indicates that the device server supports | ||
602 | * the UNMAP command (see 5.25). A TPU bit set to zero indicates | ||
603 | * that the device server does not support the UNMAP command. | ||
604 | */ | ||
605 | if (DEV_ATTRIB(dev)->emulate_tpu != 0) | ||
606 | buf[5] = 0x80; | ||
607 | |||
608 | /* | ||
609 | * A TPWS bit set to one indicates that the device server supports | ||
610 | * the use of the WRITE SAME (16) command (see 5.42) to unmap LBAs. | ||
611 | * A TPWS bit set to zero indicates that the device server does not | ||
612 | * support the use of the WRITE SAME (16) command to unmap LBAs. | ||
613 | */ | ||
614 | if (DEV_ATTRIB(dev)->emulate_tpws != 0) | ||
615 | buf[5] |= 0x40; | ||
616 | |||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | static int | ||
621 | target_emulate_inquiry(struct se_cmd *cmd) | ||
622 | { | ||
623 | struct se_device *dev = SE_DEV(cmd); | ||
624 | unsigned char *buf = cmd->t_task->t_task_buf; | ||
625 | unsigned char *cdb = cmd->t_task->t_task_cdb; | ||
626 | |||
627 | if (!(cdb[1] & 0x1)) | ||
628 | return target_emulate_inquiry_std(cmd); | ||
629 | |||
630 | /* | ||
631 | * Make sure we at least have 4 bytes of INQUIRY response | ||
632 | * payload for 0x00 going back for EVPD=1. Note that 0x80 | ||
633 | * and 0x83 will check for enough payload data length and | ||
634 | * jump to set_len: label when there is not enough inquiry EVPD | ||
635 | * payload length left for the next outgoing EVPD metadata | ||
636 | */ | ||
637 | if (cmd->data_length < 4) { | ||
638 | printk(KERN_ERR "SCSI Inquiry payload length: %u" | ||
639 | " too small for EVPD=1\n", cmd->data_length); | ||
640 | return -1; | ||
641 | } | ||
642 | buf[0] = dev->transport->get_device_type(dev); | ||
643 | |||
644 | switch (cdb[2]) { | ||
645 | case 0x00: | ||
646 | return target_emulate_evpd_00(cmd, buf); | ||
647 | case 0x80: | ||
648 | return target_emulate_evpd_80(cmd, buf); | ||
649 | case 0x83: | ||
650 | return target_emulate_evpd_83(cmd, buf); | ||
651 | case 0x86: | ||
652 | return target_emulate_evpd_86(cmd, buf); | ||
653 | case 0xb0: | ||
654 | return target_emulate_evpd_b0(cmd, buf); | ||
655 | case 0xb2: | ||
656 | return target_emulate_evpd_b2(cmd, buf); | ||
657 | default: | ||
658 | printk(KERN_ERR "Unknown VPD Code: 0x%02x\n", cdb[2]); | ||
659 | return -1; | ||
660 | } | ||
661 | |||
662 | return 0; | ||
663 | } | ||
664 | |||
665 | static int | ||
666 | target_emulate_readcapacity(struct se_cmd *cmd) | ||
667 | { | ||
668 | struct se_device *dev = SE_DEV(cmd); | ||
669 | unsigned char *buf = cmd->t_task->t_task_buf; | ||
670 | u32 blocks = dev->transport->get_blocks(dev); | ||
671 | |||
672 | buf[0] = (blocks >> 24) & 0xff; | ||
673 | buf[1] = (blocks >> 16) & 0xff; | ||
674 | buf[2] = (blocks >> 8) & 0xff; | ||
675 | buf[3] = blocks & 0xff; | ||
676 | buf[4] = (DEV_ATTRIB(dev)->block_size >> 24) & 0xff; | ||
677 | buf[5] = (DEV_ATTRIB(dev)->block_size >> 16) & 0xff; | ||
678 | buf[6] = (DEV_ATTRIB(dev)->block_size >> 8) & 0xff; | ||
679 | buf[7] = DEV_ATTRIB(dev)->block_size & 0xff; | ||
680 | /* | ||
681 | * Set max 32-bit blocks to signal SERVICE ACTION READ_CAPACITY_16 | ||
682 | */ | ||
683 | if (DEV_ATTRIB(dev)->emulate_tpu || DEV_ATTRIB(dev)->emulate_tpws) | ||
684 | put_unaligned_be32(0xFFFFFFFF, &buf[0]); | ||
685 | |||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | static int | ||
690 | target_emulate_readcapacity_16(struct se_cmd *cmd) | ||
691 | { | ||
692 | struct se_device *dev = SE_DEV(cmd); | ||
693 | unsigned char *buf = cmd->t_task->t_task_buf; | ||
694 | unsigned long long blocks = dev->transport->get_blocks(dev); | ||
695 | |||
696 | buf[0] = (blocks >> 56) & 0xff; | ||
697 | buf[1] = (blocks >> 48) & 0xff; | ||
698 | buf[2] = (blocks >> 40) & 0xff; | ||
699 | buf[3] = (blocks >> 32) & 0xff; | ||
700 | buf[4] = (blocks >> 24) & 0xff; | ||
701 | buf[5] = (blocks >> 16) & 0xff; | ||
702 | buf[6] = (blocks >> 8) & 0xff; | ||
703 | buf[7] = blocks & 0xff; | ||
704 | buf[8] = (DEV_ATTRIB(dev)->block_size >> 24) & 0xff; | ||
705 | buf[9] = (DEV_ATTRIB(dev)->block_size >> 16) & 0xff; | ||
706 | buf[10] = (DEV_ATTRIB(dev)->block_size >> 8) & 0xff; | ||
707 | buf[11] = DEV_ATTRIB(dev)->block_size & 0xff; | ||
708 | /* | ||
709 | * Set Thin Provisioning Enable bit following sbc3r22 in section | ||
710 | * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled. | ||
711 | */ | ||
712 | if (DEV_ATTRIB(dev)->emulate_tpu || DEV_ATTRIB(dev)->emulate_tpws) | ||
713 | buf[14] = 0x80; | ||
714 | |||
715 | return 0; | ||
716 | } | ||
717 | |||
718 | static int | ||
719 | target_modesense_rwrecovery(unsigned char *p) | ||
720 | { | ||
721 | p[0] = 0x01; | ||
722 | p[1] = 0x0a; | ||
723 | |||
724 | return 12; | ||
725 | } | ||
726 | |||
727 | static int | ||
728 | target_modesense_control(struct se_device *dev, unsigned char *p) | ||
729 | { | ||
730 | p[0] = 0x0a; | ||
731 | p[1] = 0x0a; | ||
732 | p[2] = 2; | ||
733 | /* | ||
734 | * From spc4r17, section 7.4.6 Control mode Page | ||
735 | * | ||
736 | * Unit Attention interlocks control (UN_INTLCK_CTRL) to code 00b | ||
737 | * | ||
738 | * 00b: The logical unit shall clear any unit attention condition | ||
739 | * reported in the same I_T_L_Q nexus transaction as a CHECK CONDITION | ||
740 | * status and shall not establish a unit attention condition when a com- | ||
741 | * mand is completed with BUSY, TASK SET FULL, or RESERVATION CONFLICT | ||
742 | * status. | ||
743 | * | ||
744 | * 10b: The logical unit shall not clear any unit attention condition | ||
745 | * reported in the same I_T_L_Q nexus transaction as a CHECK CONDITION | ||
746 | * status and shall not establish a unit attention condition when | ||
747 | * a command is completed with BUSY, TASK SET FULL, or RESERVATION | ||
748 | * CONFLICT status. | ||
749 | * | ||
750 | * 11b a The logical unit shall not clear any unit attention condition | ||
751 | * reported in the same I_T_L_Q nexus transaction as a CHECK CONDITION | ||
752 | * status and shall establish a unit attention condition for the | ||
753 | * initiator port associated with the I_T nexus on which the BUSY, | ||
754 | * TASK SET FULL, or RESERVATION CONFLICT status is being returned. | ||
755 | * Depending on the status, the additional sense code shall be set to | ||
756 | * PREVIOUS BUSY STATUS, PREVIOUS TASK SET FULL STATUS, or PREVIOUS | ||
757 | * RESERVATION CONFLICT STATUS. Until it is cleared by a REQUEST SENSE | ||
758 | * command, a unit attention condition shall be established only once | ||
759 | * for a BUSY, TASK SET FULL, or RESERVATION CONFLICT status regardless | ||
760 | * to the number of commands completed with one of those status codes. | ||
761 | */ | ||
762 | p[4] = (DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl == 2) ? 0x30 : | ||
763 | (DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00; | ||
764 | /* | ||
765 | * From spc4r17, section 7.4.6 Control mode Page | ||
766 | * | ||
767 | * Task Aborted Status (TAS) bit set to zero. | ||
768 | * | ||
769 | * A task aborted status (TAS) bit set to zero specifies that aborted | ||
770 | * tasks shall be terminated by the device server without any response | ||
771 | * to the application client. A TAS bit set to one specifies that tasks | ||
772 | * aborted by the actions of an I_T nexus other than the I_T nexus on | ||
773 | * which the command was received shall be completed with TASK ABORTED | ||
774 | * status (see SAM-4). | ||
775 | */ | ||
776 | p[5] = (DEV_ATTRIB(dev)->emulate_tas) ? 0x40 : 0x00; | ||
777 | p[8] = 0xff; | ||
778 | p[9] = 0xff; | ||
779 | p[11] = 30; | ||
780 | |||
781 | return 12; | ||
782 | } | ||
783 | |||
784 | static int | ||
785 | target_modesense_caching(struct se_device *dev, unsigned char *p) | ||
786 | { | ||
787 | p[0] = 0x08; | ||
788 | p[1] = 0x12; | ||
789 | if (DEV_ATTRIB(dev)->emulate_write_cache > 0) | ||
790 | p[2] = 0x04; /* Write Cache Enable */ | ||
791 | p[12] = 0x20; /* Disabled Read Ahead */ | ||
792 | |||
793 | return 20; | ||
794 | } | ||
795 | |||
796 | static void | ||
797 | target_modesense_write_protect(unsigned char *buf, int type) | ||
798 | { | ||
799 | /* | ||
800 | * I believe that the WP bit (bit 7) in the mode header is the same for | ||
801 | * all device types.. | ||
802 | */ | ||
803 | switch (type) { | ||
804 | case TYPE_DISK: | ||
805 | case TYPE_TAPE: | ||
806 | default: | ||
807 | buf[0] |= 0x80; /* WP bit */ | ||
808 | break; | ||
809 | } | ||
810 | } | ||
811 | |||
812 | static void | ||
813 | target_modesense_dpofua(unsigned char *buf, int type) | ||
814 | { | ||
815 | switch (type) { | ||
816 | case TYPE_DISK: | ||
817 | buf[0] |= 0x10; /* DPOFUA bit */ | ||
818 | break; | ||
819 | default: | ||
820 | break; | ||
821 | } | ||
822 | } | ||
823 | |||
824 | static int | ||
825 | target_emulate_modesense(struct se_cmd *cmd, int ten) | ||
826 | { | ||
827 | struct se_device *dev = SE_DEV(cmd); | ||
828 | char *cdb = cmd->t_task->t_task_cdb; | ||
829 | unsigned char *rbuf = cmd->t_task->t_task_buf; | ||
830 | int type = dev->transport->get_device_type(dev); | ||
831 | int offset = (ten) ? 8 : 4; | ||
832 | int length = 0; | ||
833 | unsigned char buf[SE_MODE_PAGE_BUF]; | ||
834 | |||
835 | memset(buf, 0, SE_MODE_PAGE_BUF); | ||
836 | |||
837 | switch (cdb[2] & 0x3f) { | ||
838 | case 0x01: | ||
839 | length = target_modesense_rwrecovery(&buf[offset]); | ||
840 | break; | ||
841 | case 0x08: | ||
842 | length = target_modesense_caching(dev, &buf[offset]); | ||
843 | break; | ||
844 | case 0x0a: | ||
845 | length = target_modesense_control(dev, &buf[offset]); | ||
846 | break; | ||
847 | case 0x3f: | ||
848 | length = target_modesense_rwrecovery(&buf[offset]); | ||
849 | length += target_modesense_caching(dev, &buf[offset+length]); | ||
850 | length += target_modesense_control(dev, &buf[offset+length]); | ||
851 | break; | ||
852 | default: | ||
853 | printk(KERN_ERR "Got Unknown Mode Page: 0x%02x\n", | ||
854 | cdb[2] & 0x3f); | ||
855 | return PYX_TRANSPORT_UNKNOWN_MODE_PAGE; | ||
856 | } | ||
857 | offset += length; | ||
858 | |||
859 | if (ten) { | ||
860 | offset -= 2; | ||
861 | buf[0] = (offset >> 8) & 0xff; | ||
862 | buf[1] = offset & 0xff; | ||
863 | |||
864 | if ((SE_LUN(cmd)->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || | ||
865 | (cmd->se_deve && | ||
866 | (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) | ||
867 | target_modesense_write_protect(&buf[3], type); | ||
868 | |||
869 | if ((DEV_ATTRIB(dev)->emulate_write_cache > 0) && | ||
870 | (DEV_ATTRIB(dev)->emulate_fua_write > 0)) | ||
871 | target_modesense_dpofua(&buf[3], type); | ||
872 | |||
873 | if ((offset + 2) > cmd->data_length) | ||
874 | offset = cmd->data_length; | ||
875 | |||
876 | } else { | ||
877 | offset -= 1; | ||
878 | buf[0] = offset & 0xff; | ||
879 | |||
880 | if ((SE_LUN(cmd)->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || | ||
881 | (cmd->se_deve && | ||
882 | (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) | ||
883 | target_modesense_write_protect(&buf[2], type); | ||
884 | |||
885 | if ((DEV_ATTRIB(dev)->emulate_write_cache > 0) && | ||
886 | (DEV_ATTRIB(dev)->emulate_fua_write > 0)) | ||
887 | target_modesense_dpofua(&buf[2], type); | ||
888 | |||
889 | if ((offset + 1) > cmd->data_length) | ||
890 | offset = cmd->data_length; | ||
891 | } | ||
892 | memcpy(rbuf, buf, offset); | ||
893 | |||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | static int | ||
898 | target_emulate_request_sense(struct se_cmd *cmd) | ||
899 | { | ||
900 | unsigned char *cdb = cmd->t_task->t_task_cdb; | ||
901 | unsigned char *buf = cmd->t_task->t_task_buf; | ||
902 | u8 ua_asc = 0, ua_ascq = 0; | ||
903 | |||
904 | if (cdb[1] & 0x01) { | ||
905 | printk(KERN_ERR "REQUEST_SENSE description emulation not" | ||
906 | " supported\n"); | ||
907 | return PYX_TRANSPORT_INVALID_CDB_FIELD; | ||
908 | } | ||
909 | if (!(core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq))) { | ||
910 | /* | ||
911 | * CURRENT ERROR, UNIT ATTENTION | ||
912 | */ | ||
913 | buf[0] = 0x70; | ||
914 | buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; | ||
915 | /* | ||
916 | * Make sure request data length is enough for additional | ||
917 | * sense data. | ||
918 | */ | ||
919 | if (cmd->data_length <= 18) { | ||
920 | buf[7] = 0x00; | ||
921 | return 0; | ||
922 | } | ||
923 | /* | ||
924 | * The Additional Sense Code (ASC) from the UNIT ATTENTION | ||
925 | */ | ||
926 | buf[SPC_ASC_KEY_OFFSET] = ua_asc; | ||
927 | buf[SPC_ASCQ_KEY_OFFSET] = ua_ascq; | ||
928 | buf[7] = 0x0A; | ||
929 | } else { | ||
930 | /* | ||
931 | * CURRENT ERROR, NO SENSE | ||
932 | */ | ||
933 | buf[0] = 0x70; | ||
934 | buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE; | ||
935 | /* | ||
936 | * Make sure request data length is enough for additional | ||
937 | * sense data. | ||
938 | */ | ||
939 | if (cmd->data_length <= 18) { | ||
940 | buf[7] = 0x00; | ||
941 | return 0; | ||
942 | } | ||
943 | /* | ||
944 | * NO ADDITIONAL SENSE INFORMATION | ||
945 | */ | ||
946 | buf[SPC_ASC_KEY_OFFSET] = 0x00; | ||
947 | buf[7] = 0x0A; | ||
948 | } | ||
949 | |||
950 | return 0; | ||
951 | } | ||
952 | |||
953 | /* | ||
954 | * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support. | ||
955 | * Note this is not used for TCM/pSCSI passthrough | ||
956 | */ | ||
957 | static int | ||
958 | target_emulate_unmap(struct se_task *task) | ||
959 | { | ||
960 | struct se_cmd *cmd = TASK_CMD(task); | ||
961 | struct se_device *dev = SE_DEV(cmd); | ||
962 | unsigned char *buf = cmd->t_task->t_task_buf, *ptr = NULL; | ||
963 | unsigned char *cdb = &cmd->t_task->t_task_cdb[0]; | ||
964 | sector_t lba; | ||
965 | unsigned int size = cmd->data_length, range; | ||
966 | int ret, offset; | ||
967 | unsigned short dl, bd_dl; | ||
968 | |||
969 | /* First UNMAP block descriptor starts at 8 byte offset */ | ||
970 | offset = 8; | ||
971 | size -= 8; | ||
972 | dl = get_unaligned_be16(&cdb[0]); | ||
973 | bd_dl = get_unaligned_be16(&cdb[2]); | ||
974 | ptr = &buf[offset]; | ||
975 | printk(KERN_INFO "UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu" | ||
976 | " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr); | ||
977 | |||
978 | while (size) { | ||
979 | lba = get_unaligned_be64(&ptr[0]); | ||
980 | range = get_unaligned_be32(&ptr[8]); | ||
981 | printk(KERN_INFO "UNMAP: Using lba: %llu and range: %u\n", | ||
982 | (unsigned long long)lba, range); | ||
983 | |||
984 | ret = dev->transport->do_discard(dev, lba, range); | ||
985 | if (ret < 0) { | ||
986 | printk(KERN_ERR "blkdev_issue_discard() failed: %d\n", | ||
987 | ret); | ||
988 | return -1; | ||
989 | } | ||
990 | |||
991 | ptr += 16; | ||
992 | size -= 16; | ||
993 | } | ||
994 | |||
995 | task->task_scsi_status = GOOD; | ||
996 | transport_complete_task(task, 1); | ||
997 | return 0; | ||
998 | } | ||
999 | |||
1000 | /* | ||
1001 | * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support. | ||
1002 | * Note this is not used for TCM/pSCSI passthrough | ||
1003 | */ | ||
1004 | static int | ||
1005 | target_emulate_write_same(struct se_task *task) | ||
1006 | { | ||
1007 | struct se_cmd *cmd = TASK_CMD(task); | ||
1008 | struct se_device *dev = SE_DEV(cmd); | ||
1009 | sector_t lba = cmd->t_task->t_task_lba; | ||
1010 | unsigned int range; | ||
1011 | int ret; | ||
1012 | |||
1013 | range = (cmd->data_length / DEV_ATTRIB(dev)->block_size); | ||
1014 | |||
1015 | printk(KERN_INFO "WRITE_SAME UNMAP: LBA: %llu Range: %u\n", | ||
1016 | (unsigned long long)lba, range); | ||
1017 | |||
1018 | ret = dev->transport->do_discard(dev, lba, range); | ||
1019 | if (ret < 0) { | ||
1020 | printk(KERN_INFO "blkdev_issue_discard() failed for WRITE_SAME\n"); | ||
1021 | return -1; | ||
1022 | } | ||
1023 | |||
1024 | task->task_scsi_status = GOOD; | ||
1025 | transport_complete_task(task, 1); | ||
1026 | return 0; | ||
1027 | } | ||
1028 | |||
1029 | int | ||
1030 | transport_emulate_control_cdb(struct se_task *task) | ||
1031 | { | ||
1032 | struct se_cmd *cmd = TASK_CMD(task); | ||
1033 | struct se_device *dev = SE_DEV(cmd); | ||
1034 | unsigned short service_action; | ||
1035 | int ret = 0; | ||
1036 | |||
1037 | switch (cmd->t_task->t_task_cdb[0]) { | ||
1038 | case INQUIRY: | ||
1039 | ret = target_emulate_inquiry(cmd); | ||
1040 | break; | ||
1041 | case READ_CAPACITY: | ||
1042 | ret = target_emulate_readcapacity(cmd); | ||
1043 | break; | ||
1044 | case MODE_SENSE: | ||
1045 | ret = target_emulate_modesense(cmd, 0); | ||
1046 | break; | ||
1047 | case MODE_SENSE_10: | ||
1048 | ret = target_emulate_modesense(cmd, 1); | ||
1049 | break; | ||
1050 | case SERVICE_ACTION_IN: | ||
1051 | switch (cmd->t_task->t_task_cdb[1] & 0x1f) { | ||
1052 | case SAI_READ_CAPACITY_16: | ||
1053 | ret = target_emulate_readcapacity_16(cmd); | ||
1054 | break; | ||
1055 | default: | ||
1056 | printk(KERN_ERR "Unsupported SA: 0x%02x\n", | ||
1057 | cmd->t_task->t_task_cdb[1] & 0x1f); | ||
1058 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | ||
1059 | } | ||
1060 | break; | ||
1061 | case REQUEST_SENSE: | ||
1062 | ret = target_emulate_request_sense(cmd); | ||
1063 | break; | ||
1064 | case UNMAP: | ||
1065 | if (!dev->transport->do_discard) { | ||
1066 | printk(KERN_ERR "UNMAP emulation not supported for: %s\n", | ||
1067 | dev->transport->name); | ||
1068 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | ||
1069 | } | ||
1070 | ret = target_emulate_unmap(task); | ||
1071 | break; | ||
1072 | case WRITE_SAME_16: | ||
1073 | if (!dev->transport->do_discard) { | ||
1074 | printk(KERN_ERR "WRITE_SAME_16 emulation not supported" | ||
1075 | " for: %s\n", dev->transport->name); | ||
1076 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | ||
1077 | } | ||
1078 | ret = target_emulate_write_same(task); | ||
1079 | break; | ||
1080 | case VARIABLE_LENGTH_CMD: | ||
1081 | service_action = | ||
1082 | get_unaligned_be16(&cmd->t_task->t_task_cdb[8]); | ||
1083 | switch (service_action) { | ||
1084 | case WRITE_SAME_32: | ||
1085 | if (!dev->transport->do_discard) { | ||
1086 | printk(KERN_ERR "WRITE_SAME_32 SA emulation not" | ||
1087 | " supported for: %s\n", | ||
1088 | dev->transport->name); | ||
1089 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | ||
1090 | } | ||
1091 | ret = target_emulate_write_same(task); | ||
1092 | break; | ||
1093 | default: | ||
1094 | printk(KERN_ERR "Unsupported VARIABLE_LENGTH_CMD SA:" | ||
1095 | " 0x%02x\n", service_action); | ||
1096 | break; | ||
1097 | } | ||
1098 | break; | ||
1099 | case SYNCHRONIZE_CACHE: | ||
1100 | case 0x91: /* SYNCHRONIZE_CACHE_16: */ | ||
1101 | if (!dev->transport->do_sync_cache) { | ||
1102 | printk(KERN_ERR | ||
1103 | "SYNCHRONIZE_CACHE emulation not supported" | ||
1104 | " for: %s\n", dev->transport->name); | ||
1105 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | ||
1106 | } | ||
1107 | dev->transport->do_sync_cache(task); | ||
1108 | break; | ||
1109 | case ALLOW_MEDIUM_REMOVAL: | ||
1110 | case ERASE: | ||
1111 | case REZERO_UNIT: | ||
1112 | case SEEK_10: | ||
1113 | case SPACE: | ||
1114 | case START_STOP: | ||
1115 | case TEST_UNIT_READY: | ||
1116 | case VERIFY: | ||
1117 | case WRITE_FILEMARKS: | ||
1118 | break; | ||
1119 | default: | ||
1120 | printk(KERN_ERR "Unsupported SCSI Opcode: 0x%02x for %s\n", | ||
1121 | cmd->t_task->t_task_cdb[0], dev->transport->name); | ||
1122 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | ||
1123 | } | ||
1124 | |||
1125 | if (ret < 0) | ||
1126 | return ret; | ||
1127 | task->task_scsi_status = GOOD; | ||
1128 | transport_complete_task(task, 1); | ||
1129 | |||
1130 | return PYX_TRANSPORT_SENT_TO_TRANSPORT; | ||
1131 | } | ||