Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
3 : : * Copyright (C) 2016 Intel Corporation.
4 : : * All rights reserved.
5 : : */
6 : :
7 : : #include "scsi_internal.h"
8 : :
9 : : #include "spdk/env.h"
10 : : #include "spdk/bdev.h"
11 : : #include "spdk/endian.h"
12 : : #include "spdk/likely.h"
13 : : #include "spdk/string.h"
14 : : #include "spdk/util.h"
15 : :
16 : : #define SPDK_WORK_BLOCK_SIZE (4ULL * 1024ULL * 1024ULL)
17 : : #define SPDK_WORK_ATS_BLOCK_SIZE (1ULL * 1024ULL * 1024ULL)
18 : : #define MAX_SERIAL_STRING 32
19 : :
20 : : #define DEFAULT_DISK_VENDOR "INTEL"
21 : : #define DEFAULT_DISK_REVISION "0001"
22 : : #define DEFAULT_DISK_ROTATION_RATE 1 /* Non-rotating medium */
23 : : #define DEFAULT_DISK_FORM_FACTOR 0x02 /* 3.5 inch */
24 : : #define DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT 256
25 : :
26 : : #define INQUIRY_OFFSET(field) offsetof(struct spdk_scsi_cdb_inquiry_data, field) + \
27 : : SPDK_SIZEOF_MEMBER(struct spdk_scsi_cdb_inquiry_data, field)
28 : :
29 : : static void bdev_scsi_process_block_resubmit(void *arg);
30 : :
31 : : static void
32 : 1892 : bdev_scsi_set_naa_ieee_extended(const char *name, uint8_t *buf)
33 : : {
34 : : int i;
35 : 1892 : uint64_t local_value = 0, id_a, seed = 131;
36 : :
37 [ + + ]: 54016 : for (i = 0; name[i] != '\0'; i++) {
38 : 52124 : local_value = (local_value * seed) + name[i];
39 : : }
40 : :
41 : : /*
42 : : * see spc3r23 7.6.3.6.2,
43 : : * NAA IEEE Extended identifier format
44 : : */
45 : 1892 : id_a = local_value & 0x0000000fff000000ull;
46 : 1892 : id_a = id_a << 24;
47 : :
48 : 1892 : local_value &= 0x0000000000ffffffull;
49 : : /* NAA 02, and 00 03 47 for IEEE Intel */
50 : 1892 : local_value |= 0x2000000347000000ull;
51 : 1892 : local_value |= id_a;
52 : :
53 : 1892 : to_be64((void *)buf, local_value);
54 : 1892 : }
55 : :
56 : : static int
57 : 179 : bdev_scsi_report_luns(struct spdk_scsi_lun *lun,
58 : : int sel, uint8_t *data, int alloc_len)
59 : : {
60 : : struct spdk_scsi_dev *dev;
61 : : struct spdk_scsi_lun *tmp_lun;
62 : : uint64_t fmt_lun;
63 : 179 : int hlen, len = 0;
64 : :
65 [ - + ]: 179 : if (alloc_len < 8) {
66 : 0 : return -1;
67 : : }
68 : :
69 [ - + ]: 179 : if (sel == 0x00) {
70 : : /* logical unit with addressing method */
71 [ # # ]: 0 : } else if (sel == 0x01) {
72 : : /* well known logical unit */
73 [ # # ]: 0 : } else if (sel == 0x02) {
74 : : /* logical unit */
75 : : } else {
76 : 0 : return -1;
77 : : }
78 : :
79 : : /* LUN LIST LENGTH */
80 [ - + ]: 179 : memset(data, 0, 4);
81 : :
82 : : /* Reserved */
83 [ - + ]: 179 : memset(&data[4], 0, 4);
84 : 179 : hlen = 8;
85 : :
86 : 179 : dev = lun->dev;
87 : :
88 [ + + ]: 540 : for (tmp_lun = spdk_scsi_dev_get_first_lun(dev); tmp_lun != NULL;
89 : 361 : tmp_lun = spdk_scsi_dev_get_next_lun(tmp_lun)) {
90 [ - + ]: 361 : if (alloc_len - (hlen + len) < 8) {
91 : 0 : return -1;
92 : : }
93 : :
94 : 361 : fmt_lun = spdk_scsi_lun_id_int_to_fmt(tmp_lun->id);
95 : :
96 : : /* LUN */
97 : 361 : to_be64(&data[hlen + len], fmt_lun);
98 : 361 : len += 8;
99 : : }
100 : :
101 : : /* LUN LIST LENGTH */
102 : 179 : to_be32(data, len);
103 : :
104 : 179 : return hlen + len;
105 : : }
106 : :
107 : : static int
108 : 1904 : bdev_scsi_pad_scsi_name(char *dst, const char *name)
109 : : {
110 : : size_t len;
111 : :
112 [ - + ]: 1904 : len = strlen(name);
113 [ - + - + ]: 1904 : memcpy(dst, name, len);
114 : : do {
115 : 3832 : dst[len++] = '\0';
116 [ + + ]: 3832 : } while (len & 3);
117 : :
118 : 1904 : return len;
119 : : }
120 : :
121 : : static int
122 : 13240 : bdev_scsi_inquiry(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
123 : : uint8_t *cdb, uint8_t *data, uint16_t alloc_len)
124 : : {
125 : : struct spdk_scsi_lun *lun;
126 : : struct spdk_scsi_dev *dev;
127 : : struct spdk_scsi_port *port;
128 : : uint32_t blocks, optimal_blocks;
129 : 13240 : int hlen = 0, plen, plen2;
130 : 13240 : uint16_t len = 0;
131 : : int pc;
132 : : int pd;
133 : : int evpd;
134 : : int i;
135 : 13240 : struct spdk_scsi_cdb_inquiry *inq = (struct spdk_scsi_cdb_inquiry *)cdb;
136 : :
137 : : /* standard inquiry command at lease with 36 Bytes */
138 [ - + ]: 13240 : if (alloc_len < 0x24) {
139 : 0 : goto inq_error;
140 : : }
141 : :
142 : 13240 : lun = task->lun;
143 : 13240 : dev = lun->dev;
144 : 13240 : port = task->target_port;
145 : :
146 : 13240 : pd = SPDK_SPC_PERIPHERAL_DEVICE_TYPE_DISK;
147 : 13240 : pc = inq->page_code;
148 : 13240 : evpd = inq->evpd & 0x1;
149 : :
150 [ + + + + ]: 13240 : if (!evpd && pc) {
151 : 5 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
152 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
153 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
154 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
155 : 5 : return -1;
156 : : }
157 : :
158 [ + + ]: 13235 : if (evpd) {
159 : 10121 : struct spdk_scsi_vpd_page *vpage = (struct spdk_scsi_vpd_page *)data;
160 : :
161 : : /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
162 : 10121 : vpage->peripheral_device_type = pd;
163 : 10121 : vpage->peripheral_qualifier = SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED;
164 : : /* PAGE CODE */
165 : 10121 : vpage->page_code = pc;
166 : :
167 : : /* Vital product data */
168 [ + + + - : 10121 : switch (pc) {
- - - + +
+ + ]
169 : 2603 : case SPDK_SPC_VPD_SUPPORTED_VPD_PAGES:
170 : 2603 : hlen = 4;
171 : :
172 : 2603 : vpage->params[0] = SPDK_SPC_VPD_SUPPORTED_VPD_PAGES;
173 : 2603 : vpage->params[1] = SPDK_SPC_VPD_UNIT_SERIAL_NUMBER;
174 : 2603 : vpage->params[2] = SPDK_SPC_VPD_DEVICE_IDENTIFICATION;
175 : 2603 : vpage->params[3] = SPDK_SPC_VPD_MANAGEMENT_NETWORK_ADDRESSES;
176 : 2603 : vpage->params[4] = SPDK_SPC_VPD_EXTENDED_INQUIRY_DATA;
177 : 2603 : vpage->params[5] = SPDK_SPC_VPD_MODE_PAGE_POLICY;
178 : 2603 : vpage->params[6] = SPDK_SPC_VPD_SCSI_PORTS;
179 : 2603 : vpage->params[7] = SPDK_SPC_VPD_BLOCK_LIMITS;
180 : 2603 : vpage->params[8] = SPDK_SPC_VPD_BLOCK_DEV_CHARS;
181 : 2603 : len = 9;
182 [ + + ]: 2603 : if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
183 : 2589 : vpage->params[9] = SPDK_SPC_VPD_BLOCK_THIN_PROVISION;
184 : 2589 : len++;
185 : : }
186 : :
187 : : /* PAGE LENGTH */
188 : 2603 : to_be16(vpage->alloc_len, len);
189 : 2603 : break;
190 : :
191 : 1892 : case SPDK_SPC_VPD_UNIT_SERIAL_NUMBER: {
192 : 1892 : const char *name = spdk_bdev_get_name(bdev);
193 : :
194 : 1892 : hlen = 4;
195 : :
196 : : /* PRODUCT SERIAL NUMBER */
197 [ - + ]: 1892 : len = strlen(name) + 1;
198 [ + + ]: 1892 : if (len > MAX_SERIAL_STRING) {
199 : 1340 : len = MAX_SERIAL_STRING;
200 : : }
201 : :
202 [ - + - + ]: 1892 : memcpy(vpage->params, name, len - 1);
203 : 1892 : vpage->params[len - 1] = 0;
204 : :
205 : : /* PAGE LENGTH */
206 : 1892 : to_be16(vpage->alloc_len, len);
207 : 1892 : break;
208 : : }
209 : :
210 : 1892 : case SPDK_SPC_VPD_DEVICE_IDENTIFICATION: {
211 : 1892 : const char *name = spdk_bdev_get_name(bdev);
212 : 1892 : const char *product_name = spdk_bdev_get_product_name(bdev);
213 : 1892 : uint8_t protocol_id = dev->protocol_id;
214 : 1892 : uint8_t *buf = vpage->params;
215 : : struct spdk_scsi_desig_desc *desig;
216 : :
217 : 1892 : hlen = 4;
218 : :
219 : : /* Check total length by calculated how much space all entries take */
220 : 1892 : len = sizeof(struct spdk_scsi_desig_desc) + 8;
221 : 1892 : len += sizeof(struct spdk_scsi_desig_desc) + 8 + 16 + MAX_SERIAL_STRING;
222 : 1892 : len += sizeof(struct spdk_scsi_desig_desc) + SPDK_SCSI_DEV_MAX_NAME + 1;
223 : 1892 : len += sizeof(struct spdk_scsi_desig_desc) + SPDK_SCSI_PORT_MAX_NAME_LENGTH;
224 : 1892 : len += sizeof(struct spdk_scsi_desig_desc) + 4;
225 : 1892 : len += sizeof(struct spdk_scsi_desig_desc) + 4;
226 : 1892 : len += sizeof(struct spdk_scsi_desig_desc) + 4;
227 [ - + ]: 1892 : if (sizeof(struct spdk_scsi_vpd_page) + len > alloc_len) {
228 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
229 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
230 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
231 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
232 : 0 : return -1;
233 : : }
234 : :
235 : : /* Now fill out the designator array */
236 : :
237 : : /* NAA designator */
238 : 1892 : desig = (struct spdk_scsi_desig_desc *)buf;
239 : 1892 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
240 : 1892 : desig->protocol_id = protocol_id;
241 : 1892 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_NAA;
242 : 1892 : desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
243 : 1892 : desig->reserved0 = 0;
244 : 1892 : desig->piv = 1;
245 : 1892 : desig->reserved1 = 0;
246 : 1892 : desig->len = 8;
247 : 1892 : bdev_scsi_set_naa_ieee_extended(name, desig->desig);
248 : 1892 : len = sizeof(struct spdk_scsi_desig_desc) + 8;
249 : :
250 : 1892 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
251 : :
252 : : /* T10 Vendor ID designator */
253 : 1892 : desig = (struct spdk_scsi_desig_desc *)buf;
254 : 1892 : desig->code_set = SPDK_SPC_VPD_CODE_SET_ASCII;
255 : 1892 : desig->protocol_id = protocol_id;
256 : 1892 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_T10_VENDOR_ID;
257 : 1892 : desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
258 : 1892 : desig->reserved0 = 0;
259 : 1892 : desig->piv = 1;
260 : 1892 : desig->reserved1 = 0;
261 : 1892 : desig->len = 8 + 16 + MAX_SERIAL_STRING;
262 : 1892 : spdk_strcpy_pad(desig->desig, DEFAULT_DISK_VENDOR, 8, ' ');
263 : 1892 : spdk_strcpy_pad(&desig->desig[8], product_name, 16, ' ');
264 : 1892 : spdk_strcpy_pad(&desig->desig[24], name, MAX_SERIAL_STRING, ' ');
265 : 1892 : len += sizeof(struct spdk_scsi_desig_desc) + 8 + 16 + MAX_SERIAL_STRING;
266 : :
267 : 1892 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
268 : :
269 : : /* SCSI Device Name designator */
270 : 1892 : desig = (struct spdk_scsi_desig_desc *)buf;
271 : 1892 : desig->code_set = SPDK_SPC_VPD_CODE_SET_UTF8;
272 : 1892 : desig->protocol_id = protocol_id;
273 : 1892 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
274 : 1892 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_DEVICE;
275 : 1892 : desig->reserved0 = 0;
276 : 1892 : desig->piv = 1;
277 : 1892 : desig->reserved1 = 0;
278 : 1892 : desig->len = bdev_scsi_pad_scsi_name(desig->desig, dev->name);
279 : 1892 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
280 : :
281 : 1892 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
282 : :
283 : : /* SCSI Port Name designator */
284 : 1892 : desig = (struct spdk_scsi_desig_desc *)buf;
285 : 1892 : desig->code_set = SPDK_SPC_VPD_CODE_SET_UTF8;
286 : 1892 : desig->protocol_id = protocol_id;
287 : 1892 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
288 : 1892 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
289 : 1892 : desig->reserved0 = 0;
290 : 1892 : desig->piv = 1;
291 : 1892 : desig->reserved1 = 0;
292 : 1892 : desig->len = snprintf(desig->desig, SPDK_SCSI_PORT_MAX_NAME_LENGTH, "%s", port->name);
293 : 1892 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
294 : :
295 : 1892 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
296 : :
297 : : /* Relative Target Port designator */
298 : 1892 : desig = (struct spdk_scsi_desig_desc *)buf;
299 : 1892 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
300 : 1892 : desig->protocol_id = protocol_id;
301 : 1892 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_RELATIVE_TARGET_PORT;
302 : 1892 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
303 : 1892 : desig->reserved0 = 0;
304 : 1892 : desig->piv = 1;
305 : 1892 : desig->reserved1 = 0;
306 : 1892 : desig->len = 4;
307 [ - + ]: 1892 : memset(desig->desig, 0, 2); /* Reserved */
308 : 1892 : to_be16(&desig->desig[2], port->index);
309 : 1892 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
310 : :
311 : 1892 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
312 : :
313 : : /* Target port group designator */
314 : 1892 : desig = (struct spdk_scsi_desig_desc *)buf;
315 : 1892 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
316 : 1892 : desig->protocol_id = protocol_id;
317 : 1892 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_TARGET_PORT_GROUP;
318 : 1892 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
319 : 1892 : desig->reserved0 = 0;
320 : 1892 : desig->piv = 1;
321 : 1892 : desig->reserved1 = 0;
322 : 1892 : desig->len = 4;
323 [ - + ]: 1892 : memset(desig->desig, 0, 4);
324 : 1892 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
325 : :
326 : 1892 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
327 : :
328 : : /* Logical unit group designator */
329 : 1892 : desig = (struct spdk_scsi_desig_desc *)buf;
330 : 1892 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
331 : 1892 : desig->protocol_id = protocol_id;
332 : 1892 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_LOGICAL_UNIT_GROUP;
333 : 1892 : desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
334 : 1892 : desig->reserved0 = 0;
335 : 1892 : desig->piv = 1;
336 : 1892 : desig->reserved1 = 0;
337 : 1892 : desig->len = 4;
338 [ - + ]: 1892 : memset(desig->desig, 0, 2); /* Reserved */
339 : 1892 : to_be16(&desig->desig[2], dev->id);
340 : 1892 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
341 : :
342 : 1892 : to_be16(vpage->alloc_len, len);
343 : :
344 : 1892 : break;
345 : : }
346 : :
347 : 0 : case SPDK_SPC_VPD_EXTENDED_INQUIRY_DATA: {
348 : 0 : struct spdk_scsi_vpd_ext_inquiry *vext = (struct spdk_scsi_vpd_ext_inquiry *)vpage;
349 : :
350 : 0 : hlen = 4;
351 [ # # ]: 0 : memset((uint8_t *)vext + hlen, 0, sizeof(*vext) - hlen);
352 : :
353 : : /* RTO(3) GRD_CHK(2) APP_CHK(1) REF_CHK(0) */
354 : :
355 : : /* GROUP_SUP(4) PRIOR_SUP(3) HEADSUP(2) ORDSUP(1) SIMPSUP(0) */
356 : 0 : vext->sup = SPDK_SCSI_VEXT_HEADSUP | SPDK_SCSI_VEXT_SIMPSUP;
357 : :
358 : : /* NV_SUP(1) V_SUP(0) */
359 : :
360 : : /* Reserved[7-63] */
361 : :
362 : 0 : len = 64 - hlen;
363 : :
364 : : /* PAGE LENGTH */
365 : 0 : to_be16(vpage->alloc_len, len);
366 : 0 : break;
367 : : }
368 : :
369 : 0 : case SPDK_SPC_VPD_MANAGEMENT_NETWORK_ADDRESSES:
370 : : /* PAGE LENGTH */
371 : 0 : hlen = 4;
372 : :
373 : 0 : to_be16(vpage->alloc_len, len);
374 : 0 : break;
375 : :
376 : 0 : case SPDK_SPC_VPD_MODE_PAGE_POLICY: {
377 : 0 : struct spdk_scsi_mpage_policy_desc *pdesc =
378 : : (struct spdk_scsi_mpage_policy_desc *)vpage->params;
379 : :
380 : 0 : hlen = 4;
381 : :
382 : : /* Mode page policy descriptor 1 */
383 : :
384 : : /* POLICY PAGE CODE(5-0) */
385 : : /* all page code */
386 : 0 : pdesc->page_code = 0x3f;
387 : :
388 : : /* POLICY SUBPAGE CODE */
389 : : /* all sub page */
390 : 0 : pdesc->sub_page_code = 0xff;
391 : :
392 : : /* MLUS(7) MODE PAGE POLICY(1-0) */
393 : : /* MLUS own copy */
394 : : /* Shared MODE PAGE policy */
395 : 0 : pdesc->policy = 0;
396 : : /* Reserved */
397 : 0 : pdesc->reserved = 0;
398 : :
399 : 0 : len += 4;
400 : :
401 : 0 : to_be16(vpage->alloc_len, len);
402 : 0 : break;
403 : : }
404 : :
405 : 0 : case SPDK_SPC_VPD_SCSI_PORTS: {
406 : : /* PAGE LENGTH */
407 : 0 : hlen = 4;
408 : :
409 : : /* Identification descriptor list */
410 [ # # ]: 0 : for (i = 0; i < SPDK_SCSI_DEV_MAX_PORTS; i++) {
411 : : struct spdk_scsi_port_desc *sdesc;
412 : : struct spdk_scsi_tgt_port_desc *pdesc;
413 : :
414 [ # # ]: 0 : if (!dev->port[i].is_used) {
415 : 0 : continue;
416 : : }
417 : :
418 : : /* Identification descriptor N */
419 : 0 : sdesc = (struct spdk_scsi_port_desc *)&vpage->params[len];
420 : :
421 : : /* Reserved */
422 : 0 : sdesc->reserved = 0;
423 : :
424 : : /* RELATIVE PORT IDENTIFIER */
425 : 0 : to_be16(&sdesc->rel_port_id, dev->port[i].index);
426 : :
427 : : /* Reserved */
428 : 0 : sdesc->reserved2 = 0;
429 : :
430 : : /* INITIATOR PORT TRANSPORTID LENGTH */
431 : 0 : sdesc->init_port_len = 0;
432 : :
433 : : /* Reserved */
434 : 0 : sdesc->init_port_id = 0;
435 : :
436 : : /* TARGET PORT DESCRIPTORS LENGTH */
437 : 0 : sdesc->tgt_desc_len = 0;
438 : :
439 : 0 : len += 12;
440 : :
441 : 0 : plen2 = 0;
442 : : /* Target port descriptor 1 */
443 : 0 : pdesc = (struct spdk_scsi_tgt_port_desc *)sdesc->tgt_desc;
444 : :
445 : : /* PROTOCOL IDENTIFIER(7-4) CODE SET(3-0) */
446 : 0 : pdesc->code_set =
447 : : SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI << 4 |
448 : : SPDK_SPC_VPD_CODE_SET_UTF8;
449 : :
450 : : /* PIV(7) ASSOCIATION(5-4) IDENTIFIER TYPE(3-0) */
451 : 0 : pdesc->desig_type = SPDK_SPC_VPD_DESIG_PIV |
452 : : SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT << 4 |
453 : : SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
454 : :
455 : : /* Reserved */
456 : 0 : pdesc->reserved = 0;
457 : :
458 : : /* IDENTIFIER */
459 : 0 : plen = snprintf((char *)pdesc->designator,
460 : : SPDK_SCSI_PORT_MAX_NAME_LENGTH, "%s",
461 : 0 : dev->port[i].name);
462 : 0 : pdesc->len = plen;
463 : :
464 : 0 : plen2 += 4 + plen;
465 : :
466 : : /* TARGET PORT DESCRIPTORS LENGTH */
467 : 0 : to_be16(&sdesc->tgt_desc_len, plen2);
468 : :
469 : 0 : len += plen2;
470 : : }
471 : :
472 : 0 : to_be16(vpage->alloc_len, len);
473 : 0 : break;
474 : : }
475 : :
476 : 694 : case SPDK_SPC_VPD_BLOCK_LIMITS: {
477 : 694 : uint32_t block_size = spdk_bdev_get_data_block_size(bdev);
478 : :
479 : : /* PAGE LENGTH */
480 [ - + ]: 694 : memset(&data[4], 0, 60);
481 : :
482 : 694 : hlen = 4;
483 : :
484 : : /* WSNZ(0) */
485 : : /* support zero length in WRITE SAME */
486 : :
487 : : /* MAXIMUM COMPARE AND WRITE LENGTH */
488 [ - + ]: 694 : blocks = SPDK_WORK_ATS_BLOCK_SIZE / block_size;
489 : :
490 [ + - ]: 694 : if (blocks > 0xff) {
491 : 694 : blocks = 0xff;
492 : : }
493 : :
494 : 694 : data[5] = (uint8_t)blocks;
495 : :
496 : : /* force align to 4KB */
497 [ + + ]: 694 : if (block_size < 4096) {
498 [ - + ]: 478 : optimal_blocks = 4096 / block_size;
499 : : } else {
500 : 216 : optimal_blocks = 1;
501 : : }
502 : :
503 : : /* OPTIMAL TRANSFER LENGTH GRANULARITY */
504 : 694 : to_be16(&data[6], optimal_blocks);
505 : :
506 [ - + ]: 694 : blocks = SPDK_WORK_BLOCK_SIZE / block_size;
507 : :
508 : : /* MAXIMUM TRANSFER LENGTH */
509 : 694 : to_be32(&data[8], blocks);
510 : : /* OPTIMAL TRANSFER LENGTH */
511 : 694 : to_be32(&data[12], blocks);
512 : :
513 : : /* MAXIMUM PREFETCH XDREAD XDWRITE TRANSFER LENGTH */
514 : :
515 [ + + ]: 694 : if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
516 : : /*
517 : : * MAXIMUM UNMAP LBA COUNT: indicates the
518 : : * maximum number of LBAs that may be
519 : : * unmapped by an UNMAP command.
520 : : */
521 : : /* For now, choose 4MB as the maximum. */
522 : 690 : to_be32(&data[20], 4194304);
523 : :
524 : : /*
525 : : * MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT:
526 : : * indicates the maximum number of UNMAP
527 : : * block descriptors that shall be contained
528 : : * in the parameter data transferred to the
529 : : * device server for an UNMAP command.
530 : : * The bdev layer automatically splits unmap
531 : : * requests, so pick an arbitrary high number here.
532 : : */
533 : 690 : to_be32(&data[24], DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT);
534 : :
535 : : /*
536 : : * The UGAVALID bit is left as 0 which means neither the
537 : : * OPTIMAL UNMAP GRANULARITY nor the UNMAP GRANULARITY
538 : : * ALIGNMENT fields are valid.
539 : : */
540 : : }
541 : :
542 : : /*
543 : : * MAXIMUM WRITE SAME LENGTH: indicates the
544 : : * maximum number of contiguous logical blocks
545 : : * that the device server allows to be unmapped
546 : : * or written in a single WRITE SAME command.
547 : : */
548 : 694 : to_be64(&data[36], blocks);
549 : :
550 : : /* Reserved */
551 : : /* not specified */
552 : 694 : len = 64 - hlen;
553 : :
554 : 694 : to_be16(vpage->alloc_len, len);
555 : 694 : break;
556 : : }
557 : :
558 : 686 : case SPDK_SPC_VPD_BLOCK_DEV_CHARS: {
559 : : /* PAGE LENGTH */
560 : 686 : hlen = 4;
561 : 686 : len = 64 - hlen;
562 : :
563 : 686 : to_be16(&data[4], DEFAULT_DISK_ROTATION_RATE);
564 : :
565 : : /* Reserved */
566 : 686 : data[6] = 0;
567 : : /* NOMINAL FORM FACTOR(3-0) */
568 : 686 : data[7] = DEFAULT_DISK_FORM_FACTOR << 4;
569 : : /* Reserved */
570 [ - + ]: 686 : memset(&data[8], 0, 64 - 8);
571 : :
572 : 686 : to_be16(vpage->alloc_len, len);
573 : 686 : break;
574 : : }
575 : :
576 : 716 : case SPDK_SPC_VPD_BLOCK_THIN_PROVISION: {
577 [ + + ]: 716 : if (!spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
578 : 1 : goto inq_error;
579 : : }
580 : :
581 : 715 : hlen = 4;
582 : 715 : len = 7;
583 : :
584 : : /*
585 : : * PAGE LENGTH : if the DP bit is set to one, then the
586 : : * page length shall be set 0004h.
587 : : */
588 : 715 : to_be16(&data[2], 0x0004);
589 : :
590 : : /*
591 : : * THRESHOLD EXPONENT : it indicates the threshold set
592 : : * size in LBAs as a power of 2( i.e., the threshold
593 : : * set size = 2 ^ (threshold exponent).
594 : : */
595 : 715 : data[4] = 0;
596 : :
597 : : /*
598 : : * Set the LBPU bit to indicate the support for UNMAP
599 : : * command.
600 : : */
601 : 715 : data[5] |= SPDK_SCSI_UNMAP_LBPU;
602 : :
603 : : /*
604 : : * Set the provisioning type to thin provision.
605 : : */
606 : 715 : data[6] = SPDK_SCSI_UNMAP_THIN_PROVISIONING;
607 : :
608 : 715 : to_be16(vpage->alloc_len, len);
609 : 715 : break;
610 : : }
611 : :
612 : 1638 : default:
613 [ - + - - ]: 1638 : if (pc >= 0xc0 && pc <= 0xff) {
614 [ # # # # ]: 0 : SPDK_DEBUGLOG(scsi, "Vendor specific INQUIRY VPD page 0x%x\n", pc);
615 : : } else {
616 : 1638 : SPDK_NOTICELOG("unsupported INQUIRY VPD page 0x%x\n", pc);
617 : : }
618 : 1638 : goto inq_error;
619 : : }
620 : : } else {
621 : 3114 : struct spdk_scsi_cdb_inquiry_data *inqdata =
622 : : (struct spdk_scsi_cdb_inquiry_data *)data;
623 : :
624 : : /* Standard INQUIRY data */
625 : : /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
626 : 3114 : inqdata->peripheral_device_type = pd;
627 : 3114 : inqdata->peripheral_qualifier = SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED;
628 : :
629 : : /* RMB(7) */
630 : 3114 : inqdata->rmb = 0;
631 : :
632 : : /* VERSION */
633 : : /* See SPC3/SBC2/MMC4/SAM2 for more details */
634 : 3114 : inqdata->version = SPDK_SPC_VERSION_SPC3;
635 : :
636 : : /* NORMACA(5) HISUP(4) RESPONSE DATA FORMAT(3-0) */
637 : : /* format 2 */ /* hierarchical support */
638 : 3114 : inqdata->response = 2 | 1 << 4;
639 : :
640 : 3114 : hlen = 5;
641 : :
642 : : /* SCCS(7) ACC(6) TPGS(5-4) 3PC(3) PROTECT(0) */
643 : : /* Not support TPGS */
644 : 3114 : inqdata->flags = 0;
645 : :
646 : : /* MULTIP */
647 : 3114 : inqdata->flags2 = 0x10;
648 : :
649 : : /* WBUS16(5) SYNC(4) LINKED(3) CMDQUE(1) VS(0) */
650 : : /* CMDQUE */
651 : 3114 : inqdata->flags3 = 0x2;
652 : :
653 : : /* T10 VENDOR IDENTIFICATION */
654 : 3114 : spdk_strcpy_pad(inqdata->t10_vendor_id, DEFAULT_DISK_VENDOR, 8, ' ');
655 : :
656 : : /* PRODUCT IDENTIFICATION */
657 : 3114 : spdk_strcpy_pad(inqdata->product_id, spdk_bdev_get_product_name(bdev), 16, ' ');
658 : :
659 : : /* PRODUCT REVISION LEVEL */
660 : 3114 : spdk_strcpy_pad(inqdata->product_rev, DEFAULT_DISK_REVISION, 4, ' ');
661 : :
662 : : /*
663 : : * Standard inquiry data ends here. Only populate remaining fields if alloc_len
664 : : * indicates enough space to hold it.
665 : : */
666 : 3114 : len = INQUIRY_OFFSET(product_rev) - 5;
667 : :
668 [ + - ]: 3114 : if (alloc_len >= INQUIRY_OFFSET(vendor)) {
669 : : /* Vendor specific */
670 [ - + ]: 3114 : memset(inqdata->vendor, 0x20, 20);
671 : 3114 : len += sizeof(inqdata->vendor);
672 : : }
673 : :
674 [ + - ]: 3114 : if (alloc_len >= INQUIRY_OFFSET(ius)) {
675 : : /* CLOCKING(3-2) QAS(1) IUS(0) */
676 : 3114 : inqdata->ius = 0;
677 : 3114 : len += sizeof(inqdata->ius);
678 : : }
679 : :
680 [ + - ]: 3114 : if (alloc_len >= INQUIRY_OFFSET(reserved)) {
681 : : /* Reserved */
682 : 3114 : inqdata->reserved = 0;
683 : 3114 : len += sizeof(inqdata->reserved);
684 : : }
685 : :
686 : : /* VERSION DESCRIPTOR 1-8 */
687 [ + - ]: 3114 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 2) {
688 : 3114 : to_be16(&inqdata->desc[0], 0x0960);
689 : 3114 : len += 2;
690 : : }
691 : :
692 [ + - ]: 3114 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 4) {
693 : 3114 : to_be16(&inqdata->desc[2], 0x0300); /* SPC-3 (no version claimed) */
694 : 3114 : len += 2;
695 : : }
696 : :
697 [ + - ]: 3114 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 6) {
698 : 3114 : to_be16(&inqdata->desc[4], 0x320); /* SBC-2 (no version claimed) */
699 : 3114 : len += 2;
700 : : }
701 : :
702 [ + - ]: 3114 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 8) {
703 : 3114 : to_be16(&inqdata->desc[6], 0x0040); /* SAM-2 (no version claimed) */
704 : 3114 : len += 2;
705 : : }
706 : :
707 : : /*
708 : : * We only fill out 4 descriptors, but if the allocation length goes past
709 : : * that, zero the remaining bytes. This fixes some SCSI compliance tests
710 : : * which expect a full 96 bytes to be returned, including the unpopulated
711 : : * version descriptors 5-8 (4 * 2 = 8 bytes) plus the 22 bytes of reserved
712 : : * space (bytes 74-95) - for a total of 30 bytes.
713 : : */
714 [ + - ]: 3114 : if (alloc_len > INQUIRY_OFFSET(reserved) + 8) {
715 : 3114 : i = alloc_len - (INQUIRY_OFFSET(reserved) + 8);
716 [ + - ]: 3114 : if (i > 30) {
717 : 3114 : i = 30;
718 : : }
719 [ - + ]: 3114 : memset(&inqdata->desc[8], 0, i);
720 : 3114 : len += i;
721 : : }
722 : :
723 : : /* ADDITIONAL LENGTH */
724 : 3114 : inqdata->add_len = len;
725 : : }
726 : :
727 : 11596 : return hlen + len;
728 : :
729 : 1639 : inq_error:
730 : 1639 : task->data_transferred = 0;
731 : 1639 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
732 : : SPDK_SCSI_SENSE_NO_SENSE,
733 : : SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
734 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
735 : 1639 : return -1;
736 : : }
737 : :
738 : : static void
739 : 39748 : mode_sense_page_init(uint8_t *buf, int len, int page, int subpage)
740 : : {
741 [ + + ]: 39748 : if (!buf) {
742 : 19874 : return;
743 : : }
744 : :
745 [ - + ]: 19874 : memset(buf, 0, len);
746 [ - + ]: 19874 : if (subpage != 0) {
747 : 0 : buf[0] = page | 0x40; /* PAGE + SPF=1 */
748 : 0 : buf[1] = subpage;
749 : 0 : to_be16(&buf[2], len - 4);
750 : : } else {
751 : 19874 : buf[0] = page;
752 : 19874 : buf[1] = len - 2;
753 : : }
754 : : }
755 : :
756 : : static int
757 : 258538 : bdev_scsi_mode_sense_page(struct spdk_bdev *bdev,
758 : : uint8_t *cdb, int pc, int page, int subpage,
759 : : uint8_t *data, struct spdk_scsi_task *task)
760 : : {
761 : 258538 : uint8_t *cp = data;
762 : 258538 : int len = 0;
763 : : int plen;
764 : : int i;
765 : :
766 [ - + ]: 258538 : if (pc == 0x00) {
767 : : /* Current values */
768 [ # # ]: 0 : } else if (pc == 0x01) {
769 : : /* Changeable values */
770 : : /* As we currently do not support changeable values,
771 : : all parameters are reported as zero. */
772 [ # # ]: 0 : } else if (pc == 0x02) {
773 : : /* Default values */
774 : : } else {
775 : : /* Saved values not supported */
776 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
777 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
778 : : SPDK_SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED,
779 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
780 : 0 : return -1;
781 : : }
782 : :
783 [ + + + + : 258538 : switch (page) {
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + - ]
784 : 3978 : case 0x00:
785 : : /* Vendor specific */
786 : 3978 : break;
787 : 3978 : case 0x01:
788 : : /* Read-Write Error Recovery */
789 [ - + - + ]: 3978 : SPDK_DEBUGLOG(scsi,
790 : : "MODE_SENSE Read-Write Error Recovery\n");
791 [ - + ]: 3978 : if (subpage != 0x00) {
792 : 0 : break;
793 : : }
794 : 3978 : plen = 0x0a + 2;
795 : 3978 : mode_sense_page_init(cp, plen, page, subpage);
796 : 3978 : len += plen;
797 : 3978 : break;
798 : 3978 : case 0x02:
799 : : /* Disconnect-Reconnect */
800 [ - + - + ]: 3978 : SPDK_DEBUGLOG(scsi,
801 : : "MODE_SENSE Disconnect-Reconnect\n");
802 [ - + ]: 3978 : if (subpage != 0x00) {
803 : 0 : break;
804 : : }
805 : 3978 : plen = 0x0e + 2;
806 : 3978 : mode_sense_page_init(cp, plen, page, subpage);
807 : 3978 : len += plen;
808 : 3978 : break;
809 : 3978 : case 0x03:
810 : : /* Obsolete (Format Device) */
811 : 3978 : break;
812 : 3978 : case 0x04:
813 : : /* Obsolete (Rigid Disk Geometry) */
814 : 3978 : break;
815 : 3978 : case 0x05:
816 : : /* Obsolete (Rigid Disk Geometry) */
817 : 3978 : break;
818 : 3978 : case 0x06:
819 : : /* Reserved */
820 : 3978 : break;
821 : 3978 : case 0x07:
822 : : /* Verify Error Recovery */
823 [ - + - + ]: 3978 : SPDK_DEBUGLOG(scsi,
824 : : "MODE_SENSE Verify Error Recovery\n");
825 : :
826 [ - + ]: 3978 : if (subpage != 0x00) {
827 : 0 : break;
828 : : }
829 : :
830 : 3978 : plen = 0x0a + 2;
831 : 3978 : mode_sense_page_init(cp, plen, page, subpage);
832 : 3978 : len += plen;
833 : 3978 : break;
834 : 11902 : case 0x08: {
835 : : /* Caching */
836 [ - + - + ]: 11902 : SPDK_DEBUGLOG(scsi, "MODE_SENSE Caching\n");
837 [ - + ]: 11902 : if (subpage != 0x00) {
838 : 0 : break;
839 : : }
840 : :
841 : 11902 : plen = 0x12 + 2;
842 : 11902 : mode_sense_page_init(cp, plen, page, subpage);
843 : :
844 [ + + + + : 11902 : if (cp && spdk_bdev_has_write_cache(bdev) && pc != 0x01) {
+ - ]
845 : 834 : cp[2] |= 0x4; /* WCE */
846 : : }
847 : :
848 : : /* Read Cache Disable (RCD) = 1 */
849 [ + + + - ]: 11902 : if (cp && pc != 0x01) {
850 : 5951 : cp[2] |= 0x1;
851 : : }
852 : :
853 : 11902 : len += plen;
854 : 11902 : break;
855 : : }
856 : 3978 : case 0x09:
857 : : /* Obsolete */
858 : 3978 : break;
859 [ + - - - ]: 3978 : case 0x0a:
860 : : switch (subpage) {
861 : 3978 : case 0x00:
862 : : /* Control */
863 [ - + - + ]: 3978 : SPDK_DEBUGLOG(scsi,
864 : : "MODE_SENSE Control\n");
865 : 3978 : plen = 0x0a + 2;
866 : 3978 : mode_sense_page_init(cp, plen, page, subpage);
867 : 3978 : len += plen;
868 : 3978 : break;
869 : 0 : case 0x01:
870 : : /* Control Extension */
871 [ # # # # ]: 0 : SPDK_DEBUGLOG(scsi,
872 : : "MODE_SENSE Control Extension\n");
873 : 0 : plen = 0x1c + 4;
874 : 0 : mode_sense_page_init(cp, plen, page, subpage);
875 : 0 : len += plen;
876 : 0 : break;
877 : 0 : case 0xff:
878 : : /* All subpages */
879 [ # # ]: 0 : len += bdev_scsi_mode_sense_page(bdev,
880 : : cdb, pc, page,
881 : : 0x00,
882 : 0 : cp ? &cp[len] : NULL, task);
883 [ # # ]: 0 : len += bdev_scsi_mode_sense_page(bdev,
884 : : cdb, pc, page,
885 : : 0x01,
886 : 0 : cp ? &cp[len] : NULL, task);
887 : 0 : break;
888 : 0 : default:
889 : : /* 0x02-0x3e: Reserved */
890 : 0 : break;
891 : : }
892 : 3978 : break;
893 : 3978 : case 0x0b:
894 : : /* Obsolete (Medium Types Supported) */
895 : 3978 : break;
896 : 3978 : case 0x0c:
897 : : /* Obsolete (Notch And Partition) */
898 : 3978 : break;
899 : 3978 : case 0x0d:
900 : : /* Obsolete */
901 : 3978 : break;
902 : 7956 : case 0x0e:
903 : : case 0x0f:
904 : : /* Reserved */
905 : 7956 : break;
906 : 3978 : case 0x10:
907 : : /* XOR Control */
908 [ - + - + ]: 3978 : SPDK_DEBUGLOG(scsi, "MODE_SENSE XOR Control\n");
909 [ - + ]: 3978 : if (subpage != 0x00) {
910 : 0 : break;
911 : : }
912 : 3978 : plen = 0x16 + 2;
913 : 3978 : mode_sense_page_init(cp, plen, page, subpage);
914 : 3978 : len += plen;
915 : 3978 : break;
916 : 11934 : case 0x11:
917 : : case 0x12:
918 : : case 0x13:
919 : : /* Reserved */
920 : 11934 : break;
921 : 3978 : case 0x14:
922 : : /* Enclosure Services Management */
923 : 3978 : break;
924 : 11934 : case 0x15:
925 : : case 0x16:
926 : : case 0x17:
927 : : /* Reserved */
928 : 11934 : break;
929 : 3978 : case 0x18:
930 : : /* Protocol-Specific LUN */
931 : 3978 : break;
932 : 3978 : case 0x19:
933 : : /* Protocol-Specific Port */
934 : 3978 : break;
935 : 3978 : case 0x1a:
936 : : /* Power Condition */
937 [ - + - + ]: 3978 : SPDK_DEBUGLOG(scsi,
938 : : "MODE_SENSE Power Condition\n");
939 [ - + ]: 3978 : if (subpage != 0x00) {
940 : 0 : break;
941 : : }
942 : 3978 : plen = 0x0a + 2;
943 : 3978 : mode_sense_page_init(cp, plen, page, subpage);
944 : 3978 : len += plen;
945 : 3978 : break;
946 : 3978 : case 0x1b:
947 : : /* Reserved */
948 : 3978 : break;
949 : 3978 : case 0x1c:
950 : : /* Informational Exceptions Control */
951 [ - + - + ]: 3978 : SPDK_DEBUGLOG(scsi,
952 : : "MODE_SENSE Informational Exceptions Control\n");
953 [ - + ]: 3978 : if (subpage != 0x00) {
954 : 0 : break;
955 : : }
956 : :
957 : 3978 : plen = 0x0a + 2;
958 : 3978 : mode_sense_page_init(cp, plen, page, subpage);
959 : 3978 : len += plen;
960 : 3978 : break;
961 : 11934 : case 0x1d:
962 : : case 0x1e:
963 : : case 0x1f:
964 : : /* Reserved */
965 : 11934 : break;
966 : 119340 : case 0x20:
967 : : case 0x21:
968 : : case 0x22:
969 : : case 0x23:
970 : : case 0x24:
971 : : case 0x25:
972 : : case 0x26:
973 : : case 0x27:
974 : : case 0x28:
975 : : case 0x29:
976 : : case 0x2a:
977 : : case 0x2b:
978 : : case 0x2c:
979 : : case 0x2d:
980 : : case 0x2e:
981 : : case 0x2f:
982 : : case 0x30:
983 : : case 0x31:
984 : : case 0x32:
985 : : case 0x33:
986 : : case 0x34:
987 : : case 0x35:
988 : : case 0x36:
989 : : case 0x37:
990 : : case 0x38:
991 : : case 0x39:
992 : : case 0x3a:
993 : : case 0x3b:
994 : : case 0x3c:
995 : : case 0x3d:
996 : : case 0x3e:
997 : : /* Vendor-specific */
998 : 119340 : break;
999 [ + - - ]: 3978 : case 0x3f:
1000 : : switch (subpage) {
1001 : 3978 : case 0x00:
1002 : : /* All mode pages */
1003 [ + + ]: 250614 : for (i = 0x00; i < 0x3e; i ++) {
1004 [ + + ]: 369954 : len += bdev_scsi_mode_sense_page(
1005 : : bdev, cdb, pc, i, 0x00,
1006 : 123318 : cp ? &cp[len] : NULL, task);
1007 : : }
1008 : 3978 : break;
1009 : 0 : case 0xff:
1010 : : /* All mode pages and subpages */
1011 [ # # ]: 0 : for (i = 0x00; i < 0x3e; i ++) {
1012 [ # # ]: 0 : len += bdev_scsi_mode_sense_page(
1013 : : bdev, cdb, pc, i, 0x00,
1014 : 0 : cp ? &cp[len] : NULL, task);
1015 : : }
1016 [ # # ]: 0 : for (i = 0x00; i < 0x3e; i ++) {
1017 [ # # ]: 0 : len += bdev_scsi_mode_sense_page(
1018 : : bdev, cdb, pc, i, 0xff,
1019 : 0 : cp ? &cp[len] : NULL, task);
1020 : : }
1021 : 0 : break;
1022 : 0 : default:
1023 : : /* 0x01-0x3e: Reserved */
1024 : 0 : break;
1025 : : }
1026 : 504 : }
1027 : :
1028 : 258538 : return len;
1029 : : }
1030 : :
1031 : : static int
1032 : 11902 : bdev_scsi_mode_sense(struct spdk_bdev *bdev, int md,
1033 : : uint8_t *cdb, int dbd, int llbaa, int pc,
1034 : : int page, int subpage, uint8_t *data, struct spdk_scsi_task *task)
1035 : : {
1036 : 11902 : uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev);
1037 : 11902 : uint32_t block_size = spdk_bdev_get_data_block_size(bdev);
1038 : : uint8_t *hdr, *bdesc, *pages;
1039 : : int hlen;
1040 : : int blen;
1041 : : int plen, total;
1042 : :
1043 [ + + - + ]: 11902 : assert(md == 6 || md == 10);
1044 : :
1045 [ + + ]: 11902 : if (md == 6) {
1046 : 11894 : hlen = 4;
1047 : 11894 : blen = 8; /* For MODE SENSE 6 only short LBA */
1048 : : } else {
1049 : 8 : hlen = 8;
1050 [ - + ]: 8 : blen = llbaa ? 16 : 8;
1051 : : }
1052 : :
1053 [ - + ]: 11902 : if (dbd) {
1054 : 0 : blen = 0;
1055 : : }
1056 : :
1057 [ + + ]: 11902 : pages = data ? &data[hlen + blen] : NULL;
1058 : 11902 : plen = bdev_scsi_mode_sense_page(bdev, cdb, pc, page,
1059 : : subpage,
1060 : : pages, task);
1061 [ - + ]: 11902 : if (plen < 0) {
1062 : 0 : return -1;
1063 : : }
1064 : :
1065 : 11902 : total = hlen + blen + plen;
1066 [ + + ]: 11902 : if (data == NULL) {
1067 : 5951 : return total;
1068 : : }
1069 : :
1070 : 5951 : hdr = &data[0];
1071 [ + + ]: 5951 : if (hlen == 4) {
1072 : 5947 : hdr[0] = total - 1; /* Mode Data Length */
1073 : 5947 : hdr[1] = 0; /* Medium Type */
1074 : 5947 : hdr[2] = 0; /* Device-Specific Parameter */
1075 : 5947 : hdr[3] = blen; /* Block Descriptor Length */
1076 : : } else {
1077 : 4 : to_be16(&hdr[0], total - 2); /* Mode Data Length */
1078 : 4 : hdr[2] = 0; /* Medium Type */
1079 : 4 : hdr[3] = 0; /* Device-Specific Parameter */
1080 : 4 : hdr[4] = llbaa ? 0x1 : 0; /* Long/short LBA */
1081 : 4 : hdr[5] = 0; /* Reserved */
1082 : 4 : to_be16(&hdr[6], blen); /* Block Descriptor Length */
1083 : : }
1084 : :
1085 : 5951 : bdesc = &data[hlen];
1086 [ - + ]: 5951 : if (blen == 16) {
1087 : : /* Number of Blocks */
1088 : 0 : to_be64(&bdesc[0], num_blocks);
1089 : : /* Reserved */
1090 [ # # ]: 0 : memset(&bdesc[8], 0, 4);
1091 : : /* Block Length */
1092 : 0 : to_be32(&bdesc[12], block_size);
1093 [ + - ]: 5951 : } else if (blen == 8) {
1094 : : /* Number of Blocks */
1095 [ - + ]: 5951 : if (num_blocks > 0xffffffffULL) {
1096 [ # # ]: 0 : memset(&bdesc[0], 0xff, 4);
1097 : : } else {
1098 : 5951 : to_be32(&bdesc[0], num_blocks);
1099 : : }
1100 : :
1101 : : /* Block Length */
1102 : 5951 : to_be32(&bdesc[4], block_size);
1103 : : }
1104 : :
1105 : 5951 : return total;
1106 : : }
1107 : :
1108 : : static void
1109 : 14755013 : bdev_scsi_task_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
1110 : : void *cb_arg)
1111 : : {
1112 : 14755013 : struct spdk_scsi_task *task = cb_arg;
1113 : 1818589 : int sc, sk, asc, ascq;
1114 : :
1115 : 14755013 : spdk_bdev_io_get_scsi_status(bdev_io, &sc, &sk, &asc, &ascq);
1116 : :
1117 : 14755013 : spdk_bdev_free_io(bdev_io);
1118 : :
1119 : 14755013 : spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
1120 : 14755013 : scsi_lun_complete_task(task->lun, task);
1121 : 14755013 : }
1122 : :
1123 : : static void
1124 : 17411307 : bdev_scsi_read_task_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
1125 : : void *cb_arg)
1126 : : {
1127 : 17411307 : struct spdk_scsi_task *task = cb_arg;
1128 : 2328841 : int sc, sk, asc, ascq;
1129 : :
1130 : 17411307 : task->bdev_io = bdev_io;
1131 : :
1132 : 17411307 : spdk_bdev_io_get_scsi_status(bdev_io, &sc, &sk, &asc, &ascq);
1133 : :
1134 : 17411307 : spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
1135 : 17411307 : scsi_lun_complete_task(task->lun, task);
1136 : 17411307 : }
1137 : :
1138 : : static void
1139 : 10 : bdev_scsi_task_complete_reset(struct spdk_bdev_io *bdev_io, bool success,
1140 : : void *cb_arg)
1141 : : {
1142 : 10 : struct spdk_scsi_task *task = cb_arg;
1143 : :
1144 : 10 : spdk_bdev_free_io(bdev_io);
1145 : :
1146 [ + - ]: 10 : if (success) {
1147 : 10 : task->response = SPDK_SCSI_TASK_MGMT_RESP_SUCCESS;
1148 : : }
1149 : :
1150 : 10 : scsi_lun_complete_reset_task(task->lun, task);
1151 : 10 : }
1152 : :
1153 : : static void
1154 : 199047 : bdev_scsi_queue_io(struct spdk_scsi_task *task, spdk_bdev_io_wait_cb cb_fn, void *cb_arg)
1155 : : {
1156 : 199047 : struct spdk_scsi_lun *lun = task->lun;
1157 : 199047 : struct spdk_bdev *bdev = lun->bdev;
1158 : 199047 : struct spdk_io_channel *ch = lun->io_channel;
1159 : : int rc;
1160 : :
1161 : 199047 : task->bdev_io_wait.bdev = bdev;
1162 : 199047 : task->bdev_io_wait.cb_fn = cb_fn;
1163 : 199047 : task->bdev_io_wait.cb_arg = cb_arg;
1164 : :
1165 : 199047 : rc = spdk_bdev_queue_io_wait(bdev, ch, &task->bdev_io_wait);
1166 [ - + ]: 199047 : if (rc != 0) {
1167 : 0 : assert(false);
1168 : : }
1169 : 199047 : }
1170 : :
1171 : : static int
1172 : 1190293 : bdev_scsi_sync(struct spdk_bdev *bdev, struct spdk_bdev_desc *bdev_desc,
1173 : : struct spdk_io_channel *bdev_ch, struct spdk_scsi_task *task,
1174 : : uint64_t lba, uint32_t num_blocks)
1175 : : {
1176 : : uint64_t bdev_num_blocks;
1177 : : int rc;
1178 : :
1179 [ - + ]: 1190293 : if (num_blocks == 0) {
1180 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1181 : : }
1182 : :
1183 : 1190293 : bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
1184 : :
1185 [ + + + - ]: 1190293 : if (lba >= bdev_num_blocks || num_blocks > bdev_num_blocks ||
1186 [ - + ]: 1190292 : lba > (bdev_num_blocks - num_blocks)) {
1187 : 1 : SPDK_ERRLOG("end of media\n");
1188 : 1 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1189 : : SPDK_SCSI_SENSE_NO_SENSE,
1190 : : SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
1191 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1192 : 1 : return SPDK_SCSI_TASK_COMPLETE;
1193 : : }
1194 : :
1195 : 1190292 : rc = spdk_bdev_flush_blocks(bdev_desc, bdev_ch, lba, num_blocks,
1196 : : bdev_scsi_task_complete_cmd, task);
1197 : :
1198 [ + + ]: 1190292 : if (rc) {
1199 [ + - ]: 61387 : if (rc == -ENOMEM) {
1200 : 61387 : bdev_scsi_queue_io(task, bdev_scsi_process_block_resubmit, task);
1201 : 61387 : return SPDK_SCSI_TASK_PENDING;
1202 : : }
1203 : 0 : SPDK_ERRLOG("spdk_bdev_flush_blocks() failed\n");
1204 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1205 : : SPDK_SCSI_SENSE_NO_SENSE,
1206 : : SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
1207 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1208 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1209 : : }
1210 : 1128905 : task->data_transferred = 0;
1211 : 1128905 : return SPDK_SCSI_TASK_PENDING;
1212 : : }
1213 : :
1214 : : static uint64_t
1215 : 31132991 : _bytes_to_blocks(uint32_t block_size, uint64_t offset_bytes, uint64_t *offset_blocks,
1216 : : uint64_t num_bytes, uint64_t *num_blocks)
1217 : : {
1218 : : uint8_t shift_cnt;
1219 : :
1220 : : /* Avoid expensive div operations if possible. These spdk_u32 functions are very cheap. */
1221 [ + - ]: 31132991 : if (spdk_likely(spdk_u32_is_pow2(block_size))) {
1222 : 31132991 : shift_cnt = spdk_u32log2(block_size);
1223 [ - + ]: 31132991 : *offset_blocks = offset_bytes >> shift_cnt;
1224 [ - + ]: 31132991 : *num_blocks = num_bytes >> shift_cnt;
1225 [ - + ]: 31132991 : return (offset_bytes - (*offset_blocks << shift_cnt)) |
1226 [ - + ]: 31132991 : (num_bytes - (*num_blocks << shift_cnt));
1227 : : } else {
1228 [ # # ]: 0 : *offset_blocks = offset_bytes / block_size;
1229 [ # # ]: 0 : *num_blocks = num_bytes / block_size;
1230 [ # # # # ]: 0 : return (offset_bytes % block_size) | (num_bytes % block_size);
1231 : : }
1232 : : }
1233 : :
1234 : : static int
1235 : 31132497 : bdev_scsi_readwrite(struct spdk_bdev *bdev, struct spdk_bdev_desc *bdev_desc,
1236 : : struct spdk_io_channel *bdev_ch, struct spdk_scsi_task *task,
1237 : : uint64_t lba, uint32_t xfer_len, bool is_read, bool is_compare)
1238 : : {
1239 : 4147435 : uint64_t bdev_num_blocks, offset_blocks, num_blocks;
1240 : : uint32_t max_xfer_len, block_size;
1241 : 31132497 : int sk = SPDK_SCSI_SENSE_NO_SENSE, asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
1242 : : int rc;
1243 : :
1244 : 31132497 : task->data_transferred = 0;
1245 : :
1246 [ + + + + : 31132497 : if (spdk_unlikely(task->dxfer_dir != SPDK_SCSI_DIR_NONE &&
- + ]
1247 : : task->dxfer_dir != (is_read ? SPDK_SCSI_DIR_FROM_DEV : SPDK_SCSI_DIR_TO_DEV))) {
1248 : 0 : SPDK_ERRLOG("Incorrect data direction\n");
1249 : 0 : goto check_condition;
1250 : : }
1251 : :
1252 : 31132497 : bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
1253 [ + + + + ]: 31132497 : if (spdk_unlikely(bdev_num_blocks <= lba || bdev_num_blocks - lba < xfer_len)) {
1254 [ - + - + ]: 12 : SPDK_DEBUGLOG(scsi, "end of media\n");
1255 : 12 : sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
1256 : 12 : asc = SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1257 : 12 : goto check_condition;
1258 : : }
1259 : :
1260 [ + + ]: 31132485 : if (spdk_unlikely(xfer_len == 0)) {
1261 : 4 : task->status = SPDK_SCSI_STATUS_GOOD;
1262 : 4 : return SPDK_SCSI_TASK_COMPLETE;
1263 : : }
1264 : :
1265 : 31132481 : block_size = spdk_bdev_get_data_block_size(bdev);
1266 : :
1267 : : /* Transfer Length is limited to the Block Limits VPD page Maximum Transfer Length */
1268 [ - + ]: 31132481 : max_xfer_len = SPDK_WORK_BLOCK_SIZE / block_size;
1269 [ + + ]: 31132481 : if (spdk_unlikely(xfer_len > max_xfer_len)) {
1270 : 4 : SPDK_ERRLOG("xfer_len %" PRIu32 " > maximum transfer length %" PRIu32 "\n",
1271 : : xfer_len, max_xfer_len);
1272 : 4 : sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
1273 : 4 : asc = SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB;
1274 : 4 : goto check_condition;
1275 : : }
1276 : :
1277 [ + + ]: 31132477 : if (!is_read) {
1278 : : /* Additional check for Transfer Length */
1279 [ - + ]: 13669043 : if (xfer_len * block_size > task->transfer_len) {
1280 : 0 : SPDK_ERRLOG("xfer_len %" PRIu32 " * block_size %" PRIu32 " > transfer_len %u\n",
1281 : : xfer_len, block_size, task->transfer_len);
1282 : 0 : goto check_condition;
1283 : : }
1284 : : }
1285 : :
1286 [ - + ]: 31132477 : if (_bytes_to_blocks(block_size, task->offset, &offset_blocks, task->length, &num_blocks) != 0) {
1287 : 0 : SPDK_ERRLOG("task's offset %" PRIu64 " or length %" PRIu32 " is not block multiple\n",
1288 : : task->offset, task->length);
1289 : 0 : goto check_condition;
1290 : : }
1291 : :
1292 : 31132477 : offset_blocks += lba;
1293 : :
1294 [ - + - + : 31132477 : SPDK_DEBUGLOG(scsi,
- - ]
1295 : : "%s: lba=%"PRIu64", len=%"PRIu64"\n",
1296 : : is_read ? "Read" : "Write", offset_blocks, num_blocks);
1297 : :
1298 [ + + ]: 31132477 : if (is_read) {
1299 : 17463434 : rc = spdk_bdev_readv_blocks(bdev_desc, bdev_ch, task->iovs, task->iovcnt,
1300 : : offset_blocks, num_blocks,
1301 : : bdev_scsi_read_task_complete_cmd, task);
1302 [ - + ]: 13669043 : } else if (is_compare) {
1303 : : struct iovec *iov;
1304 : : size_t len;
1305 : :
1306 [ # # # # ]: 0 : if (task->iovcnt != 1 || task->iovs[0].iov_len != (block_size * 2)) {
1307 [ # # ]: 0 : if (task->iovcnt != 1) {
1308 : 0 : SPDK_ERRLOG("task's iovcnt %" PRIu32 " is not 1.\n", task->iovcnt);
1309 : : } else {
1310 : 0 : SPDK_ERRLOG("task's iov len %" PRIu64 " is not 2 * BLOCK_SIZE.\n",
1311 : : task->iovs[0].iov_len);
1312 : : }
1313 : 0 : sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
1314 : 0 : asc = SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB;
1315 : 0 : goto check_condition;
1316 : : }
1317 : :
1318 : 0 : iov = &task->iovs[0];
1319 : 0 : len = iov->iov_len >> 1;
1320 : 0 : task->caw_iov.iov_len = len;
1321 : 0 : task->caw_iov.iov_base = (uint8_t *)(iov->iov_base) + len;
1322 : 0 : iov->iov_len = len;
1323 : :
1324 : 0 : rc = spdk_bdev_comparev_and_writev_blocks(bdev_desc, bdev_ch, iov, 1,
1325 : : &task->caw_iov, 1, offset_blocks, 1, bdev_scsi_task_complete_cmd, task);
1326 : : } else {
1327 : 13669043 : rc = spdk_bdev_writev_blocks(bdev_desc, bdev_ch, task->iovs, task->iovcnt,
1328 : : offset_blocks, num_blocks,
1329 : : bdev_scsi_task_complete_cmd, task);
1330 : : }
1331 : :
1332 [ + + ]: 31132477 : if (rc) {
1333 [ + - ]: 95074 : if (rc == -ENOMEM) {
1334 : 95074 : bdev_scsi_queue_io(task, bdev_scsi_process_block_resubmit, task);
1335 : 95074 : return SPDK_SCSI_TASK_PENDING;
1336 : : }
1337 [ # # # # ]: 0 : SPDK_ERRLOG("spdk_bdev_%s_blocks() failed: %d\n",
1338 : : is_read ? "readv" : (is_compare ? "comparev_and_writev" : "writev"), rc);
1339 : 0 : goto check_condition;
1340 : : }
1341 : :
1342 : 31037403 : task->data_transferred = task->length;
1343 : 31037403 : return SPDK_SCSI_TASK_PENDING;
1344 : :
1345 : 16 : check_condition:
1346 : 16 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, sk, asc,
1347 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1348 : 16 : return SPDK_SCSI_TASK_COMPLETE;
1349 : : }
1350 : :
1351 : : struct spdk_bdev_scsi_split_ctx {
1352 : : struct spdk_scsi_task *task;
1353 : : union {
1354 : : struct spdk_scsi_unmap_bdesc desc[DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT];
1355 : : uint64_t start_offset_blocks; /* used by writesame */
1356 : : };
1357 : : uint16_t remaining_count;
1358 : : uint16_t current_count;
1359 : : uint16_t outstanding_count;
1360 : : int (*fn)(struct spdk_bdev_scsi_split_ctx *ctx);
1361 : : };
1362 : :
1363 : : static int bdev_scsi_split(struct spdk_bdev_scsi_split_ctx *ctx);
1364 : :
1365 : : static void
1366 : 42586 : bdev_scsi_split_resubmit(void *arg)
1367 : : {
1368 : 42586 : struct spdk_bdev_scsi_split_ctx *ctx = arg;
1369 : :
1370 : 42586 : bdev_scsi_split(ctx);
1371 : 42586 : }
1372 : :
1373 : : static int
1374 : 780071 : bdev_scsi_split(struct spdk_bdev_scsi_split_ctx *ctx)
1375 : : {
1376 : 780071 : struct spdk_scsi_task *task = ctx->task;
1377 : 780071 : uint8_t opcode = task->cdb[0];
1378 : : int rc;
1379 : :
1380 [ + + ]: 2251915 : while (ctx->remaining_count != 0) {
1381 : 1514468 : rc = ctx->fn(ctx);
1382 [ + + ]: 1514468 : if (rc == 0) {
1383 : 1471844 : ctx->current_count++;
1384 : 1471844 : ctx->remaining_count--;
1385 : : } else {
1386 : 42624 : ctx->outstanding_count--;
1387 [ + - ]: 42624 : if (rc == -ENOMEM) {
1388 [ + + ]: 42624 : if (ctx->outstanding_count == 0) {
1389 : : /*
1390 : : * If there are outstanding child I/Os, the last
1391 : : * completion will call this function again to try
1392 : : * the next split. Hence, queue the parent task only
1393 : : * if there is no outstanding child I/O.
1394 : : */
1395 : 42586 : bdev_scsi_queue_io(task, bdev_scsi_split_resubmit, ctx);
1396 : : }
1397 : 42624 : return SPDK_SCSI_TASK_PENDING;
1398 : : } else {
1399 : 0 : SPDK_ERRLOG("SCSI %s failed\n", spdk_scsi_sbc_opcode_string(opcode, 0));
1400 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1401 : : SPDK_SCSI_SENSE_NO_SENSE,
1402 : : SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
1403 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1404 : : /* If any child I/O failed, stop further splitting process. */
1405 : 0 : ctx->current_count += ctx->remaining_count;
1406 : 0 : ctx->remaining_count = 0;
1407 : : /* We can't complete here - we may have to wait for previously
1408 : : * submitted child I/Os to complete */
1409 : 0 : break;
1410 : : }
1411 : : }
1412 : : }
1413 : :
1414 [ - + ]: 737447 : if (ctx->outstanding_count == 0) {
1415 : 0 : free(ctx);
1416 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1417 : : }
1418 : :
1419 : 737447 : return SPDK_SCSI_TASK_PENDING;
1420 : : }
1421 : :
1422 : : static void
1423 : 1471844 : bdev_scsi_task_complete_split_cmd(struct spdk_bdev_io *bdev_io, bool success,
1424 : : void *cb_arg)
1425 : : {
1426 : 1471844 : struct spdk_bdev_scsi_split_ctx *ctx = cb_arg;
1427 : 1471844 : struct spdk_scsi_task *task = ctx->task;
1428 : :
1429 : 1471844 : spdk_bdev_free_io(bdev_io);
1430 : :
1431 [ + + ]: 1471844 : if (!success) {
1432 : 4000 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1433 : : SPDK_SCSI_SENSE_NO_SENSE,
1434 : : SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
1435 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1436 : : /* If any child I/O failed, stop further splitting process. */
1437 : 4000 : ctx->current_count += ctx->remaining_count;
1438 : 4000 : ctx->remaining_count = 0;
1439 : : }
1440 : :
1441 : 1471844 : ctx->outstanding_count--;
1442 [ + + ]: 1471844 : if (ctx->outstanding_count != 0) {
1443 : : /* Any child I/O is still outstanding. */
1444 : 734359 : return;
1445 : : }
1446 : :
1447 [ + + ]: 737485 : if (ctx->remaining_count == 0) {
1448 : : /* SCSI task finishes when all descriptors are consumed. */
1449 : 737447 : scsi_lun_complete_task(task->lun, task);
1450 : 737447 : free(ctx);
1451 : 737447 : return;
1452 : : }
1453 : :
1454 : : /* Continue with splitting process. */
1455 : 38 : bdev_scsi_split(ctx);
1456 : : }
1457 : :
1458 : : static int
1459 : 736933 : __copy_desc(struct spdk_bdev_scsi_split_ctx *ctx, uint8_t *data, size_t data_len)
1460 : : {
1461 : : uint16_t desc_data_len;
1462 : : uint16_t desc_count;
1463 : :
1464 [ - + ]: 736933 : if (!data) {
1465 : 0 : return -EINVAL;
1466 : : }
1467 : :
1468 [ - + ]: 736933 : if (data_len < 8) {
1469 : : /* We can't even get the reported length, so fail. */
1470 : 0 : return -EINVAL;
1471 : : }
1472 : :
1473 : 736933 : desc_data_len = from_be16(&data[2]);
1474 : 736933 : desc_count = desc_data_len / 16;
1475 : :
1476 [ - + ]: 736933 : if (desc_data_len > (data_len - 8)) {
1477 : 0 : SPDK_ERRLOG("Error - desc_data_len (%u) > data_len (%zu) - 8\n",
1478 : : desc_data_len, data_len);
1479 : 0 : return -EINVAL;
1480 : : }
1481 : :
1482 [ - + ]: 736933 : if (desc_count > DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT) {
1483 : 0 : SPDK_ERRLOG("desc_count (%u) greater than max allowed (%u)\n",
1484 : : desc_count, DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT);
1485 : 0 : return -EINVAL;
1486 : : }
1487 : :
1488 [ - + - + ]: 736933 : memcpy(ctx->desc, &data[8], desc_data_len);
1489 : 736933 : return desc_count;
1490 : : }
1491 : :
1492 : : static int
1493 : 779527 : _bdev_scsi_unmap(struct spdk_bdev_scsi_split_ctx *ctx)
1494 : : {
1495 : 779527 : struct spdk_scsi_task *task = ctx->task;
1496 : 779527 : struct spdk_scsi_lun *lun = task->lun;
1497 : : struct spdk_scsi_unmap_bdesc *desc;
1498 : : uint64_t offset_blocks;
1499 : : uint64_t num_blocks;
1500 : :
1501 : 779527 : desc = &ctx->desc[ctx->current_count];
1502 : :
1503 : 779527 : offset_blocks = from_be64(&desc->lba);
1504 : 779527 : num_blocks = from_be32(&desc->block_count);
1505 : :
1506 [ - + ]: 779527 : if (num_blocks == 0) {
1507 : 0 : return 0;
1508 : : }
1509 : :
1510 : 779527 : ctx->outstanding_count++;
1511 : 779527 : return spdk_bdev_unmap_blocks(lun->bdev_desc,
1512 : : lun->io_channel,
1513 : : offset_blocks,
1514 : : num_blocks,
1515 : : bdev_scsi_task_complete_split_cmd,
1516 : : ctx);
1517 : : }
1518 : :
1519 : : static int
1520 : 736933 : bdev_scsi_unmap(struct spdk_bdev *bdev, struct spdk_scsi_task *task)
1521 : : {
1522 : : struct spdk_bdev_scsi_split_ctx *ctx;
1523 : : uint8_t *data;
1524 : 736933 : int desc_count = -1;
1525 : 42 : int data_len;
1526 : :
1527 [ - + ]: 736933 : assert(task->status == SPDK_SCSI_STATUS_GOOD);
1528 : :
1529 : 736933 : ctx = calloc(1, sizeof(*ctx));
1530 [ - + ]: 736933 : if (!ctx) {
1531 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1532 : : SPDK_SCSI_SENSE_NO_SENSE,
1533 : : SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
1534 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1535 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1536 : : }
1537 : :
1538 : 736933 : ctx->task = task;
1539 : 736933 : ctx->current_count = 0;
1540 : 736933 : ctx->outstanding_count = 0;
1541 : 736933 : ctx->fn = _bdev_scsi_unmap;
1542 : :
1543 [ + - ]: 736933 : if (task->iovcnt == 1) {
1544 : 736933 : data = (uint8_t *)task->iovs[0].iov_base;
1545 : 736933 : data_len = task->iovs[0].iov_len;
1546 : 736933 : desc_count = __copy_desc(ctx, data, data_len);
1547 : : } else {
1548 : 0 : data = spdk_scsi_task_gather_data(task, &data_len);
1549 [ # # ]: 0 : if (data) {
1550 : 0 : desc_count = __copy_desc(ctx, data, data_len);
1551 : 0 : free(data);
1552 : : }
1553 : : }
1554 : :
1555 [ + - ]: 736933 : if (desc_count > 0) {
1556 : 736933 : ctx->remaining_count = desc_count;
1557 : 736933 : return bdev_scsi_split(ctx);
1558 : : }
1559 : :
1560 [ # # ]: 0 : if (desc_count < 0) {
1561 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1562 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
1563 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
1564 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1565 : : }
1566 : :
1567 : 0 : free(ctx);
1568 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1569 : : }
1570 : :
1571 : : static int
1572 : 734941 : _bdev_scsi_write_same(struct spdk_bdev_scsi_split_ctx *ctx)
1573 : : {
1574 : 734941 : struct spdk_scsi_task *task = ctx->task;
1575 : 734941 : struct spdk_scsi_lun *lun = task->lun;
1576 : : uint64_t offset_blocks;
1577 : :
1578 : 734941 : ctx->outstanding_count++;
1579 : 734941 : offset_blocks = ctx->start_offset_blocks + ctx->current_count;
1580 : 734941 : return spdk_bdev_writev_blocks(lun->bdev_desc, lun->io_channel, task->iovs, task->iovcnt,
1581 : : offset_blocks, 1, bdev_scsi_task_complete_split_cmd, ctx);
1582 : : }
1583 : :
1584 : : static int
1585 : 514 : bdev_scsi_write_same(struct spdk_bdev *bdev, struct spdk_bdev_desc *bdev_desc,
1586 : : struct spdk_io_channel *bdev_ch, struct spdk_scsi_task *task,
1587 : : uint64_t lba, uint32_t xfer_len, uint8_t flags)
1588 : : {
1589 : : struct spdk_bdev_scsi_split_ctx *ctx;
1590 : 95 : uint64_t bdev_num_blocks, offset_blocks, num_blocks;
1591 : : uint32_t max_xfer_len, block_size;
1592 : 514 : int sk = SPDK_SCSI_SENSE_NO_SENSE, asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
1593 : :
1594 : 514 : task->data_transferred = 0;
1595 : :
1596 [ - + ]: 514 : if (spdk_unlikely(task->dxfer_dir != SPDK_SCSI_DIR_TO_DEV)) {
1597 : 0 : SPDK_ERRLOG("Incorrect data direction\n");
1598 : 0 : goto check_condition;
1599 : : }
1600 : :
1601 : 514 : block_size = spdk_bdev_get_data_block_size(bdev);
1602 [ - + ]: 514 : if (spdk_unlikely(task->transfer_len != block_size)) {
1603 : 0 : SPDK_ERRLOG("Incorrect data length(%d), a single logical block(%d) is required\n",
1604 : : task->transfer_len, block_size);
1605 : 0 : goto check_condition;
1606 : : }
1607 : :
1608 [ - + ]: 514 : if (spdk_unlikely(xfer_len == 0)) {
1609 : 0 : task->status = SPDK_SCSI_STATUS_GOOD;
1610 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1611 : : }
1612 : :
1613 : 514 : bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
1614 [ + - - + ]: 514 : if (spdk_unlikely(bdev_num_blocks <= lba || bdev_num_blocks - lba < xfer_len)) {
1615 [ # # # # ]: 0 : SPDK_DEBUGLOG(scsi, "end of media\n");
1616 : 0 : sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
1617 : 0 : asc = SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1618 : 0 : goto check_condition;
1619 : : }
1620 : :
1621 : : /* see MAXIMUM WRITE SAME LENGTH of SPDK_SPC_VPD_BLOCK_LIMITS */
1622 [ - + ]: 514 : max_xfer_len = SPDK_WORK_BLOCK_SIZE / block_size;
1623 [ - + ]: 514 : if (spdk_unlikely(xfer_len > max_xfer_len)) {
1624 : 0 : SPDK_ERRLOG("xfer_len %"PRIu32 " > maximum transfer length %" PRIu32 "\n",
1625 : : xfer_len, max_xfer_len);
1626 : 0 : sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
1627 : 0 : asc = SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB;
1628 : 0 : goto check_condition;
1629 : : }
1630 : :
1631 [ - + ]: 514 : if (_bytes_to_blocks(block_size, task->offset, &offset_blocks, task->length * xfer_len,
1632 : : &num_blocks) != 0) {
1633 : 0 : SPDK_ERRLOG("task's offset %" PRIu64 " or length %" PRIu32 " is not block multiple\n",
1634 : : task->offset, task->length);
1635 : 0 : goto check_condition;
1636 : : }
1637 : :
1638 : 514 : offset_blocks += lba;
1639 [ - + - + ]: 514 : SPDK_DEBUGLOG(scsi, "Writesame: lba=%"PRIu64", len=%"PRIu64"\n",
1640 : : offset_blocks, num_blocks);
1641 : :
1642 : 514 : ctx = calloc(1, sizeof(*ctx));
1643 [ - + ]: 514 : if (!ctx) {
1644 : 0 : SPDK_ERRLOG("No enough memory on SCSI WRITE SAME\n");
1645 : 0 : goto check_condition;
1646 : : }
1647 : :
1648 : 514 : ctx->task = task;
1649 : 514 : ctx->start_offset_blocks = offset_blocks;
1650 : 514 : ctx->current_count = 0;
1651 : 514 : ctx->outstanding_count = 0;
1652 : 514 : ctx->remaining_count = xfer_len;
1653 : 514 : ctx->fn = _bdev_scsi_write_same;
1654 : :
1655 : 514 : task->data_transferred = task->length;
1656 : :
1657 : 514 : return bdev_scsi_split(ctx);
1658 : :
1659 : 0 : check_condition:
1660 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1661 : : sk, asc, SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1662 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1663 : : }
1664 : :
1665 : : static int
1666 : 33084324 : bdev_scsi_process_block(struct spdk_scsi_task *task)
1667 : : {
1668 : 33084324 : struct spdk_scsi_lun *lun = task->lun;
1669 : 33084324 : struct spdk_bdev *bdev = lun->bdev;
1670 : : uint64_t lba;
1671 : : uint32_t xfer_len;
1672 : 33084324 : uint32_t len = 0;
1673 : 33084324 : uint8_t *cdb = task->cdb;
1674 : :
1675 : : /* XXX: We need to support FUA bit for writes! */
1676 [ - + - + : 33084324 : switch (cdb[0]) {
- + + + +
+ - + ]
1677 : 0 : case SPDK_SBC_READ_6:
1678 : : case SPDK_SBC_WRITE_6:
1679 : 0 : lba = (uint64_t)cdb[1] << 16;
1680 : 0 : lba |= (uint64_t)cdb[2] << 8;
1681 : 0 : lba |= (uint64_t)cdb[3];
1682 : 0 : xfer_len = cdb[4];
1683 [ # # ]: 0 : if (xfer_len == 0) {
1684 : 0 : xfer_len = 256;
1685 : : }
1686 : 0 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1687 : : task, lba, xfer_len,
1688 : 0 : cdb[0] == SPDK_SBC_READ_6, false);
1689 : :
1690 : 29884931 : case SPDK_SBC_READ_10:
1691 : : case SPDK_SBC_WRITE_10:
1692 : 29884931 : lba = from_be32(&cdb[2]);
1693 : 29884931 : xfer_len = from_be16(&cdb[7]);
1694 : 29884931 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1695 : : task, lba, xfer_len,
1696 : 29884931 : cdb[0] == SPDK_SBC_READ_10, false);
1697 : :
1698 : 0 : case SPDK_SBC_READ_12:
1699 : : case SPDK_SBC_WRITE_12:
1700 : 0 : lba = from_be32(&cdb[2]);
1701 : 0 : xfer_len = from_be32(&cdb[6]);
1702 : 0 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1703 : : task, lba, xfer_len,
1704 : 0 : cdb[0] == SPDK_SBC_READ_12, false);
1705 : 1247566 : case SPDK_SBC_READ_16:
1706 : : case SPDK_SBC_WRITE_16:
1707 : 1247566 : lba = from_be64(&cdb[2]);
1708 : 1247566 : xfer_len = from_be32(&cdb[10]);
1709 : 1247566 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1710 : : task, lba, xfer_len,
1711 : 1247566 : cdb[0] == SPDK_SBC_READ_16, false);
1712 : :
1713 : 0 : case SPDK_SBC_COMPARE_AND_WRITE: {
1714 : 0 : uint32_t num_blocks = cdb[13];
1715 : 0 : uint8_t wrprotect = (cdb[1] >> 5) & 0x07;
1716 : 0 : bool dpo = cdb[1] & 0x10;
1717 : 0 : bool fua = cdb[1] & 0x08;
1718 : :
1719 : 0 : lba = from_be64(&cdb[2]);
1720 : :
1721 [ # # # # : 0 : if (dpo || fua || wrprotect) {
# # ]
1722 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1723 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
1724 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
1725 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1726 : 0 : SPDK_ERRLOG("Invalid Task\n");
1727 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1728 : : }
1729 : :
1730 [ # # ]: 0 : if (num_blocks != 1) {
1731 : 0 : SPDK_ERRLOG("Invalid CAW block count, request block count is %u, limit is : 1\n",
1732 : : num_blocks);
1733 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1734 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
1735 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
1736 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1737 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1738 : : }
1739 : :
1740 : 0 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1741 : : task, lba, num_blocks, false, true);
1742 : : }
1743 : :
1744 : 185 : case SPDK_SBC_READ_CAPACITY_10: {
1745 : 185 : uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev);
1746 : 16 : uint8_t buffer[8];
1747 : :
1748 [ - + ]: 185 : if (num_blocks - 1 > 0xffffffffULL) {
1749 [ # # ]: 0 : memset(buffer, 0xff, 4);
1750 : : } else {
1751 : 185 : to_be32(buffer, num_blocks - 1);
1752 : : }
1753 : 185 : to_be32(&buffer[4], spdk_bdev_get_data_block_size(bdev));
1754 : :
1755 : 185 : len = spdk_min(task->length, sizeof(buffer));
1756 [ - + ]: 185 : if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) {
1757 : 0 : break;
1758 : : }
1759 : :
1760 : 185 : task->data_transferred = len;
1761 : 185 : task->status = SPDK_SCSI_STATUS_GOOD;
1762 : 185 : break;
1763 : : }
1764 : :
1765 : 1991 : case SPDK_SPC_SERVICE_ACTION_IN_16:
1766 [ + - ]: 1991 : switch (cdb[1] & 0x1f) { /* SERVICE ACTION */
1767 : 1991 : case SPDK_SBC_SAI_READ_CAPACITY_16: {
1768 : 1991 : uint8_t buffer[32] = {0};
1769 : : uint32_t lbppb, lbppbe;
1770 : :
1771 : 1991 : to_be64(&buffer[0], spdk_bdev_get_num_blocks(bdev) - 1);
1772 : 1991 : to_be32(&buffer[8], spdk_bdev_get_data_block_size(bdev));
1773 [ - + ]: 1991 : lbppb = spdk_bdev_get_physical_block_size(bdev) / spdk_bdev_get_data_block_size(bdev);
1774 : 1991 : lbppbe = spdk_u32log2(lbppb);
1775 [ - + ]: 1991 : if (lbppbe > 0xf) {
1776 : 0 : SPDK_ERRLOG("lbppbe(0x%x) > 0xf\n", lbppbe);
1777 : : } else {
1778 : 1991 : buffer[13] = lbppbe;
1779 : : }
1780 : : /*
1781 : : * Set the TPE bit to 1 to indicate thin provisioning.
1782 : : * The position of TPE bit is the 7th bit in 14th byte
1783 : : * in READ CAPACITY (16) parameter data.
1784 : : */
1785 [ + + ]: 1991 : if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
1786 : 1981 : buffer[14] |= 1 << 7;
1787 : : }
1788 : :
1789 [ - + ]: 1991 : len = spdk_min(from_be32(&cdb[10]), sizeof(buffer));
1790 [ - + ]: 1991 : if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) {
1791 : 0 : break;
1792 : : }
1793 : :
1794 : 1991 : task->data_transferred = len;
1795 : 1991 : task->status = SPDK_SCSI_STATUS_GOOD;
1796 : 1991 : break;
1797 : : }
1798 : :
1799 : 0 : default:
1800 : 0 : return SPDK_SCSI_TASK_UNKNOWN;
1801 : : }
1802 : 1855 : break;
1803 : :
1804 : 1190293 : case SPDK_SBC_SYNCHRONIZE_CACHE_10:
1805 : : case SPDK_SBC_SYNCHRONIZE_CACHE_16:
1806 [ + + ]: 1190293 : if (cdb[0] == SPDK_SBC_SYNCHRONIZE_CACHE_10) {
1807 : 673604 : lba = from_be32(&cdb[2]);
1808 : 673604 : len = from_be16(&cdb[7]);
1809 : : } else {
1810 : 516689 : lba = from_be64(&cdb[2]);
1811 : 516689 : len = from_be32(&cdb[10]);
1812 : : }
1813 : :
1814 [ + + ]: 1190293 : if (len == 0) {
1815 : 673603 : len = spdk_bdev_get_num_blocks(bdev) - lba;
1816 : : }
1817 : :
1818 : 1190293 : return bdev_scsi_sync(bdev, lun->bdev_desc, lun->io_channel, task, lba, len);
1819 : : break;
1820 : :
1821 : 736933 : case SPDK_SBC_UNMAP:
1822 : 736933 : return bdev_scsi_unmap(bdev, task);
1823 : :
1824 : 514 : case SPDK_SBC_WRITE_SAME_10:
1825 : 514 : lba = from_be32(&cdb[2]);
1826 : 514 : xfer_len = from_be16(&cdb[7]);
1827 : 514 : return bdev_scsi_write_same(bdev, lun->bdev_desc, lun->io_channel,
1828 : 514 : task, lba, xfer_len, cdb[1]);
1829 : :
1830 : 0 : case SPDK_SBC_WRITE_SAME_16:
1831 : 0 : lba = from_be64(&cdb[2]);
1832 : 0 : xfer_len = from_be32(&cdb[10]);
1833 : 0 : return bdev_scsi_write_same(bdev, lun->bdev_desc, lun->io_channel,
1834 : 0 : task, lba, xfer_len, cdb[1]);
1835 : :
1836 : :
1837 : 21911 : default:
1838 : 21911 : return SPDK_SCSI_TASK_UNKNOWN;
1839 : : }
1840 : :
1841 : 2176 : return SPDK_SCSI_TASK_COMPLETE;
1842 : : }
1843 : :
1844 : : static void
1845 : 156461 : bdev_scsi_process_block_resubmit(void *arg)
1846 : : {
1847 : 156461 : struct spdk_scsi_task *task = arg;
1848 : :
1849 : 156461 : bdev_scsi_process_block(task);
1850 : 156461 : }
1851 : :
1852 : : static int
1853 : 187 : bdev_scsi_check_len(struct spdk_scsi_task *task, int len, int min_len)
1854 : : {
1855 [ + - ]: 187 : if (len >= min_len) {
1856 : 187 : return 0;
1857 : : }
1858 : :
1859 : : /* INVALID FIELD IN CDB */
1860 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1861 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
1862 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
1863 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1864 : 0 : return -1;
1865 : : }
1866 : :
1867 : : static int
1868 : 21911 : bdev_scsi_process_primary(struct spdk_scsi_task *task)
1869 : : {
1870 : 21911 : struct spdk_scsi_lun *lun = task->lun;
1871 : 21911 : struct spdk_bdev *bdev = lun->bdev;
1872 : 21911 : int alloc_len = -1;
1873 : 21911 : int data_len = -1;
1874 : 21911 : uint8_t *cdb = task->cdb;
1875 : 21911 : uint8_t *data = NULL;
1876 : 21911 : int rc = 0;
1877 : 21911 : int pllen, md = 0;
1878 : : int llba;
1879 : : int dbd, pc, page, subpage;
1880 : 21911 : int cmd_parsed = 0;
1881 : :
1882 [ + + + + : 21911 : switch (cdb[0]) {
+ - - - +
- - - - -
+ ]
1883 : 13240 : case SPDK_SPC_INQUIRY:
1884 : 13240 : alloc_len = from_be16(&cdb[3]);
1885 : 13240 : data_len = spdk_max(4096, alloc_len);
1886 : 13240 : data = calloc(1, data_len);
1887 [ - + ]: 13240 : assert(data != NULL);
1888 : 13240 : rc = bdev_scsi_inquiry(bdev, task, cdb, data, data_len);
1889 : 13240 : data_len = spdk_min(rc, data_len);
1890 [ + + ]: 13240 : if (rc < 0) {
1891 : 1644 : break;
1892 : : }
1893 : :
1894 [ - + - + ]: 11596 : SPDK_LOGDUMP(scsi, "INQUIRY", data, data_len);
1895 : 11596 : break;
1896 : :
1897 : 179 : case SPDK_SPC_REPORT_LUNS: {
1898 : : int sel;
1899 : :
1900 : 179 : sel = cdb[2];
1901 [ - + - + ]: 179 : SPDK_DEBUGLOG(scsi, "sel=%x\n", sel);
1902 : :
1903 : 179 : alloc_len = from_be32(&cdb[6]);
1904 : 179 : rc = bdev_scsi_check_len(task, alloc_len, 16);
1905 [ - + ]: 179 : if (rc < 0) {
1906 : 0 : break;
1907 : : }
1908 : :
1909 : 179 : data_len = spdk_max(4096, alloc_len);
1910 : 179 : data = calloc(1, data_len);
1911 [ - + ]: 179 : assert(data != NULL);
1912 : 179 : rc = bdev_scsi_report_luns(task->lun, sel, data, data_len);
1913 : 179 : data_len = rc;
1914 [ - + ]: 179 : if (rc < 0) {
1915 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1916 : : SPDK_SCSI_SENSE_NO_SENSE,
1917 : : SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
1918 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1919 : 0 : break;
1920 : : }
1921 : :
1922 [ - + - + ]: 179 : SPDK_LOGDUMP(scsi, "REPORT LUNS", data, data_len);
1923 : 179 : break;
1924 : : }
1925 : :
1926 : 8 : case SPDK_SPC_MODE_SELECT_6:
1927 : : case SPDK_SPC_MODE_SELECT_10:
1928 [ + - ]: 8 : if (cdb[0] == SPDK_SPC_MODE_SELECT_6) {
1929 : : /* MODE_SELECT(6) must have at least a 4 byte header. */
1930 : 8 : md = 4;
1931 : 8 : pllen = cdb[4];
1932 : : } else {
1933 : : /* MODE_SELECT(10) must have at least an 8 byte header. */
1934 : 0 : md = 8;
1935 : 0 : pllen = from_be16(&cdb[7]);
1936 : : }
1937 : :
1938 [ + + ]: 8 : if (pllen == 0) {
1939 : 4 : break;
1940 : : }
1941 : :
1942 : 4 : rc = bdev_scsi_check_len(task, pllen, md);
1943 [ - + ]: 4 : if (rc < 0) {
1944 : 0 : break;
1945 : : }
1946 : :
1947 : 4 : data = spdk_scsi_task_gather_data(task, &rc);
1948 [ - + ]: 4 : if (rc < 0) {
1949 : 0 : break;
1950 : : }
1951 : 4 : data_len = rc;
1952 : :
1953 : 4 : rc = bdev_scsi_check_len(task, data_len, spdk_max(pllen, md));
1954 [ - + ]: 4 : if (rc < 0) {
1955 : 0 : break;
1956 : : }
1957 : :
1958 : 4 : rc = pllen;
1959 : 4 : data_len = 0;
1960 : 4 : break;
1961 : :
1962 : 5947 : case SPDK_SPC_MODE_SENSE_6:
1963 : 5947 : alloc_len = cdb[4];
1964 : 5947 : md = 6;
1965 : : /* FALLTHROUGH */
1966 : 5951 : case SPDK_SPC_MODE_SENSE_10:
1967 : 5951 : llba = 0;
1968 : :
1969 [ + + ]: 5951 : if (md == 0) {
1970 : 4 : alloc_len = from_be16(&cdb[7]);
1971 : 4 : llba = !!(cdb[1] & 0x10);
1972 : 4 : md = 10;
1973 : : }
1974 : :
1975 : 5951 : dbd = !!(cdb[1] & 0x8);
1976 : 5951 : pc = (cdb[2] & 0xc0) >> 6;
1977 : 5951 : page = cdb[2] & 0x3f;
1978 : 5951 : subpage = cdb[3];
1979 : :
1980 : : /* First call with no buffer to discover needed buffer size */
1981 : 5951 : rc = bdev_scsi_mode_sense(bdev, md,
1982 : : cdb, dbd, llba, pc,
1983 : : page, subpage,
1984 : : NULL, task);
1985 [ - + ]: 5951 : if (rc < 0) {
1986 : 0 : break;
1987 : : }
1988 : :
1989 : 5951 : data_len = rc;
1990 : 5951 : data = calloc(1, data_len);
1991 [ - + ]: 5951 : assert(data != NULL);
1992 : :
1993 : : /* First call with no buffer to discover needed buffer size */
1994 : 5951 : rc = bdev_scsi_mode_sense(bdev, md,
1995 : : cdb, dbd, llba, pc,
1996 : : page, subpage,
1997 : : data, task);
1998 [ - + ]: 5951 : if (rc < 0) {
1999 : : /* INVALID FIELD IN CDB */
2000 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
2001 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
2002 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
2003 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
2004 : 0 : break;
2005 : : }
2006 : 5951 : break;
2007 : :
2008 : 0 : case SPDK_SPC_REQUEST_SENSE: {
2009 : : int desc;
2010 : : int sk, asc, ascq;
2011 : :
2012 : 0 : desc = cdb[1] & 0x1;
2013 [ # # ]: 0 : if (desc != 0) {
2014 : : /* INVALID FIELD IN CDB */
2015 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
2016 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
2017 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
2018 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
2019 : 0 : break;
2020 : : }
2021 : :
2022 : 0 : alloc_len = cdb[4];
2023 : :
2024 : : /* NO ADDITIONAL SENSE INFORMATION */
2025 : 0 : sk = SPDK_SCSI_SENSE_NO_SENSE;
2026 : 0 : asc = 0x00;
2027 : 0 : ascq = 0x00;
2028 : :
2029 : 0 : spdk_scsi_task_build_sense_data(task, sk, asc, ascq);
2030 : :
2031 : 0 : data_len = task->sense_data_len;
2032 : 0 : data = calloc(1, data_len);
2033 [ # # ]: 0 : assert(data != NULL);
2034 [ # # # # ]: 0 : memcpy(data, task->sense_data, data_len);
2035 : 0 : break;
2036 : : }
2037 : :
2038 : 0 : case SPDK_SPC_LOG_SELECT:
2039 [ # # # # ]: 0 : SPDK_DEBUGLOG(scsi, "LOG_SELECT\n");
2040 : 0 : cmd_parsed = 1;
2041 : : /* FALLTHROUGH */
2042 : 0 : case SPDK_SPC_LOG_SENSE:
2043 [ # # ]: 0 : if (!cmd_parsed) {
2044 [ # # # # ]: 0 : SPDK_DEBUGLOG(scsi, "LOG_SENSE\n");
2045 : : }
2046 : :
2047 : : /* INVALID COMMAND OPERATION CODE */
2048 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
2049 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
2050 : : SPDK_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
2051 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
2052 : 0 : rc = -1;
2053 : 0 : break;
2054 : :
2055 : 2188 : case SPDK_SPC_TEST_UNIT_READY:
2056 [ - + - + ]: 2188 : SPDK_DEBUGLOG(scsi, "TEST_UNIT_READY\n");
2057 : 2188 : cmd_parsed = 1;
2058 : : /* FALLTHROUGH */
2059 : 2188 : case SPDK_SBC_START_STOP_UNIT:
2060 [ - + ]: 2188 : if (!cmd_parsed) {
2061 [ # # # # ]: 0 : SPDK_DEBUGLOG(scsi, "START_STOP_UNIT\n");
2062 : : }
2063 : :
2064 : 2188 : rc = 0;
2065 : 2188 : break;
2066 : :
2067 : 0 : case SPDK_SPC_PERSISTENT_RESERVE_OUT:
2068 : 0 : pllen = from_be32(&cdb[5]);
2069 : 0 : rc = bdev_scsi_check_len(task, pllen, 24);
2070 [ # # ]: 0 : if (rc < 0) {
2071 : 0 : break;
2072 : : }
2073 : :
2074 : 0 : data = spdk_scsi_task_gather_data(task, &rc);
2075 [ # # ]: 0 : if (rc < 0) {
2076 : 0 : break;
2077 : : }
2078 : 0 : data_len = rc;
2079 [ # # ]: 0 : if (data_len < 24) {
2080 : 0 : rc = -1;
2081 : 0 : break;
2082 : : }
2083 : :
2084 : 0 : rc = scsi_pr_out(task, cdb, data, data_len);
2085 [ # # ]: 0 : if (rc < 0) {
2086 : 0 : break;
2087 : : }
2088 : 0 : rc = pllen;
2089 : 0 : data_len = 0;
2090 : 0 : break;
2091 : :
2092 : 0 : case SPDK_SPC_PERSISTENT_RESERVE_IN:
2093 : 0 : alloc_len = from_be16(&cdb[7]);
2094 : 0 : data_len = alloc_len;
2095 : 0 : data = calloc(1, data_len);
2096 [ # # ]: 0 : assert(data != NULL);
2097 : 0 : rc = scsi_pr_in(task, cdb, data, data_len);
2098 : 0 : break;
2099 : :
2100 : 0 : case SPDK_SPC2_RESERVE_6:
2101 : : case SPDK_SPC2_RESERVE_10:
2102 : 0 : rc = scsi2_reserve(task, cdb);
2103 [ # # ]: 0 : if (rc == 0) {
2104 [ # # ]: 0 : if (cdb[0] == SPDK_SPC2_RESERVE_10) {
2105 : 0 : rc = from_be16(&cdb[7]);
2106 : : }
2107 : 0 : data_len = 0;
2108 : : }
2109 : 0 : break;
2110 : :
2111 : 0 : case SPDK_SPC2_RELEASE_6:
2112 : : case SPDK_SPC2_RELEASE_10:
2113 : 0 : rc = scsi2_release(task);
2114 : 0 : break;
2115 : :
2116 : 345 : default:
2117 : 345 : return SPDK_SCSI_TASK_UNKNOWN;
2118 : : }
2119 : :
2120 [ + + + + ]: 21566 : if (rc >= 0 && data_len > 0) {
2121 [ - + ]: 17726 : assert(alloc_len >= 0);
2122 : 17726 : spdk_scsi_task_scatter_data(task, data, spdk_min(alloc_len, data_len));
2123 : 17726 : rc = spdk_min(data_len, alloc_len);
2124 : : }
2125 : :
2126 [ + + ]: 21566 : if (rc >= 0) {
2127 : 19922 : task->data_transferred = rc;
2128 : 19922 : task->status = SPDK_SCSI_STATUS_GOOD;
2129 : : }
2130 : :
2131 [ + + ]: 21566 : if (data) {
2132 : 19374 : free(data);
2133 : : }
2134 : :
2135 : 21566 : return SPDK_SCSI_TASK_COMPLETE;
2136 : : }
2137 : :
2138 : : int
2139 : 32927863 : bdev_scsi_execute(struct spdk_scsi_task *task)
2140 : : {
2141 : : int rc;
2142 : :
2143 [ + + ]: 32927863 : if ((rc = bdev_scsi_process_block(task)) == SPDK_SCSI_TASK_UNKNOWN) {
2144 [ + + ]: 21911 : if ((rc = bdev_scsi_process_primary(task)) == SPDK_SCSI_TASK_UNKNOWN) {
2145 [ - + - + ]: 345 : SPDK_DEBUGLOG(scsi, "unsupported SCSI OP=0x%x\n", task->cdb[0]);
2146 : : /* INVALID COMMAND OPERATION CODE */
2147 : 345 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
2148 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
2149 : : SPDK_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
2150 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
2151 : 345 : return SPDK_SCSI_TASK_COMPLETE;
2152 : : }
2153 : : }
2154 : :
2155 : 32927518 : return rc;
2156 : : }
2157 : :
2158 : : static void
2159 : 0 : bdev_scsi_reset_resubmit(void *arg)
2160 : : {
2161 : 0 : struct spdk_scsi_task *task = arg;
2162 : :
2163 : 0 : bdev_scsi_reset(task);
2164 : 0 : }
2165 : :
2166 : : void
2167 : 10 : bdev_scsi_reset(struct spdk_scsi_task *task)
2168 : : {
2169 : 10 : struct spdk_scsi_lun *lun = task->lun;
2170 : : int rc;
2171 : :
2172 : 10 : rc = spdk_bdev_reset(lun->bdev_desc, lun->io_channel, bdev_scsi_task_complete_reset,
2173 : : task);
2174 [ - + ]: 10 : if (rc == -ENOMEM) {
2175 : 0 : bdev_scsi_queue_io(task, bdev_scsi_reset_resubmit, task);
2176 : : }
2177 : 10 : }
2178 : :
2179 : : bool
2180 : 26171076 : bdev_scsi_get_dif_ctx(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
2181 : : struct spdk_dif_ctx *dif_ctx)
2182 : : {
2183 : 26171076 : uint32_t ref_tag = 0, dif_check_flags = 0, data_offset;
2184 : : uint8_t *cdb;
2185 : : int rc;
2186 : 12 : struct spdk_dif_ctx_init_ext_opts dif_opts;
2187 : :
2188 [ + + ]: 26171076 : if (spdk_likely(spdk_bdev_get_md_size(bdev) == 0)) {
2189 : 26171064 : return false;
2190 : : }
2191 : :
2192 : 12 : cdb = task->cdb;
2193 : 12 : data_offset = task->offset;
2194 : :
2195 : : /* We use lower 32 bits of LBA as Reference. Tag */
2196 [ + + + - ]: 12 : switch (cdb[0]) {
2197 : 4 : case SPDK_SBC_READ_6:
2198 : : case SPDK_SBC_WRITE_6:
2199 : 4 : ref_tag = (uint32_t)cdb[1] << 16;
2200 : 4 : ref_tag |= (uint32_t)cdb[2] << 8;
2201 : 4 : ref_tag |= (uint32_t)cdb[3];
2202 : 4 : break;
2203 : 4 : case SPDK_SBC_READ_10:
2204 : : case SPDK_SBC_WRITE_10:
2205 : : case SPDK_SBC_READ_12:
2206 : : case SPDK_SBC_WRITE_12:
2207 : 4 : ref_tag = from_be32(&cdb[2]);
2208 : 4 : break;
2209 : 4 : case SPDK_SBC_READ_16:
2210 : : case SPDK_SBC_WRITE_16:
2211 : 4 : ref_tag = (uint32_t)from_be64(&cdb[2]);
2212 : 4 : break;
2213 : 0 : default:
2214 : 0 : return false;
2215 : : }
2216 : :
2217 [ - + ]: 12 : if (spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_REFTAG)) {
2218 : 0 : dif_check_flags |= SPDK_DIF_FLAGS_REFTAG_CHECK;
2219 : : }
2220 : :
2221 [ - + ]: 12 : if (spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_GUARD)) {
2222 : 0 : dif_check_flags |= SPDK_DIF_FLAGS_GUARD_CHECK;
2223 : : }
2224 : :
2225 : 12 : dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
2226 : 12 : dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
2227 : 24 : rc = spdk_dif_ctx_init(dif_ctx,
2228 : : spdk_bdev_get_block_size(bdev),
2229 : : spdk_bdev_get_md_size(bdev),
2230 : 12 : spdk_bdev_is_md_interleaved(bdev),
2231 : 12 : spdk_bdev_is_dif_head_of_md(bdev),
2232 : : spdk_bdev_get_dif_type(bdev),
2233 : : dif_check_flags,
2234 : : ref_tag, 0, 0, data_offset, 0, &dif_opts);
2235 : :
2236 : 12 : return (rc == 0) ? true : false;
2237 : : }
|