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 : 1151 : bdev_scsi_set_naa_ieee_extended(const char *name, uint8_t *buf)
33 : : {
34 : : int i;
35 : 1151 : uint64_t local_value = 0, id_a, seed = 131;
36 : :
37 [ + + ]: 33030 : for (i = 0; name[i] != '\0'; i++) {
38 : 31879 : 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 : 1151 : id_a = local_value & 0x0000000fff000000ull;
46 : 1151 : id_a = id_a << 24;
47 : :
48 : 1151 : local_value &= 0x0000000000ffffffull;
49 : : /* NAA 02, and 00 03 47 for IEEE Intel */
50 : 1151 : local_value |= 0x2000000347000000ull;
51 : 1151 : local_value |= id_a;
52 : :
53 : 1151 : to_be64((void *)buf, local_value);
54 : 1151 : }
55 : :
56 : : static int
57 : 139 : 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 : 139 : int hlen, len = 0;
64 : :
65 [ - + ]: 139 : if (alloc_len < 8) {
66 : 0 : return -1;
67 : : }
68 : :
69 [ - + ]: 139 : 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 [ - + ]: 139 : memset(data, 0, 4);
81 : :
82 : : /* Reserved */
83 [ - + ]: 139 : memset(&data[4], 0, 4);
84 : 139 : hlen = 8;
85 : :
86 : 139 : dev = lun->dev;
87 : :
88 [ + + ]: 284 : for (tmp_lun = spdk_scsi_dev_get_first_lun(dev); tmp_lun != NULL;
89 : 145 : tmp_lun = spdk_scsi_dev_get_next_lun(tmp_lun)) {
90 [ - + ]: 145 : if (alloc_len - (hlen + len) < 8) {
91 : 0 : return -1;
92 : : }
93 : :
94 : 145 : fmt_lun = spdk_scsi_lun_id_int_to_fmt(tmp_lun->id);
95 : :
96 : : /* LUN */
97 : 145 : to_be64(&data[hlen + len], fmt_lun);
98 : 145 : len += 8;
99 : : }
100 : :
101 : : /* LUN LIST LENGTH */
102 : 139 : to_be32(data, len);
103 : :
104 : 139 : return hlen + len;
105 : : }
106 : :
107 : : static int
108 : 1163 : bdev_scsi_pad_scsi_name(char *dst, const char *name)
109 : : {
110 : : size_t len;
111 : :
112 [ - + ]: 1163 : len = strlen(name);
113 [ - + - + ]: 1163 : memcpy(dst, name, len);
114 : : do {
115 : 2446 : dst[len++] = '\0';
116 [ + + ]: 2446 : } while (len & 3);
117 : :
118 : 1163 : return len;
119 : : }
120 : :
121 : : static int
122 : 7834 : 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 : 7834 : int hlen = 0, plen, plen2;
130 : 7834 : uint16_t len = 0;
131 : : int pc;
132 : : int pd;
133 : : int evpd;
134 : : int i;
135 : 7834 : struct spdk_scsi_cdb_inquiry *inq = (struct spdk_scsi_cdb_inquiry *)cdb;
136 : :
137 : : /* standard inquiry command at lease with 36 Bytes */
138 [ - + ]: 7834 : if (alloc_len < 0x24) {
139 : 0 : goto inq_error;
140 : : }
141 : :
142 : 7834 : lun = task->lun;
143 : 7834 : dev = lun->dev;
144 : 7834 : port = task->target_port;
145 : :
146 : 7834 : pd = SPDK_SPC_PERIPHERAL_DEVICE_TYPE_DISK;
147 : 7834 : pc = inq->page_code;
148 : 7834 : evpd = inq->evpd & 0x1;
149 : :
150 [ + + + + ]: 7834 : if (!evpd && pc) {
151 : 4 : 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 : 4 : return -1;
156 : : }
157 : :
158 [ + + ]: 7830 : if (evpd) {
159 : 5467 : struct spdk_scsi_vpd_page *vpage = (struct spdk_scsi_vpd_page *)data;
160 : :
161 : : /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
162 : 5467 : vpage->peripheral_device_type = pd;
163 : 5467 : vpage->peripheral_qualifier = SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED;
164 : : /* PAGE CODE */
165 : 5467 : vpage->page_code = pc;
166 : :
167 : : /* Vital product data */
168 [ + + + - : 5467 : switch (pc) {
- - - + +
+ + ]
169 : 1448 : case SPDK_SPC_VPD_SUPPORTED_VPD_PAGES:
170 : 1448 : hlen = 4;
171 : :
172 : 1448 : vpage->params[0] = SPDK_SPC_VPD_SUPPORTED_VPD_PAGES;
173 : 1448 : vpage->params[1] = SPDK_SPC_VPD_UNIT_SERIAL_NUMBER;
174 : 1448 : vpage->params[2] = SPDK_SPC_VPD_DEVICE_IDENTIFICATION;
175 : 1448 : vpage->params[3] = SPDK_SPC_VPD_MANAGEMENT_NETWORK_ADDRESSES;
176 : 1448 : vpage->params[4] = SPDK_SPC_VPD_EXTENDED_INQUIRY_DATA;
177 : 1448 : vpage->params[5] = SPDK_SPC_VPD_MODE_PAGE_POLICY;
178 : 1448 : vpage->params[6] = SPDK_SPC_VPD_SCSI_PORTS;
179 : 1448 : vpage->params[7] = SPDK_SPC_VPD_BLOCK_LIMITS;
180 : 1448 : vpage->params[8] = SPDK_SPC_VPD_BLOCK_DEV_CHARS;
181 : 1448 : len = 9;
182 [ + + ]: 1448 : if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
183 : 1434 : vpage->params[9] = SPDK_SPC_VPD_BLOCK_THIN_PROVISION;
184 : 1434 : len++;
185 : : }
186 : :
187 : : /* PAGE LENGTH */
188 : 1448 : to_be16(vpage->alloc_len, len);
189 : 1448 : break;
190 : :
191 : 1151 : case SPDK_SPC_VPD_UNIT_SERIAL_NUMBER: {
192 : 1151 : const char *name = spdk_bdev_get_name(bdev);
193 : :
194 : 1151 : hlen = 4;
195 : :
196 : : /* PRODUCT SERIAL NUMBER */
197 [ - + ]: 1151 : len = strlen(name) + 1;
198 [ + + ]: 1151 : if (len > MAX_SERIAL_STRING) {
199 : 822 : len = MAX_SERIAL_STRING;
200 : : }
201 : :
202 [ - + - + ]: 1151 : memcpy(vpage->params, name, len - 1);
203 : 1151 : vpage->params[len - 1] = 0;
204 : :
205 : : /* PAGE LENGTH */
206 : 1151 : to_be16(vpage->alloc_len, len);
207 : 1151 : break;
208 : : }
209 : :
210 : 1151 : case SPDK_SPC_VPD_DEVICE_IDENTIFICATION: {
211 : 1151 : const char *name = spdk_bdev_get_name(bdev);
212 : 1151 : const char *product_name = spdk_bdev_get_product_name(bdev);
213 : 1151 : uint8_t protocol_id = dev->protocol_id;
214 : 1151 : uint8_t *buf = vpage->params;
215 : : struct spdk_scsi_desig_desc *desig;
216 : :
217 : 1151 : hlen = 4;
218 : :
219 : : /* Check total length by calculated how much space all entries take */
220 : 1151 : len = sizeof(struct spdk_scsi_desig_desc) + 8;
221 : 1151 : len += sizeof(struct spdk_scsi_desig_desc) + 8 + 16 + MAX_SERIAL_STRING;
222 : 1151 : len += sizeof(struct spdk_scsi_desig_desc) + SPDK_SCSI_DEV_MAX_NAME + 1;
223 : 1151 : len += sizeof(struct spdk_scsi_desig_desc) + SPDK_SCSI_PORT_MAX_NAME_LENGTH;
224 : 1151 : len += sizeof(struct spdk_scsi_desig_desc) + 4;
225 : 1151 : len += sizeof(struct spdk_scsi_desig_desc) + 4;
226 : 1151 : len += sizeof(struct spdk_scsi_desig_desc) + 4;
227 [ - + ]: 1151 : 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 : 1151 : desig = (struct spdk_scsi_desig_desc *)buf;
239 : 1151 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
240 : 1151 : desig->protocol_id = protocol_id;
241 : 1151 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_NAA;
242 : 1151 : desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
243 : 1151 : desig->reserved0 = 0;
244 : 1151 : desig->piv = 1;
245 : 1151 : desig->reserved1 = 0;
246 : 1151 : desig->len = 8;
247 : 1151 : bdev_scsi_set_naa_ieee_extended(name, desig->desig);
248 : 1151 : len = sizeof(struct spdk_scsi_desig_desc) + 8;
249 : :
250 : 1151 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
251 : :
252 : : /* T10 Vendor ID designator */
253 : 1151 : desig = (struct spdk_scsi_desig_desc *)buf;
254 : 1151 : desig->code_set = SPDK_SPC_VPD_CODE_SET_ASCII;
255 : 1151 : desig->protocol_id = protocol_id;
256 : 1151 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_T10_VENDOR_ID;
257 : 1151 : desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
258 : 1151 : desig->reserved0 = 0;
259 : 1151 : desig->piv = 1;
260 : 1151 : desig->reserved1 = 0;
261 : 1151 : desig->len = 8 + 16 + MAX_SERIAL_STRING;
262 : 1151 : spdk_strcpy_pad(desig->desig, DEFAULT_DISK_VENDOR, 8, ' ');
263 : 1151 : spdk_strcpy_pad(&desig->desig[8], product_name, 16, ' ');
264 : 1151 : spdk_strcpy_pad(&desig->desig[24], name, MAX_SERIAL_STRING, ' ');
265 : 1151 : len += sizeof(struct spdk_scsi_desig_desc) + 8 + 16 + MAX_SERIAL_STRING;
266 : :
267 : 1151 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
268 : :
269 : : /* SCSI Device Name designator */
270 : 1151 : desig = (struct spdk_scsi_desig_desc *)buf;
271 : 1151 : desig->code_set = SPDK_SPC_VPD_CODE_SET_UTF8;
272 : 1151 : desig->protocol_id = protocol_id;
273 : 1151 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
274 : 1151 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_DEVICE;
275 : 1151 : desig->reserved0 = 0;
276 : 1151 : desig->piv = 1;
277 : 1151 : desig->reserved1 = 0;
278 : 1151 : desig->len = bdev_scsi_pad_scsi_name(desig->desig, dev->name);
279 : 1151 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
280 : :
281 : 1151 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
282 : :
283 : : /* SCSI Port Name designator */
284 : 1151 : desig = (struct spdk_scsi_desig_desc *)buf;
285 : 1151 : desig->code_set = SPDK_SPC_VPD_CODE_SET_UTF8;
286 : 1151 : desig->protocol_id = protocol_id;
287 : 1151 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
288 : 1151 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
289 : 1151 : desig->reserved0 = 0;
290 : 1151 : desig->piv = 1;
291 : 1151 : desig->reserved1 = 0;
292 : 1151 : desig->len = snprintf(desig->desig, SPDK_SCSI_PORT_MAX_NAME_LENGTH, "%s", port->name);
293 : 1151 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
294 : :
295 : 1151 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
296 : :
297 : : /* Relative Target Port designator */
298 : 1151 : desig = (struct spdk_scsi_desig_desc *)buf;
299 : 1151 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
300 : 1151 : desig->protocol_id = protocol_id;
301 : 1151 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_RELATIVE_TARGET_PORT;
302 : 1151 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
303 : 1151 : desig->reserved0 = 0;
304 : 1151 : desig->piv = 1;
305 : 1151 : desig->reserved1 = 0;
306 : 1151 : desig->len = 4;
307 [ - + ]: 1151 : memset(desig->desig, 0, 2); /* Reserved */
308 : 1151 : to_be16(&desig->desig[2], port->index);
309 : 1151 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
310 : :
311 : 1151 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
312 : :
313 : : /* Target port group designator */
314 : 1151 : desig = (struct spdk_scsi_desig_desc *)buf;
315 : 1151 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
316 : 1151 : desig->protocol_id = protocol_id;
317 : 1151 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_TARGET_PORT_GROUP;
318 : 1151 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
319 : 1151 : desig->reserved0 = 0;
320 : 1151 : desig->piv = 1;
321 : 1151 : desig->reserved1 = 0;
322 : 1151 : desig->len = 4;
323 [ - + ]: 1151 : memset(desig->desig, 0, 4);
324 : 1151 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
325 : :
326 : 1151 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
327 : :
328 : : /* Logical unit group designator */
329 : 1151 : desig = (struct spdk_scsi_desig_desc *)buf;
330 : 1151 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
331 : 1151 : desig->protocol_id = protocol_id;
332 : 1151 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_LOGICAL_UNIT_GROUP;
333 : 1151 : desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
334 : 1151 : desig->reserved0 = 0;
335 : 1151 : desig->piv = 1;
336 : 1151 : desig->reserved1 = 0;
337 : 1151 : desig->len = 4;
338 [ - + ]: 1151 : memset(desig->desig, 0, 2); /* Reserved */
339 : 1151 : to_be16(&desig->desig[2], dev->id);
340 : 1151 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
341 : :
342 : 1151 : to_be16(vpage->alloc_len, len);
343 : :
344 : 1151 : 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 : 280 : case SPDK_SPC_VPD_BLOCK_LIMITS: {
477 : 280 : uint32_t block_size = spdk_bdev_get_data_block_size(bdev);
478 : :
479 : : /* PAGE LENGTH */
480 [ - + ]: 280 : memset(&data[4], 0, 60);
481 : :
482 : 280 : hlen = 4;
483 : :
484 : : /* WSNZ(0) */
485 : : /* support zero length in WRITE SAME */
486 : :
487 : : /* MAXIMUM COMPARE AND WRITE LENGTH */
488 [ - + ]: 280 : blocks = SPDK_WORK_ATS_BLOCK_SIZE / block_size;
489 : :
490 [ + - ]: 280 : if (blocks > 0xff) {
491 : 280 : blocks = 0xff;
492 : : }
493 : :
494 : 280 : data[5] = (uint8_t)blocks;
495 : :
496 : : /* force align to 4KB */
497 [ + + ]: 280 : if (block_size < 4096) {
498 [ - + ]: 74 : optimal_blocks = 4096 / block_size;
499 : : } else {
500 : 206 : optimal_blocks = 1;
501 : : }
502 : :
503 : : /* OPTIMAL TRANSFER LENGTH GRANULARITY */
504 : 280 : to_be16(&data[6], optimal_blocks);
505 : :
506 [ - + ]: 280 : blocks = SPDK_WORK_BLOCK_SIZE / block_size;
507 : :
508 : : /* MAXIMUM TRANSFER LENGTH */
509 : 280 : to_be32(&data[8], blocks);
510 : : /* OPTIMAL TRANSFER LENGTH */
511 : 280 : to_be32(&data[12], blocks);
512 : :
513 : : /* MAXIMUM PREFETCH XDREAD XDWRITE TRANSFER LENGTH */
514 : :
515 [ + + ]: 280 : 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 : 276 : 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 : 276 : 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 : 280 : to_be64(&data[36], blocks);
549 : :
550 : : /* Reserved */
551 : : /* not specified */
552 : 280 : len = 64 - hlen;
553 : :
554 : 280 : to_be16(vpage->alloc_len, len);
555 : 280 : break;
556 : : }
557 : :
558 : 272 : case SPDK_SPC_VPD_BLOCK_DEV_CHARS: {
559 : : /* PAGE LENGTH */
560 : 272 : hlen = 4;
561 : 272 : len = 64 - hlen;
562 : :
563 : 272 : to_be16(&data[4], DEFAULT_DISK_ROTATION_RATE);
564 : :
565 : : /* Reserved */
566 : 272 : data[6] = 0;
567 : : /* NOMINAL FORM FACTOR(3-0) */
568 : 272 : data[7] = DEFAULT_DISK_FORM_FACTOR << 4;
569 : : /* Reserved */
570 [ - + ]: 272 : memset(&data[8], 0, 64 - 8);
571 : :
572 : 272 : to_be16(vpage->alloc_len, len);
573 : 272 : break;
574 : : }
575 : :
576 : 302 : case SPDK_SPC_VPD_BLOCK_THIN_PROVISION: {
577 [ + + ]: 302 : if (!spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
578 : 1 : goto inq_error;
579 : : }
580 : :
581 : 301 : hlen = 4;
582 : 301 : 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 : 301 : 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 : 301 : data[4] = 0;
596 : :
597 : : /*
598 : : * Set the LBPU bit to indicate the support for UNMAP
599 : : * command.
600 : : */
601 : 301 : data[5] |= SPDK_SCSI_UNMAP_LBPU;
602 : :
603 : : /*
604 : : * Set the provisioning type to thin provision.
605 : : */
606 : 301 : data[6] = SPDK_SCSI_UNMAP_THIN_PROVISIONING;
607 : :
608 : 301 : to_be16(vpage->alloc_len, len);
609 : 301 : break;
610 : : }
611 : :
612 : 863 : default:
613 [ - + - - ]: 863 : if (pc >= 0xc0 && pc <= 0xff) {
614 [ # # # # ]: 0 : SPDK_DEBUGLOG(scsi, "Vendor specific INQUIRY VPD page 0x%x\n", pc);
615 : : } else {
616 : 863 : SPDK_NOTICELOG("unsupported INQUIRY VPD page 0x%x\n", pc);
617 : : }
618 : 863 : goto inq_error;
619 : : }
620 : : } else {
621 : 2363 : 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 : 2363 : inqdata->peripheral_device_type = pd;
627 : 2363 : inqdata->peripheral_qualifier = SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED;
628 : :
629 : : /* RMB(7) */
630 : 2363 : inqdata->rmb = 0;
631 : :
632 : : /* VERSION */
633 : : /* See SPC3/SBC2/MMC4/SAM2 for more details */
634 : 2363 : inqdata->version = SPDK_SPC_VERSION_SPC3;
635 : :
636 : : /* NORMACA(5) HISUP(4) RESPONSE DATA FORMAT(3-0) */
637 : : /* format 2 */ /* hierarchical support */
638 : 2363 : inqdata->response = 2 | 1 << 4;
639 : :
640 : 2363 : hlen = 5;
641 : :
642 : : /* SCCS(7) ACC(6) TPGS(5-4) 3PC(3) PROTECT(0) */
643 : : /* Not support TPGS */
644 : 2363 : inqdata->flags = 0;
645 : :
646 : : /* MULTIP */
647 : 2363 : inqdata->flags2 = 0x10;
648 : :
649 : : /* WBUS16(5) SYNC(4) LINKED(3) CMDQUE(1) VS(0) */
650 : : /* CMDQUE */
651 : 2363 : inqdata->flags3 = 0x2;
652 : :
653 : : /* T10 VENDOR IDENTIFICATION */
654 : 2363 : spdk_strcpy_pad(inqdata->t10_vendor_id, DEFAULT_DISK_VENDOR, 8, ' ');
655 : :
656 : : /* PRODUCT IDENTIFICATION */
657 : 2363 : spdk_strcpy_pad(inqdata->product_id, spdk_bdev_get_product_name(bdev), 16, ' ');
658 : :
659 : : /* PRODUCT REVISION LEVEL */
660 : 2363 : 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 : 2363 : len = INQUIRY_OFFSET(product_rev) - 5;
667 : :
668 [ + - ]: 2363 : if (alloc_len >= INQUIRY_OFFSET(vendor)) {
669 : : /* Vendor specific */
670 [ - + ]: 2363 : memset(inqdata->vendor, 0x20, 20);
671 : 2363 : len += sizeof(inqdata->vendor);
672 : : }
673 : :
674 [ + - ]: 2363 : if (alloc_len >= INQUIRY_OFFSET(ius)) {
675 : : /* CLOCKING(3-2) QAS(1) IUS(0) */
676 : 2363 : inqdata->ius = 0;
677 : 2363 : len += sizeof(inqdata->ius);
678 : : }
679 : :
680 [ + - ]: 2363 : if (alloc_len >= INQUIRY_OFFSET(reserved)) {
681 : : /* Reserved */
682 : 2363 : inqdata->reserved = 0;
683 : 2363 : len += sizeof(inqdata->reserved);
684 : : }
685 : :
686 : : /* VERSION DESCRIPTOR 1-8 */
687 [ + - ]: 2363 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 2) {
688 : 2363 : to_be16(&inqdata->desc[0], 0x0960);
689 : 2363 : len += 2;
690 : : }
691 : :
692 [ + - ]: 2363 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 4) {
693 : 2363 : to_be16(&inqdata->desc[2], 0x0300); /* SPC-3 (no version claimed) */
694 : 2363 : len += 2;
695 : : }
696 : :
697 [ + - ]: 2363 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 6) {
698 : 2363 : to_be16(&inqdata->desc[4], 0x320); /* SBC-2 (no version claimed) */
699 : 2363 : len += 2;
700 : : }
701 : :
702 [ + - ]: 2363 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 8) {
703 : 2363 : to_be16(&inqdata->desc[6], 0x0040); /* SAM-2 (no version claimed) */
704 : 2363 : 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 [ + - ]: 2363 : if (alloc_len > INQUIRY_OFFSET(reserved) + 8) {
715 : 2363 : i = alloc_len - (INQUIRY_OFFSET(reserved) + 8);
716 [ + - ]: 2363 : if (i > 30) {
717 : 2363 : i = 30;
718 : : }
719 [ - + ]: 2363 : memset(&inqdata->desc[8], 0, i);
720 : 2363 : len += i;
721 : : }
722 : :
723 : : /* ADDITIONAL LENGTH */
724 : 2363 : inqdata->add_len = len;
725 : : }
726 : :
727 : 6966 : return hlen + len;
728 : :
729 : 864 : inq_error:
730 : 864 : task->data_transferred = 0;
731 : 864 : 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 : 864 : return -1;
736 : : }
737 : :
738 : : static void
739 : 20108 : mode_sense_page_init(uint8_t *buf, int len, int page, int subpage)
740 : : {
741 [ + + ]: 20108 : if (!buf) {
742 : 10054 : return;
743 : : }
744 : :
745 [ - + ]: 10054 : memset(buf, 0, len);
746 [ - + ]: 10054 : 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 : 10054 : buf[0] = page;
752 : 10054 : buf[1] = len - 2;
753 : : }
754 : : }
755 : :
756 : : static int
757 : 130878 : 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 : 130878 : uint8_t *cp = data;
762 : 130878 : int len = 0;
763 : : int plen;
764 : : int i;
765 : :
766 [ - + ]: 130878 : 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 [ + + + + : 130878 : switch (page) {
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + - ]
784 : 2014 : case 0x00:
785 : : /* Vendor specific */
786 : 2014 : break;
787 : 2014 : case 0x01:
788 : : /* Read-Write Error Recovery */
789 [ - + - + ]: 2014 : SPDK_DEBUGLOG(scsi,
790 : : "MODE_SENSE Read-Write Error Recovery\n");
791 [ - + ]: 2014 : if (subpage != 0x00) {
792 : 0 : break;
793 : : }
794 : 2014 : plen = 0x0a + 2;
795 : 2014 : mode_sense_page_init(cp, plen, page, subpage);
796 : 2014 : len += plen;
797 : 2014 : break;
798 : 2014 : case 0x02:
799 : : /* Disconnect-Reconnect */
800 [ - + - + ]: 2014 : SPDK_DEBUGLOG(scsi,
801 : : "MODE_SENSE Disconnect-Reconnect\n");
802 [ - + ]: 2014 : if (subpage != 0x00) {
803 : 0 : break;
804 : : }
805 : 2014 : plen = 0x0e + 2;
806 : 2014 : mode_sense_page_init(cp, plen, page, subpage);
807 : 2014 : len += plen;
808 : 2014 : break;
809 : 2014 : case 0x03:
810 : : /* Obsolete (Format Device) */
811 : 2014 : break;
812 : 2014 : case 0x04:
813 : : /* Obsolete (Rigid Disk Geometry) */
814 : 2014 : break;
815 : 2014 : case 0x05:
816 : : /* Obsolete (Rigid Disk Geometry) */
817 : 2014 : break;
818 : 2014 : case 0x06:
819 : : /* Reserved */
820 : 2014 : break;
821 : 2014 : case 0x07:
822 : : /* Verify Error Recovery */
823 [ - + - + ]: 2014 : SPDK_DEBUGLOG(scsi,
824 : : "MODE_SENSE Verify Error Recovery\n");
825 : :
826 [ - + ]: 2014 : if (subpage != 0x00) {
827 : 0 : break;
828 : : }
829 : :
830 : 2014 : plen = 0x0a + 2;
831 : 2014 : mode_sense_page_init(cp, plen, page, subpage);
832 : 2014 : len += plen;
833 : 2014 : break;
834 : 6010 : case 0x08: {
835 : : /* Caching */
836 [ - + - + ]: 6010 : SPDK_DEBUGLOG(scsi, "MODE_SENSE Caching\n");
837 [ - + ]: 6010 : if (subpage != 0x00) {
838 : 0 : break;
839 : : }
840 : :
841 : 6010 : plen = 0x12 + 2;
842 : 6010 : mode_sense_page_init(cp, plen, page, subpage);
843 : :
844 [ + + + + : 6010 : if (cp && spdk_bdev_has_write_cache(bdev) && pc != 0x01) {
+ - ]
845 : 681 : cp[2] |= 0x4; /* WCE */
846 : : }
847 : :
848 : : /* Read Cache Disable (RCD) = 1 */
849 [ + + + - ]: 6010 : if (cp && pc != 0x01) {
850 : 3005 : cp[2] |= 0x1;
851 : : }
852 : :
853 : 6010 : len += plen;
854 : 6010 : break;
855 : : }
856 : 2014 : case 0x09:
857 : : /* Obsolete */
858 : 2014 : break;
859 [ + - - - ]: 2014 : case 0x0a:
860 : : switch (subpage) {
861 : 2014 : case 0x00:
862 : : /* Control */
863 [ - + - + ]: 2014 : SPDK_DEBUGLOG(scsi,
864 : : "MODE_SENSE Control\n");
865 : 2014 : plen = 0x0a + 2;
866 : 2014 : mode_sense_page_init(cp, plen, page, subpage);
867 : 2014 : len += plen;
868 : 2014 : 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 : 2014 : break;
893 : 2014 : case 0x0b:
894 : : /* Obsolete (Medium Types Supported) */
895 : 2014 : break;
896 : 2014 : case 0x0c:
897 : : /* Obsolete (Notch And Partition) */
898 : 2014 : break;
899 : 2014 : case 0x0d:
900 : : /* Obsolete */
901 : 2014 : break;
902 : 4028 : case 0x0e:
903 : : case 0x0f:
904 : : /* Reserved */
905 : 4028 : break;
906 : 2014 : case 0x10:
907 : : /* XOR Control */
908 [ - + - + ]: 2014 : SPDK_DEBUGLOG(scsi, "MODE_SENSE XOR Control\n");
909 [ - + ]: 2014 : if (subpage != 0x00) {
910 : 0 : break;
911 : : }
912 : 2014 : plen = 0x16 + 2;
913 : 2014 : mode_sense_page_init(cp, plen, page, subpage);
914 : 2014 : len += plen;
915 : 2014 : break;
916 : 6042 : case 0x11:
917 : : case 0x12:
918 : : case 0x13:
919 : : /* Reserved */
920 : 6042 : break;
921 : 2014 : case 0x14:
922 : : /* Enclosure Services Management */
923 : 2014 : break;
924 : 6042 : case 0x15:
925 : : case 0x16:
926 : : case 0x17:
927 : : /* Reserved */
928 : 6042 : break;
929 : 2014 : case 0x18:
930 : : /* Protocol-Specific LUN */
931 : 2014 : break;
932 : 2014 : case 0x19:
933 : : /* Protocol-Specific Port */
934 : 2014 : break;
935 : 2014 : case 0x1a:
936 : : /* Power Condition */
937 [ - + - + ]: 2014 : SPDK_DEBUGLOG(scsi,
938 : : "MODE_SENSE Power Condition\n");
939 [ - + ]: 2014 : if (subpage != 0x00) {
940 : 0 : break;
941 : : }
942 : 2014 : plen = 0x0a + 2;
943 : 2014 : mode_sense_page_init(cp, plen, page, subpage);
944 : 2014 : len += plen;
945 : 2014 : break;
946 : 2014 : case 0x1b:
947 : : /* Reserved */
948 : 2014 : break;
949 : 2014 : case 0x1c:
950 : : /* Informational Exceptions Control */
951 [ - + - + ]: 2014 : SPDK_DEBUGLOG(scsi,
952 : : "MODE_SENSE Informational Exceptions Control\n");
953 [ - + ]: 2014 : if (subpage != 0x00) {
954 : 0 : break;
955 : : }
956 : :
957 : 2014 : plen = 0x0a + 2;
958 : 2014 : mode_sense_page_init(cp, plen, page, subpage);
959 : 2014 : len += plen;
960 : 2014 : break;
961 : 6042 : case 0x1d:
962 : : case 0x1e:
963 : : case 0x1f:
964 : : /* Reserved */
965 : 6042 : break;
966 : 60420 : 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 : 60420 : break;
999 [ + - - ]: 2014 : case 0x3f:
1000 : : switch (subpage) {
1001 : 2014 : case 0x00:
1002 : : /* All mode pages */
1003 [ + + ]: 126882 : for (i = 0x00; i < 0x3e; i ++) {
1004 [ + + ]: 187302 : len += bdev_scsi_mode_sense_page(
1005 : : bdev, cdb, pc, i, 0x00,
1006 : 62434 : cp ? &cp[len] : NULL, task);
1007 : : }
1008 : 2014 : 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 : 130878 : return len;
1029 : : }
1030 : :
1031 : : static int
1032 : 6010 : 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 : 6010 : uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev);
1037 : 6010 : 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 [ + + - + ]: 6010 : assert(md == 6 || md == 10);
1044 : :
1045 [ + + ]: 6010 : if (md == 6) {
1046 : 6002 : hlen = 4;
1047 : 6002 : blen = 8; /* For MODE SENSE 6 only short LBA */
1048 : : } else {
1049 : 8 : hlen = 8;
1050 [ - + ]: 8 : blen = llbaa ? 16 : 8;
1051 : : }
1052 : :
1053 [ - + ]: 6010 : if (dbd) {
1054 : 0 : blen = 0;
1055 : : }
1056 : :
1057 [ + + ]: 6010 : pages = data ? &data[hlen + blen] : NULL;
1058 : 6010 : plen = bdev_scsi_mode_sense_page(bdev, cdb, pc, page,
1059 : : subpage,
1060 : : pages, task);
1061 [ - + ]: 6010 : if (plen < 0) {
1062 : 0 : return -1;
1063 : : }
1064 : :
1065 : 6010 : total = hlen + blen + plen;
1066 [ + + ]: 6010 : if (data == NULL) {
1067 : 3005 : return total;
1068 : : }
1069 : :
1070 : 3005 : hdr = &data[0];
1071 [ + + ]: 3005 : if (hlen == 4) {
1072 : 3001 : hdr[0] = total - 1; /* Mode Data Length */
1073 : 3001 : hdr[1] = 0; /* Medium Type */
1074 : 3001 : hdr[2] = 0; /* Device-Specific Parameter */
1075 : 3001 : 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 : 3005 : bdesc = &data[hlen];
1086 [ - + ]: 3005 : 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 [ + - ]: 3005 : } else if (blen == 8) {
1094 : : /* Number of Blocks */
1095 [ + + ]: 3005 : if (num_blocks > 0xffffffffULL) {
1096 [ - + ]: 30 : memset(&bdesc[0], 0xff, 4);
1097 : : } else {
1098 : 2975 : to_be32(&bdesc[0], num_blocks);
1099 : : }
1100 : :
1101 : : /* Block Length */
1102 : 3005 : to_be32(&bdesc[4], block_size);
1103 : : }
1104 : :
1105 : 3005 : return total;
1106 : : }
1107 : :
1108 : : static void
1109 : 3428592 : bdev_scsi_task_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
1110 : : void *cb_arg)
1111 : : {
1112 : 3428592 : struct spdk_scsi_task *task = cb_arg;
1113 : 805102 : int sc, sk, asc, ascq;
1114 : :
1115 : 3428592 : spdk_bdev_io_get_scsi_status(bdev_io, &sc, &sk, &asc, &ascq);
1116 : :
1117 : 3428592 : spdk_bdev_free_io(bdev_io);
1118 : :
1119 : 3428592 : spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
1120 : 3428592 : scsi_lun_complete_task(task->lun, task);
1121 : 3428592 : }
1122 : :
1123 : : static void
1124 : 5409635 : bdev_scsi_read_task_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
1125 : : void *cb_arg)
1126 : : {
1127 : 5409635 : struct spdk_scsi_task *task = cb_arg;
1128 : 828672 : int sc, sk, asc, ascq;
1129 : :
1130 : 5409635 : task->bdev_io = bdev_io;
1131 : :
1132 : 5409635 : spdk_bdev_io_get_scsi_status(bdev_io, &sc, &sk, &asc, &ascq);
1133 : :
1134 : 5409635 : spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
1135 : 5409635 : scsi_lun_complete_task(task->lun, task);
1136 : 5409635 : }
1137 : :
1138 : : static void
1139 : 6 : bdev_scsi_task_complete_reset(struct spdk_bdev_io *bdev_io, bool success,
1140 : : void *cb_arg)
1141 : : {
1142 : 6 : struct spdk_scsi_task *task = cb_arg;
1143 : :
1144 : 6 : spdk_bdev_free_io(bdev_io);
1145 : :
1146 [ + - ]: 6 : if (success) {
1147 : 6 : task->response = SPDK_SCSI_TASK_MGMT_RESP_SUCCESS;
1148 : : }
1149 : :
1150 : 6 : scsi_lun_complete_reset_task(task->lun, task);
1151 : 6 : }
1152 : :
1153 : : static void
1154 : 182511 : bdev_scsi_queue_io(struct spdk_scsi_task *task, spdk_bdev_io_wait_cb cb_fn, void *cb_arg)
1155 : : {
1156 : 182511 : struct spdk_scsi_lun *lun = task->lun;
1157 : 182511 : struct spdk_bdev *bdev = lun->bdev;
1158 : 182511 : struct spdk_io_channel *ch = lun->io_channel;
1159 : : int rc;
1160 : :
1161 : 182511 : task->bdev_io_wait.bdev = bdev;
1162 : 182511 : task->bdev_io_wait.cb_fn = cb_fn;
1163 : 182511 : task->bdev_io_wait.cb_arg = cb_arg;
1164 : :
1165 : 182511 : rc = spdk_bdev_queue_io_wait(bdev, ch, &task->bdev_io_wait);
1166 [ - + ]: 182511 : if (rc != 0) {
1167 : 0 : assert(false);
1168 : : }
1169 : 182511 : }
1170 : :
1171 : : static int
1172 : 465823 : 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 [ - + ]: 465823 : if (num_blocks == 0) {
1180 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1181 : : }
1182 : :
1183 : 465823 : bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
1184 : :
1185 [ + - + - ]: 465823 : if (lba >= bdev_num_blocks || num_blocks > bdev_num_blocks ||
1186 [ - + ]: 465823 : lba > (bdev_num_blocks - num_blocks)) {
1187 : 0 : SPDK_ERRLOG("end of media\n");
1188 : 0 : 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 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1193 : : }
1194 : :
1195 : 465823 : rc = spdk_bdev_flush_blocks(bdev_desc, bdev_ch, lba, num_blocks,
1196 : : bdev_scsi_task_complete_cmd, task);
1197 : :
1198 [ + + ]: 465823 : if (rc) {
1199 [ + - ]: 57187 : if (rc == -ENOMEM) {
1200 : 57187 : bdev_scsi_queue_io(task, bdev_scsi_process_block_resubmit, task);
1201 : 57187 : 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 : 408636 : task->data_transferred = 0;
1211 : 408636 : return SPDK_SCSI_TASK_PENDING;
1212 : : }
1213 : :
1214 : : static uint64_t
1215 : 8513354 : _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 [ + - ]: 8513354 : if (spdk_likely(spdk_u32_is_pow2(block_size))) {
1222 : 8513354 : shift_cnt = spdk_u32log2(block_size);
1223 [ - + ]: 8513354 : *offset_blocks = offset_bytes >> shift_cnt;
1224 [ - + ]: 8513354 : *num_blocks = num_bytes >> shift_cnt;
1225 [ - + ]: 8513354 : return (offset_bytes - (*offset_blocks << shift_cnt)) |
1226 [ - + ]: 8513354 : (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 : 8513286 : 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 : 1633781 : uint64_t bdev_num_blocks, offset_blocks, num_blocks;
1240 : : uint32_t max_xfer_len, block_size;
1241 : 8513286 : int sk = SPDK_SCSI_SENSE_NO_SENSE, asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
1242 : : int rc;
1243 : :
1244 : 8513286 : task->data_transferred = 0;
1245 : :
1246 [ + + + + : 8513286 : 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 : 8513286 : bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
1253 [ + + + + ]: 8513286 : 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 [ + + ]: 8513274 : if (spdk_unlikely(xfer_len == 0)) {
1261 : 4 : task->status = SPDK_SCSI_STATUS_GOOD;
1262 : 4 : return SPDK_SCSI_TASK_COMPLETE;
1263 : : }
1264 : :
1265 : 8513270 : 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 [ - + ]: 8513270 : max_xfer_len = SPDK_WORK_BLOCK_SIZE / block_size;
1269 [ + + ]: 8513270 : 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 [ + + ]: 8513266 : if (!is_read) {
1278 : : /* Additional check for Transfer Length */
1279 [ - + ]: 3057864 : 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 [ - + ]: 8513266 : 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 : 8513266 : offset_blocks += lba;
1293 : :
1294 [ - + - + : 8513266 : SPDK_DEBUGLOG(scsi,
- - ]
1295 : : "%s: lba=%"PRIu64", len=%"PRIu64"\n",
1296 : : is_read ? "Read" : "Write", offset_blocks, num_blocks);
1297 : :
1298 [ + + ]: 8513266 : if (is_read) {
1299 : 5455402 : 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 [ - + ]: 3057864 : } 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 : 3057864 : 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 [ + + ]: 8513266 : if (rc) {
1333 [ + - ]: 83687 : if (rc == -ENOMEM) {
1334 : 83687 : bdev_scsi_queue_io(task, bdev_scsi_process_block_resubmit, task);
1335 : 83687 : 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 : 8429579 : task->data_transferred = task->length;
1343 : 8429579 : 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 : 41637 : bdev_scsi_split_resubmit(void *arg)
1367 : : {
1368 : 41637 : struct spdk_bdev_scsi_split_ctx *ctx = arg;
1369 : :
1370 : 41637 : bdev_scsi_split(ctx);
1371 : 41637 : }
1372 : :
1373 : : static int
1374 : 691884 : bdev_scsi_split(struct spdk_bdev_scsi_split_ctx *ctx)
1375 : : {
1376 : 691884 : struct spdk_scsi_task *task = ctx->task;
1377 : 691884 : uint8_t opcode = task->cdb[0];
1378 : : int rc;
1379 : :
1380 [ + + ]: 1583617 : while (ctx->remaining_count != 0) {
1381 : 933388 : rc = ctx->fn(ctx);
1382 [ + + ]: 933388 : if (rc == 0) {
1383 : 891733 : ctx->current_count++;
1384 : 891733 : ctx->remaining_count--;
1385 : 891733 : ctx->outstanding_count++;
1386 : 891733 : continue;
1387 [ + - ]: 41655 : } else if (rc == -ENOMEM) {
1388 : 41655 : break;
1389 : : }
1390 : :
1391 : 0 : SPDK_ERRLOG("SCSI %s failed\n", spdk_scsi_sbc_opcode_string(opcode, 0));
1392 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1393 : : SPDK_SCSI_SENSE_NO_SENSE,
1394 : : SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
1395 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1396 : : /* If any child I/O failed, stop further splitting process. */
1397 : 0 : ctx->current_count += ctx->remaining_count;
1398 : 0 : ctx->remaining_count = 0;
1399 : 0 : break;
1400 : : }
1401 : :
1402 [ + + ]: 691884 : if (ctx->outstanding_count != 0) {
1403 : : /* We can't complete here - we may have to wait for previously
1404 : : * submitted child I/Os to complete */
1405 : 650247 : return SPDK_SCSI_TASK_PENDING;
1406 : : }
1407 : :
1408 [ + - ]: 41637 : if (rc == -ENOMEM) {
1409 : : /* none outstanding child IO submitted, no callback would be involked.
1410 : : this is the last chance to resubmit on -ENOMEM */
1411 : 41637 : bdev_scsi_queue_io(task, bdev_scsi_split_resubmit, ctx);
1412 : 41637 : return SPDK_SCSI_TASK_PENDING;
1413 : : }
1414 : :
1415 : 0 : free(ctx);
1416 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1417 : : }
1418 : :
1419 : : static void
1420 : 891733 : bdev_scsi_task_complete_split_cmd(struct spdk_bdev_io *bdev_io, bool success,
1421 : : void *cb_arg)
1422 : : {
1423 : 891733 : struct spdk_bdev_scsi_split_ctx *ctx = cb_arg;
1424 : 891733 : struct spdk_scsi_task *task = ctx->task;
1425 : :
1426 : 891733 : spdk_bdev_free_io(bdev_io);
1427 : :
1428 [ - + ]: 891733 : if (!success) {
1429 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1430 : : SPDK_SCSI_SENSE_NO_SENSE,
1431 : : SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
1432 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1433 : : /* If any child I/O failed, stop further splitting process. */
1434 : 0 : ctx->current_count += ctx->remaining_count;
1435 : 0 : ctx->remaining_count = 0;
1436 : : }
1437 : :
1438 : 891733 : ctx->outstanding_count--;
1439 [ + + ]: 891733 : if (ctx->outstanding_count != 0) {
1440 : : /* Any child I/O is still outstanding. */
1441 : 241486 : return;
1442 : : }
1443 : :
1444 [ + + ]: 650247 : if (ctx->remaining_count == 0) {
1445 : : /* SCSI task finishes when all descriptors are consumed. */
1446 : 650229 : scsi_lun_complete_task(task->lun, task);
1447 : 650229 : free(ctx);
1448 : 650229 : return;
1449 : : }
1450 : :
1451 : : /* Continue with splitting process. */
1452 : 18 : bdev_scsi_split(ctx);
1453 : : }
1454 : :
1455 : : static int
1456 : 650141 : __copy_desc(struct spdk_bdev_scsi_split_ctx *ctx, uint8_t *data, size_t data_len)
1457 : : {
1458 : : uint16_t desc_data_len;
1459 : : uint16_t desc_count;
1460 : :
1461 [ - + ]: 650141 : if (!data) {
1462 : 0 : return -EINVAL;
1463 : : }
1464 : :
1465 [ - + ]: 650141 : if (data_len < 8) {
1466 : : /* We can't even get the reported length, so fail. */
1467 : 0 : return -EINVAL;
1468 : : }
1469 : :
1470 : 650141 : desc_data_len = from_be16(&data[2]);
1471 : 650141 : desc_count = desc_data_len / 16;
1472 : :
1473 [ - + ]: 650141 : if (desc_data_len > (data_len - 8)) {
1474 : 0 : SPDK_ERRLOG("Error - desc_data_len (%u) > data_len (%zu) - 8\n",
1475 : : desc_data_len, data_len);
1476 : 0 : return -EINVAL;
1477 : : }
1478 : :
1479 [ - + ]: 650141 : if (desc_count > DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT) {
1480 : 0 : SPDK_ERRLOG("desc_count (%u) greater than max allowed (%u)\n",
1481 : : desc_count, DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT);
1482 : 0 : return -EINVAL;
1483 : : }
1484 : :
1485 [ - + - + ]: 650141 : memcpy(ctx->desc, &data[8], desc_data_len);
1486 : 650141 : return desc_count;
1487 : : }
1488 : :
1489 : : static int
1490 : 691806 : _bdev_scsi_unmap(struct spdk_bdev_scsi_split_ctx *ctx)
1491 : : {
1492 : 691806 : struct spdk_scsi_task *task = ctx->task;
1493 : 691806 : struct spdk_scsi_lun *lun = task->lun;
1494 : : struct spdk_scsi_unmap_bdesc *desc;
1495 : : uint64_t offset_blocks;
1496 : : uint64_t num_blocks;
1497 : :
1498 : 691806 : desc = &ctx->desc[ctx->current_count];
1499 : :
1500 : 691806 : offset_blocks = from_be64(&desc->lba);
1501 : 691806 : num_blocks = from_be32(&desc->block_count);
1502 : :
1503 : 691806 : return spdk_bdev_unmap_blocks(lun->bdev_desc,
1504 : : lun->io_channel,
1505 : : offset_blocks,
1506 : : num_blocks,
1507 : : bdev_scsi_task_complete_split_cmd,
1508 : : ctx);
1509 : : }
1510 : :
1511 : : static int
1512 : 650141 : bdev_scsi_unmap(struct spdk_bdev *bdev, struct spdk_scsi_task *task)
1513 : : {
1514 : : struct spdk_bdev_scsi_split_ctx *ctx;
1515 : : uint8_t *data;
1516 : 650141 : int desc_count = -1;
1517 : 21 : int data_len;
1518 : :
1519 [ - + ]: 650141 : assert(task->status == SPDK_SCSI_STATUS_GOOD);
1520 : :
1521 : 650141 : ctx = calloc(1, sizeof(*ctx));
1522 [ - + ]: 650141 : if (!ctx) {
1523 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1524 : : SPDK_SCSI_SENSE_NO_SENSE,
1525 : : SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
1526 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1527 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1528 : : }
1529 : :
1530 : 650141 : ctx->task = task;
1531 : 650141 : ctx->current_count = 0;
1532 : 650141 : ctx->outstanding_count = 0;
1533 : 650141 : ctx->fn = _bdev_scsi_unmap;
1534 : :
1535 [ + - ]: 650141 : if (task->iovcnt == 1) {
1536 : 650141 : data = (uint8_t *)task->iovs[0].iov_base;
1537 : 650141 : data_len = task->iovs[0].iov_len;
1538 : 650141 : desc_count = __copy_desc(ctx, data, data_len);
1539 : : } else {
1540 : 0 : data = spdk_scsi_task_gather_data(task, &data_len);
1541 [ # # ]: 0 : if (data) {
1542 : 0 : desc_count = __copy_desc(ctx, data, data_len);
1543 : 0 : free(data);
1544 : : }
1545 : : }
1546 : :
1547 [ + - ]: 650141 : if (desc_count > 0) {
1548 : 650141 : ctx->remaining_count = desc_count;
1549 : 650141 : return bdev_scsi_split(ctx);
1550 : : }
1551 : :
1552 [ # # ]: 0 : if (desc_count < 0) {
1553 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1554 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
1555 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
1556 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1557 : : }
1558 : :
1559 : 0 : free(ctx);
1560 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1561 : : }
1562 : :
1563 : : static int
1564 : 241582 : _bdev_scsi_write_same(struct spdk_bdev_scsi_split_ctx *ctx)
1565 : : {
1566 : 241582 : struct spdk_scsi_task *task = ctx->task;
1567 : 241582 : struct spdk_scsi_lun *lun = task->lun;
1568 : : uint64_t offset_blocks;
1569 : :
1570 : 241582 : offset_blocks = ctx->start_offset_blocks + ctx->current_count;
1571 : 241582 : return spdk_bdev_writev_blocks(lun->bdev_desc, lun->io_channel, task->iovs, task->iovcnt,
1572 : : offset_blocks, 1, bdev_scsi_task_complete_split_cmd, ctx);
1573 : : }
1574 : :
1575 : : static int
1576 : 88 : bdev_scsi_write_same(struct spdk_bdev *bdev, struct spdk_bdev_desc *bdev_desc,
1577 : : struct spdk_io_channel *bdev_ch, struct spdk_scsi_task *task,
1578 : : uint64_t lba, uint32_t xfer_len, uint8_t flags)
1579 : : {
1580 : : struct spdk_bdev_scsi_split_ctx *ctx;
1581 : 34 : uint64_t bdev_num_blocks, offset_blocks, num_blocks;
1582 : : uint32_t max_xfer_len, block_size;
1583 : 88 : int sk = SPDK_SCSI_SENSE_NO_SENSE, asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
1584 : :
1585 : 88 : task->data_transferred = 0;
1586 : :
1587 [ - + ]: 88 : if (spdk_unlikely(task->dxfer_dir != SPDK_SCSI_DIR_TO_DEV)) {
1588 : 0 : SPDK_ERRLOG("Incorrect data direction\n");
1589 : 0 : goto check_condition;
1590 : : }
1591 : :
1592 : 88 : block_size = spdk_bdev_get_data_block_size(bdev);
1593 [ - + ]: 88 : if (spdk_unlikely(task->transfer_len != block_size)) {
1594 : 0 : SPDK_ERRLOG("Incorrect data length(%d), a single logical block(%d) is required\n",
1595 : : task->transfer_len, block_size);
1596 : 0 : goto check_condition;
1597 : : }
1598 : :
1599 [ - + ]: 88 : if (spdk_unlikely(xfer_len == 0)) {
1600 : 0 : task->status = SPDK_SCSI_STATUS_GOOD;
1601 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1602 : : }
1603 : :
1604 : 88 : bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
1605 [ + - - + ]: 88 : if (spdk_unlikely(bdev_num_blocks <= lba || bdev_num_blocks - lba < xfer_len)) {
1606 [ # # # # ]: 0 : SPDK_DEBUGLOG(scsi, "end of media\n");
1607 : 0 : sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
1608 : 0 : asc = SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1609 : 0 : goto check_condition;
1610 : : }
1611 : :
1612 : : /* see MAXIMUM WRITE SAME LENGTH of SPDK_SPC_VPD_BLOCK_LIMITS */
1613 [ - + ]: 88 : max_xfer_len = SPDK_WORK_BLOCK_SIZE / block_size;
1614 [ - + ]: 88 : if (spdk_unlikely(xfer_len > max_xfer_len)) {
1615 : 0 : SPDK_ERRLOG("xfer_len %"PRIu32 " > maximum transfer length %" PRIu32 "\n",
1616 : : xfer_len, max_xfer_len);
1617 : 0 : sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
1618 : 0 : asc = SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB;
1619 : 0 : goto check_condition;
1620 : : }
1621 : :
1622 [ - + ]: 88 : if (_bytes_to_blocks(block_size, task->offset, &offset_blocks,
1623 : 88 : (uint64_t)task->length * xfer_len,
1624 : : &num_blocks) != 0) {
1625 : 0 : SPDK_ERRLOG("task's offset %" PRIu64 " or length %" PRIu32 " is not block multiple\n",
1626 : : task->offset, task->length);
1627 : 0 : goto check_condition;
1628 : : }
1629 : :
1630 : 88 : offset_blocks += lba;
1631 [ - + - + ]: 88 : SPDK_DEBUGLOG(scsi, "Writesame: lba=%"PRIu64", len=%"PRIu64"\n",
1632 : : offset_blocks, num_blocks);
1633 : :
1634 : 88 : ctx = calloc(1, sizeof(*ctx));
1635 [ - + ]: 88 : if (!ctx) {
1636 : 0 : SPDK_ERRLOG("No enough memory on SCSI WRITE SAME\n");
1637 : 0 : goto check_condition;
1638 : : }
1639 : :
1640 : 88 : ctx->task = task;
1641 : 88 : ctx->start_offset_blocks = offset_blocks;
1642 : 88 : ctx->current_count = 0;
1643 : 88 : ctx->outstanding_count = 0;
1644 : 88 : ctx->remaining_count = xfer_len;
1645 : 88 : ctx->fn = _bdev_scsi_write_same;
1646 : :
1647 : 88 : task->data_transferred = task->length;
1648 : :
1649 : 88 : return bdev_scsi_split(ctx);
1650 : :
1651 : 0 : check_condition:
1652 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1653 : : sk, asc, SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1654 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1655 : : }
1656 : :
1657 : : static int
1658 : 9642845 : bdev_scsi_process_block(struct spdk_scsi_task *task)
1659 : : {
1660 : 9642845 : struct spdk_scsi_lun *lun = task->lun;
1661 : 9642845 : struct spdk_bdev *bdev = lun->bdev;
1662 : : uint64_t lba;
1663 : : uint32_t xfer_len;
1664 : 9642845 : uint32_t len = 0;
1665 : 9642845 : uint8_t *cdb = task->cdb;
1666 : :
1667 : : /* XXX: We need to support FUA bit for writes! */
1668 [ - + - + : 9642845 : switch (cdb[0]) {
- + + + +
+ - + ]
1669 : 0 : case SPDK_SBC_READ_6:
1670 : : case SPDK_SBC_WRITE_6:
1671 : 0 : lba = (uint64_t)cdb[1] << 16;
1672 : 0 : lba |= (uint64_t)cdb[2] << 8;
1673 : 0 : lba |= (uint64_t)cdb[3];
1674 : 0 : xfer_len = cdb[4];
1675 [ # # ]: 0 : if (xfer_len == 0) {
1676 : 0 : xfer_len = 256;
1677 : : }
1678 : 0 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1679 : : task, lba, xfer_len,
1680 : 0 : cdb[0] == SPDK_SBC_READ_6, false);
1681 : :
1682 : 7406300 : case SPDK_SBC_READ_10:
1683 : : case SPDK_SBC_WRITE_10:
1684 : 7406300 : lba = from_be32(&cdb[2]);
1685 : 7406300 : xfer_len = from_be16(&cdb[7]);
1686 : 7406300 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1687 : : task, lba, xfer_len,
1688 : 7406300 : cdb[0] == SPDK_SBC_READ_10, false);
1689 : :
1690 : 0 : case SPDK_SBC_READ_12:
1691 : : case SPDK_SBC_WRITE_12:
1692 : 0 : lba = from_be32(&cdb[2]);
1693 : 0 : xfer_len = from_be32(&cdb[6]);
1694 : 0 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1695 : : task, lba, xfer_len,
1696 : 0 : cdb[0] == SPDK_SBC_READ_12, false);
1697 : 1106986 : case SPDK_SBC_READ_16:
1698 : : case SPDK_SBC_WRITE_16:
1699 : 1106986 : lba = from_be64(&cdb[2]);
1700 : 1106986 : xfer_len = from_be32(&cdb[10]);
1701 : 1106986 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1702 : : task, lba, xfer_len,
1703 : 1106986 : cdb[0] == SPDK_SBC_READ_16, false);
1704 : :
1705 : 0 : case SPDK_SBC_COMPARE_AND_WRITE: {
1706 : 0 : uint32_t num_blocks = cdb[13];
1707 : 0 : uint8_t wrprotect = (cdb[1] >> 5) & 0x07;
1708 : 0 : bool dpo = cdb[1] & 0x10;
1709 : 0 : bool fua = cdb[1] & 0x08;
1710 : :
1711 : 0 : lba = from_be64(&cdb[2]);
1712 : :
1713 [ # # # # : 0 : if (dpo || fua || wrprotect) {
# # ]
1714 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1715 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
1716 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
1717 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1718 : 0 : SPDK_ERRLOG("Invalid Task\n");
1719 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1720 : : }
1721 : :
1722 [ # # ]: 0 : if (num_blocks != 1) {
1723 : 0 : SPDK_ERRLOG("Invalid CAW block count, request block count is %u, limit is : 1\n",
1724 : : num_blocks);
1725 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1726 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
1727 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
1728 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1729 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1730 : : }
1731 : :
1732 : 0 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1733 : : task, lba, num_blocks, false, true);
1734 : : }
1735 : :
1736 : 176 : case SPDK_SBC_READ_CAPACITY_10: {
1737 : 176 : uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev);
1738 : 7 : uint8_t buffer[8];
1739 : :
1740 [ + + ]: 176 : if (num_blocks - 1 > 0xffffffffULL) {
1741 [ - + ]: 2 : memset(buffer, 0xff, 4);
1742 : : } else {
1743 : 174 : to_be32(buffer, num_blocks - 1);
1744 : : }
1745 : 176 : to_be32(&buffer[4], spdk_bdev_get_data_block_size(bdev));
1746 : :
1747 : 176 : len = spdk_min(task->length, sizeof(buffer));
1748 [ - + ]: 176 : if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) {
1749 : 0 : break;
1750 : : }
1751 : :
1752 : 176 : task->data_transferred = len;
1753 : 176 : task->status = SPDK_SCSI_STATUS_GOOD;
1754 : 176 : break;
1755 : : }
1756 : :
1757 : 1009 : case SPDK_SPC_SERVICE_ACTION_IN_16:
1758 [ + - ]: 1009 : switch (cdb[1] & 0x1f) { /* SERVICE ACTION */
1759 : 1009 : case SPDK_SBC_SAI_READ_CAPACITY_16: {
1760 : 1009 : uint8_t buffer[32] = {0};
1761 : : uint32_t lbppb, lbppbe;
1762 : :
1763 : 1009 : to_be64(&buffer[0], spdk_bdev_get_num_blocks(bdev) - 1);
1764 : 1009 : to_be32(&buffer[8], spdk_bdev_get_data_block_size(bdev));
1765 [ - + ]: 1009 : lbppb = spdk_bdev_get_physical_block_size(bdev) / spdk_bdev_get_data_block_size(bdev);
1766 : 1009 : lbppbe = spdk_u32log2(lbppb);
1767 [ - + ]: 1009 : if (lbppbe > 0xf) {
1768 : 0 : SPDK_ERRLOG("lbppbe(0x%x) > 0xf\n", lbppbe);
1769 : : } else {
1770 : 1009 : buffer[13] = lbppbe;
1771 : : }
1772 : : /*
1773 : : * Set the TPE bit to 1 to indicate thin provisioning.
1774 : : * The position of TPE bit is the 7th bit in 14th byte
1775 : : * in READ CAPACITY (16) parameter data.
1776 : : */
1777 [ + + ]: 1009 : if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
1778 : 999 : buffer[14] |= 1 << 7;
1779 : : }
1780 : :
1781 [ - + ]: 1009 : len = spdk_min(from_be32(&cdb[10]), sizeof(buffer));
1782 [ - + ]: 1009 : if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) {
1783 : 0 : break;
1784 : : }
1785 : :
1786 : 1009 : task->data_transferred = len;
1787 : 1009 : task->status = SPDK_SCSI_STATUS_GOOD;
1788 : 1009 : break;
1789 : : }
1790 : :
1791 : 0 : default:
1792 : 0 : return SPDK_SCSI_TASK_UNKNOWN;
1793 : : }
1794 : 957 : break;
1795 : :
1796 : 465823 : case SPDK_SBC_SYNCHRONIZE_CACHE_10:
1797 : : case SPDK_SBC_SYNCHRONIZE_CACHE_16:
1798 [ + + ]: 465823 : if (cdb[0] == SPDK_SBC_SYNCHRONIZE_CACHE_10) {
1799 : 49 : lba = from_be32(&cdb[2]);
1800 : 49 : len = from_be16(&cdb[7]);
1801 : : } else {
1802 : 465774 : lba = from_be64(&cdb[2]);
1803 : 465774 : len = from_be32(&cdb[10]);
1804 : : }
1805 : :
1806 [ + + ]: 465823 : if (len == 0) {
1807 : 49 : len = spdk_bdev_get_num_blocks(bdev) - lba;
1808 : : }
1809 : :
1810 : 465823 : return bdev_scsi_sync(bdev, lun->bdev_desc, lun->io_channel, task, lba, len);
1811 : : break;
1812 : :
1813 : 650141 : case SPDK_SBC_UNMAP:
1814 : 650141 : return bdev_scsi_unmap(bdev, task);
1815 : :
1816 : 88 : case SPDK_SBC_WRITE_SAME_10:
1817 : 88 : lba = from_be32(&cdb[2]);
1818 : 88 : xfer_len = from_be16(&cdb[7]);
1819 : 88 : return bdev_scsi_write_same(bdev, lun->bdev_desc, lun->io_channel,
1820 : 88 : task, lba, xfer_len, cdb[1]);
1821 : :
1822 : 0 : case SPDK_SBC_WRITE_SAME_16:
1823 : 0 : lba = from_be64(&cdb[2]);
1824 : 0 : xfer_len = from_be32(&cdb[10]);
1825 : 0 : return bdev_scsi_write_same(bdev, lun->bdev_desc, lun->io_channel,
1826 : 0 : task, lba, xfer_len, cdb[1]);
1827 : :
1828 : :
1829 : 12322 : default:
1830 : 12322 : return SPDK_SCSI_TASK_UNKNOWN;
1831 : : }
1832 : :
1833 : 1185 : return SPDK_SCSI_TASK_COMPLETE;
1834 : : }
1835 : :
1836 : : static void
1837 : 140874 : bdev_scsi_process_block_resubmit(void *arg)
1838 : : {
1839 : 140874 : struct spdk_scsi_task *task = arg;
1840 : :
1841 : 140874 : bdev_scsi_process_block(task);
1842 : 140874 : }
1843 : :
1844 : : static int
1845 : 147 : bdev_scsi_check_len(struct spdk_scsi_task *task, int len, int min_len)
1846 : : {
1847 [ + - ]: 147 : if (len >= min_len) {
1848 : 147 : return 0;
1849 : : }
1850 : :
1851 : : /* INVALID FIELD IN CDB */
1852 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1853 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
1854 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
1855 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1856 : 0 : return -1;
1857 : : }
1858 : :
1859 : : static int
1860 : 12322 : bdev_scsi_process_primary(struct spdk_scsi_task *task)
1861 : : {
1862 : 12322 : struct spdk_scsi_lun *lun = task->lun;
1863 : 12322 : struct spdk_bdev *bdev = lun->bdev;
1864 : 12322 : int alloc_len = -1;
1865 : 12322 : int data_len = -1;
1866 : 12322 : uint8_t *cdb = task->cdb;
1867 : 12322 : uint8_t *data = NULL;
1868 : 12322 : int rc = 0;
1869 : 12322 : int pllen, md = 0;
1870 : : int llba;
1871 : : int dbd, pc, page, subpage;
1872 : 12322 : int cmd_parsed = 0;
1873 : :
1874 [ + + + + : 12322 : switch (cdb[0]) {
+ - - - +
- - - - -
+ ]
1875 : 7834 : case SPDK_SPC_INQUIRY:
1876 : 7834 : alloc_len = from_be16(&cdb[3]);
1877 : 7834 : data_len = spdk_max(4096, alloc_len);
1878 : 7834 : data = calloc(1, data_len);
1879 [ - + ]: 7834 : assert(data != NULL);
1880 : 7834 : rc = bdev_scsi_inquiry(bdev, task, cdb, data, data_len);
1881 : 7834 : data_len = spdk_min(rc, data_len);
1882 [ + + ]: 7834 : if (rc < 0) {
1883 : 868 : break;
1884 : : }
1885 : :
1886 [ - + - + ]: 6966 : SPDK_LOGDUMP(scsi, "INQUIRY", data, data_len);
1887 : 6966 : break;
1888 : :
1889 : 139 : case SPDK_SPC_REPORT_LUNS: {
1890 : : int sel;
1891 : :
1892 : 139 : sel = cdb[2];
1893 [ - + - + ]: 139 : SPDK_DEBUGLOG(scsi, "sel=%x\n", sel);
1894 : :
1895 : 139 : alloc_len = from_be32(&cdb[6]);
1896 : 139 : rc = bdev_scsi_check_len(task, alloc_len, 16);
1897 [ - + ]: 139 : if (rc < 0) {
1898 : 0 : break;
1899 : : }
1900 : :
1901 : 139 : data_len = spdk_max(4096, alloc_len);
1902 : 139 : data = calloc(1, data_len);
1903 [ - + ]: 139 : assert(data != NULL);
1904 : 139 : rc = bdev_scsi_report_luns(task->lun, sel, data, data_len);
1905 : 139 : data_len = rc;
1906 [ - + ]: 139 : if (rc < 0) {
1907 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1908 : : SPDK_SCSI_SENSE_NO_SENSE,
1909 : : SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
1910 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1911 : 0 : break;
1912 : : }
1913 : :
1914 [ - + - + ]: 139 : SPDK_LOGDUMP(scsi, "REPORT LUNS", data, data_len);
1915 : 139 : break;
1916 : : }
1917 : :
1918 : 8 : case SPDK_SPC_MODE_SELECT_6:
1919 : : case SPDK_SPC_MODE_SELECT_10:
1920 [ + - ]: 8 : if (cdb[0] == SPDK_SPC_MODE_SELECT_6) {
1921 : : /* MODE_SELECT(6) must have at least a 4 byte header. */
1922 : 8 : md = 4;
1923 : 8 : pllen = cdb[4];
1924 : : } else {
1925 : : /* MODE_SELECT(10) must have at least an 8 byte header. */
1926 : 0 : md = 8;
1927 : 0 : pllen = from_be16(&cdb[7]);
1928 : : }
1929 : :
1930 [ + + ]: 8 : if (pllen == 0) {
1931 : 4 : break;
1932 : : }
1933 : :
1934 : 4 : rc = bdev_scsi_check_len(task, pllen, md);
1935 [ - + ]: 4 : if (rc < 0) {
1936 : 0 : break;
1937 : : }
1938 : :
1939 : 4 : data = spdk_scsi_task_gather_data(task, &rc);
1940 [ - + ]: 4 : if (rc < 0) {
1941 : 0 : break;
1942 : : }
1943 : 4 : data_len = rc;
1944 : :
1945 : 4 : rc = bdev_scsi_check_len(task, data_len, spdk_max(pllen, md));
1946 [ - + ]: 4 : if (rc < 0) {
1947 : 0 : break;
1948 : : }
1949 : :
1950 : 4 : rc = pllen;
1951 : 4 : data_len = 0;
1952 : 4 : break;
1953 : :
1954 : 3001 : case SPDK_SPC_MODE_SENSE_6:
1955 : 3001 : alloc_len = cdb[4];
1956 : 3001 : md = 6;
1957 : : /* FALLTHROUGH */
1958 : 3005 : case SPDK_SPC_MODE_SENSE_10:
1959 : 3005 : llba = 0;
1960 : :
1961 [ + + ]: 3005 : if (md == 0) {
1962 : 4 : alloc_len = from_be16(&cdb[7]);
1963 : 4 : llba = !!(cdb[1] & 0x10);
1964 : 4 : md = 10;
1965 : : }
1966 : :
1967 : 3005 : dbd = !!(cdb[1] & 0x8);
1968 : 3005 : pc = (cdb[2] & 0xc0) >> 6;
1969 : 3005 : page = cdb[2] & 0x3f;
1970 : 3005 : subpage = cdb[3];
1971 : :
1972 : : /* First call with no buffer to discover needed buffer size */
1973 : 3005 : rc = bdev_scsi_mode_sense(bdev, md,
1974 : : cdb, dbd, llba, pc,
1975 : : page, subpage,
1976 : : NULL, task);
1977 [ - + ]: 3005 : if (rc < 0) {
1978 : 0 : break;
1979 : : }
1980 : :
1981 : 3005 : data_len = rc;
1982 : 3005 : data = calloc(1, data_len);
1983 [ - + ]: 3005 : assert(data != NULL);
1984 : :
1985 : : /* First call with no buffer to discover needed buffer size */
1986 : 3005 : rc = bdev_scsi_mode_sense(bdev, md,
1987 : : cdb, dbd, llba, pc,
1988 : : page, subpage,
1989 : : data, task);
1990 [ - + ]: 3005 : if (rc < 0) {
1991 : : /* INVALID FIELD IN CDB */
1992 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1993 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
1994 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
1995 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1996 : 0 : break;
1997 : : }
1998 : 3005 : break;
1999 : :
2000 : 0 : case SPDK_SPC_REQUEST_SENSE: {
2001 : : int desc;
2002 : : int sk, asc, ascq;
2003 : :
2004 : 0 : desc = cdb[1] & 0x1;
2005 [ # # ]: 0 : if (desc != 0) {
2006 : : /* INVALID FIELD IN CDB */
2007 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
2008 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
2009 : : SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
2010 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
2011 : 0 : break;
2012 : : }
2013 : :
2014 : 0 : alloc_len = cdb[4];
2015 : :
2016 : : /* NO ADDITIONAL SENSE INFORMATION */
2017 : 0 : sk = SPDK_SCSI_SENSE_NO_SENSE;
2018 : 0 : asc = 0x00;
2019 : 0 : ascq = 0x00;
2020 : :
2021 : 0 : spdk_scsi_task_build_sense_data(task, sk, asc, ascq);
2022 : :
2023 : 0 : data_len = task->sense_data_len;
2024 : 0 : data = calloc(1, data_len);
2025 [ # # ]: 0 : assert(data != NULL);
2026 [ # # # # ]: 0 : memcpy(data, task->sense_data, data_len);
2027 : 0 : break;
2028 : : }
2029 : :
2030 : 0 : case SPDK_SPC_LOG_SELECT:
2031 [ # # # # ]: 0 : SPDK_DEBUGLOG(scsi, "LOG_SELECT\n");
2032 : 0 : cmd_parsed = 1;
2033 : : /* FALLTHROUGH */
2034 : 0 : case SPDK_SPC_LOG_SENSE:
2035 [ # # ]: 0 : if (!cmd_parsed) {
2036 [ # # # # ]: 0 : SPDK_DEBUGLOG(scsi, "LOG_SENSE\n");
2037 : : }
2038 : :
2039 : : /* INVALID COMMAND OPERATION CODE */
2040 : 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
2041 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
2042 : : SPDK_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
2043 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
2044 : 0 : rc = -1;
2045 : 0 : break;
2046 : :
2047 : 1194 : case SPDK_SPC_TEST_UNIT_READY:
2048 [ - + - + ]: 1194 : SPDK_DEBUGLOG(scsi, "TEST_UNIT_READY\n");
2049 : 1194 : cmd_parsed = 1;
2050 : : /* FALLTHROUGH */
2051 : 1194 : case SPDK_SBC_START_STOP_UNIT:
2052 [ - + ]: 1194 : if (!cmd_parsed) {
2053 [ # # # # ]: 0 : SPDK_DEBUGLOG(scsi, "START_STOP_UNIT\n");
2054 : : }
2055 : :
2056 : 1194 : rc = 0;
2057 : 1194 : break;
2058 : :
2059 : 0 : case SPDK_SPC_PERSISTENT_RESERVE_OUT:
2060 : 0 : pllen = from_be32(&cdb[5]);
2061 : 0 : rc = bdev_scsi_check_len(task, pllen, 24);
2062 [ # # ]: 0 : if (rc < 0) {
2063 : 0 : break;
2064 : : }
2065 : :
2066 : 0 : data = spdk_scsi_task_gather_data(task, &rc);
2067 [ # # ]: 0 : if (rc < 0) {
2068 : 0 : break;
2069 : : }
2070 : 0 : data_len = rc;
2071 [ # # ]: 0 : if (data_len < 24) {
2072 : 0 : rc = -1;
2073 : 0 : break;
2074 : : }
2075 : :
2076 : 0 : rc = scsi_pr_out(task, cdb, data, data_len);
2077 [ # # ]: 0 : if (rc < 0) {
2078 : 0 : break;
2079 : : }
2080 : 0 : rc = pllen;
2081 : 0 : data_len = 0;
2082 : 0 : break;
2083 : :
2084 : 0 : case SPDK_SPC_PERSISTENT_RESERVE_IN:
2085 : 0 : alloc_len = from_be16(&cdb[7]);
2086 : 0 : data_len = alloc_len;
2087 : 0 : data = calloc(1, data_len);
2088 [ # # ]: 0 : assert(data != NULL);
2089 : 0 : rc = scsi_pr_in(task, cdb, data, data_len);
2090 : 0 : break;
2091 : :
2092 : 0 : case SPDK_SPC2_RESERVE_6:
2093 : : case SPDK_SPC2_RESERVE_10:
2094 : 0 : rc = scsi2_reserve(task, cdb);
2095 [ # # ]: 0 : if (rc == 0) {
2096 [ # # ]: 0 : if (cdb[0] == SPDK_SPC2_RESERVE_10) {
2097 : 0 : rc = from_be16(&cdb[7]);
2098 : : }
2099 : 0 : data_len = 0;
2100 : : }
2101 : 0 : break;
2102 : :
2103 : 0 : case SPDK_SPC2_RELEASE_6:
2104 : : case SPDK_SPC2_RELEASE_10:
2105 : 0 : rc = scsi2_release(task);
2106 : 0 : break;
2107 : :
2108 : 142 : default:
2109 : 142 : return SPDK_SCSI_TASK_UNKNOWN;
2110 : : }
2111 : :
2112 [ + + + + ]: 12180 : if (rc >= 0 && data_len > 0) {
2113 [ - + ]: 10110 : assert(alloc_len >= 0);
2114 : 10110 : spdk_scsi_task_scatter_data(task, data, spdk_min(alloc_len, data_len));
2115 : 10110 : rc = spdk_min(data_len, alloc_len);
2116 : : }
2117 : :
2118 [ + + ]: 12180 : if (rc >= 0) {
2119 : 11312 : task->data_transferred = rc;
2120 : 11312 : task->status = SPDK_SCSI_STATUS_GOOD;
2121 : : }
2122 : :
2123 [ + + ]: 12180 : if (data) {
2124 : 10982 : free(data);
2125 : : }
2126 : :
2127 : 12180 : return SPDK_SCSI_TASK_COMPLETE;
2128 : : }
2129 : :
2130 : : int
2131 : 9501971 : bdev_scsi_execute(struct spdk_scsi_task *task)
2132 : : {
2133 : : int rc;
2134 : :
2135 [ + + ]: 9501971 : if ((rc = bdev_scsi_process_block(task)) == SPDK_SCSI_TASK_UNKNOWN) {
2136 [ + + ]: 12322 : if ((rc = bdev_scsi_process_primary(task)) == SPDK_SCSI_TASK_UNKNOWN) {
2137 [ - + - + ]: 142 : SPDK_DEBUGLOG(scsi, "unsupported SCSI OP=0x%x\n", task->cdb[0]);
2138 : : /* INVALID COMMAND OPERATION CODE */
2139 : 142 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
2140 : : SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
2141 : : SPDK_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
2142 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
2143 : 142 : return SPDK_SCSI_TASK_COMPLETE;
2144 : : }
2145 : : }
2146 : :
2147 : 9501829 : return rc;
2148 : : }
2149 : :
2150 : : static void
2151 : 0 : bdev_scsi_reset_resubmit(void *arg)
2152 : : {
2153 : 0 : struct spdk_scsi_task *task = arg;
2154 : :
2155 : 0 : bdev_scsi_reset(task);
2156 : 0 : }
2157 : :
2158 : : void
2159 : 6 : bdev_scsi_reset(struct spdk_scsi_task *task)
2160 : : {
2161 : 6 : struct spdk_scsi_lun *lun = task->lun;
2162 : : int rc;
2163 : :
2164 : 6 : rc = spdk_bdev_reset(lun->bdev_desc, lun->io_channel, bdev_scsi_task_complete_reset,
2165 : : task);
2166 [ - + ]: 6 : if (rc == -ENOMEM) {
2167 : 0 : bdev_scsi_queue_io(task, bdev_scsi_reset_resubmit, task);
2168 : : }
2169 : 6 : }
2170 : :
2171 : : bool
2172 : 5945770 : bdev_scsi_get_dif_ctx(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
2173 : : struct spdk_dif_ctx *dif_ctx)
2174 : : {
2175 : 5945770 : uint32_t ref_tag = 0, dif_check_flags = 0, data_offset;
2176 : : uint8_t *cdb;
2177 : : int rc;
2178 : 12 : struct spdk_dif_ctx_init_ext_opts dif_opts;
2179 : :
2180 [ + + ]: 5945770 : if (spdk_likely(spdk_bdev_get_md_size(bdev) == 0)) {
2181 : 5945758 : return false;
2182 : : }
2183 : :
2184 : 12 : cdb = task->cdb;
2185 : 12 : data_offset = task->offset;
2186 : :
2187 : : /* We use lower 32 bits of LBA as Reference. Tag */
2188 [ + + + - ]: 12 : switch (cdb[0]) {
2189 : 4 : case SPDK_SBC_READ_6:
2190 : : case SPDK_SBC_WRITE_6:
2191 : 4 : ref_tag = (uint32_t)cdb[1] << 16;
2192 : 4 : ref_tag |= (uint32_t)cdb[2] << 8;
2193 : 4 : ref_tag |= (uint32_t)cdb[3];
2194 : 4 : break;
2195 : 4 : case SPDK_SBC_READ_10:
2196 : : case SPDK_SBC_WRITE_10:
2197 : : case SPDK_SBC_READ_12:
2198 : : case SPDK_SBC_WRITE_12:
2199 : 4 : ref_tag = from_be32(&cdb[2]);
2200 : 4 : break;
2201 : 4 : case SPDK_SBC_READ_16:
2202 : : case SPDK_SBC_WRITE_16:
2203 : 4 : ref_tag = (uint32_t)from_be64(&cdb[2]);
2204 : 4 : break;
2205 : 0 : default:
2206 : 0 : return false;
2207 : : }
2208 : :
2209 [ - + ]: 12 : if (spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_REFTAG)) {
2210 : 0 : dif_check_flags |= SPDK_DIF_FLAGS_REFTAG_CHECK;
2211 : : }
2212 : :
2213 [ - + ]: 12 : if (spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_GUARD)) {
2214 : 0 : dif_check_flags |= SPDK_DIF_FLAGS_GUARD_CHECK;
2215 : : }
2216 : :
2217 : 12 : dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
2218 : 12 : dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
2219 : 24 : rc = spdk_dif_ctx_init(dif_ctx,
2220 : : spdk_bdev_get_block_size(bdev),
2221 : : spdk_bdev_get_md_size(bdev),
2222 : 12 : spdk_bdev_is_md_interleaved(bdev),
2223 : 12 : spdk_bdev_is_dif_head_of_md(bdev),
2224 : : spdk_bdev_get_dif_type(bdev),
2225 : : dif_check_flags,
2226 : : ref_tag, 0, 0, data_offset, 0, &dif_opts);
2227 : :
2228 : 12 : return (rc == 0) ? true : false;
2229 : : }
|