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 0 : bdev_scsi_set_naa_ieee_extended(const char *name, uint8_t *buf)
33 : {
34 0 : int i;
35 0 : uint64_t local_value = 0, id_a, seed = 131;
36 :
37 0 : for (i = 0; name[i] != '\0'; i++) {
38 0 : local_value = (local_value * seed) + name[i];
39 0 : }
40 :
41 : /*
42 : * see spc3r23 7.6.3.6.2,
43 : * NAA IEEE Extended identifier format
44 : */
45 0 : id_a = local_value & 0x0000000fff000000ull;
46 0 : id_a = id_a << 24;
47 :
48 0 : local_value &= 0x0000000000ffffffull;
49 : /* NAA 02, and 00 03 47 for IEEE Intel */
50 0 : local_value |= 0x2000000347000000ull;
51 0 : local_value |= id_a;
52 :
53 0 : to_be64((void *)buf, local_value);
54 0 : }
55 :
56 : static int
57 0 : bdev_scsi_report_luns(struct spdk_scsi_lun *lun,
58 : int sel, uint8_t *data, int alloc_len)
59 : {
60 0 : struct spdk_scsi_dev *dev;
61 0 : struct spdk_scsi_lun *tmp_lun;
62 0 : uint64_t fmt_lun;
63 0 : int hlen, len = 0;
64 :
65 0 : if (alloc_len < 8) {
66 0 : return -1;
67 : }
68 :
69 0 : 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 0 : } else {
76 0 : return -1;
77 : }
78 :
79 : /* LUN LIST LENGTH */
80 0 : memset(data, 0, 4);
81 :
82 : /* Reserved */
83 0 : memset(&data[4], 0, 4);
84 0 : hlen = 8;
85 :
86 0 : dev = lun->dev;
87 :
88 0 : for (tmp_lun = spdk_scsi_dev_get_first_lun(dev); tmp_lun != NULL;
89 0 : tmp_lun = spdk_scsi_dev_get_next_lun(tmp_lun)) {
90 0 : if (alloc_len - (hlen + len) < 8) {
91 0 : return -1;
92 : }
93 :
94 0 : fmt_lun = spdk_scsi_lun_id_int_to_fmt(tmp_lun->id);
95 :
96 : /* LUN */
97 0 : to_be64(&data[hlen + len], fmt_lun);
98 0 : len += 8;
99 0 : }
100 :
101 : /* LUN LIST LENGTH */
102 0 : to_be32(data, len);
103 :
104 0 : return hlen + len;
105 0 : }
106 :
107 : static int
108 3 : bdev_scsi_pad_scsi_name(char *dst, const char *name)
109 : {
110 3 : size_t len;
111 :
112 3 : len = strlen(name);
113 3 : memcpy(dst, name, len);
114 3 : do {
115 6 : dst[len++] = '\0';
116 6 : } while (len & 3);
117 :
118 6 : return len;
119 3 : }
120 :
121 : static int
122 258 : 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 258 : struct spdk_scsi_lun *lun;
126 258 : struct spdk_scsi_dev *dev;
127 258 : struct spdk_scsi_port *port;
128 258 : uint32_t blocks, optimal_blocks;
129 258 : int hlen = 0, plen, plen2;
130 258 : uint16_t len = 0;
131 258 : int pc;
132 258 : int pd;
133 258 : int evpd;
134 258 : int i;
135 258 : struct spdk_scsi_cdb_inquiry *inq = (struct spdk_scsi_cdb_inquiry *)cdb;
136 :
137 : /* standard inquiry command at lease with 36 Bytes */
138 258 : if (alloc_len < 0x24) {
139 0 : goto inq_error;
140 : }
141 :
142 258 : lun = task->lun;
143 258 : dev = lun->dev;
144 258 : port = task->target_port;
145 :
146 258 : pd = SPDK_SPC_PERIPHERAL_DEVICE_TYPE_DISK;
147 258 : pc = inq->page_code;
148 258 : evpd = inq->evpd & 0x1;
149 :
150 258 : if (!evpd && pc) {
151 1 : 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 1 : return -1;
156 : }
157 :
158 257 : if (evpd) {
159 0 : struct spdk_scsi_vpd_page *vpage = (struct spdk_scsi_vpd_page *)data;
160 :
161 : /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
162 0 : vpage->peripheral_device_type = pd;
163 0 : vpage->peripheral_qualifier = SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED;
164 : /* PAGE CODE */
165 0 : vpage->page_code = pc;
166 :
167 : /* Vital product data */
168 0 : switch (pc) {
169 : case SPDK_SPC_VPD_SUPPORTED_VPD_PAGES:
170 0 : hlen = 4;
171 :
172 0 : vpage->params[0] = SPDK_SPC_VPD_SUPPORTED_VPD_PAGES;
173 0 : vpage->params[1] = SPDK_SPC_VPD_UNIT_SERIAL_NUMBER;
174 0 : vpage->params[2] = SPDK_SPC_VPD_DEVICE_IDENTIFICATION;
175 0 : vpage->params[3] = SPDK_SPC_VPD_MANAGEMENT_NETWORK_ADDRESSES;
176 0 : vpage->params[4] = SPDK_SPC_VPD_EXTENDED_INQUIRY_DATA;
177 0 : vpage->params[5] = SPDK_SPC_VPD_MODE_PAGE_POLICY;
178 0 : vpage->params[6] = SPDK_SPC_VPD_SCSI_PORTS;
179 0 : vpage->params[7] = SPDK_SPC_VPD_BLOCK_LIMITS;
180 0 : vpage->params[8] = SPDK_SPC_VPD_BLOCK_DEV_CHARS;
181 0 : len = 9;
182 0 : if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
183 0 : vpage->params[9] = SPDK_SPC_VPD_BLOCK_THIN_PROVISION;
184 0 : len++;
185 0 : }
186 :
187 : /* PAGE LENGTH */
188 0 : to_be16(vpage->alloc_len, len);
189 0 : break;
190 :
191 : case SPDK_SPC_VPD_UNIT_SERIAL_NUMBER: {
192 0 : const char *name = spdk_bdev_get_name(bdev);
193 :
194 0 : hlen = 4;
195 :
196 : /* PRODUCT SERIAL NUMBER */
197 0 : len = strlen(name) + 1;
198 0 : if (len > MAX_SERIAL_STRING) {
199 0 : len = MAX_SERIAL_STRING;
200 0 : }
201 :
202 0 : memcpy(vpage->params, name, len - 1);
203 0 : vpage->params[len - 1] = 0;
204 :
205 : /* PAGE LENGTH */
206 0 : to_be16(vpage->alloc_len, len);
207 : break;
208 0 : }
209 :
210 : case SPDK_SPC_VPD_DEVICE_IDENTIFICATION: {
211 0 : const char *name = spdk_bdev_get_name(bdev);
212 0 : const char *product_name = spdk_bdev_get_product_name(bdev);
213 0 : uint8_t protocol_id = dev->protocol_id;
214 0 : uint8_t *buf = vpage->params;
215 0 : struct spdk_scsi_desig_desc *desig;
216 :
217 0 : hlen = 4;
218 :
219 : /* Check total length by calculated how much space all entries take */
220 0 : len = sizeof(struct spdk_scsi_desig_desc) + 8;
221 0 : len += sizeof(struct spdk_scsi_desig_desc) + 8 + 16 + MAX_SERIAL_STRING;
222 0 : len += sizeof(struct spdk_scsi_desig_desc) + SPDK_SCSI_DEV_MAX_NAME + 1;
223 0 : len += sizeof(struct spdk_scsi_desig_desc) + SPDK_SCSI_PORT_MAX_NAME_LENGTH;
224 0 : len += sizeof(struct spdk_scsi_desig_desc) + 4;
225 0 : len += sizeof(struct spdk_scsi_desig_desc) + 4;
226 0 : len += sizeof(struct spdk_scsi_desig_desc) + 4;
227 0 : 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 0 : desig = (struct spdk_scsi_desig_desc *)buf;
239 0 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
240 0 : desig->protocol_id = protocol_id;
241 0 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_NAA;
242 0 : desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
243 0 : desig->reserved0 = 0;
244 0 : desig->piv = 1;
245 0 : desig->reserved1 = 0;
246 0 : desig->len = 8;
247 0 : bdev_scsi_set_naa_ieee_extended(name, desig->desig);
248 0 : len = sizeof(struct spdk_scsi_desig_desc) + 8;
249 :
250 0 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
251 :
252 : /* T10 Vendor ID designator */
253 0 : desig = (struct spdk_scsi_desig_desc *)buf;
254 0 : desig->code_set = SPDK_SPC_VPD_CODE_SET_ASCII;
255 0 : desig->protocol_id = protocol_id;
256 0 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_T10_VENDOR_ID;
257 0 : desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
258 0 : desig->reserved0 = 0;
259 0 : desig->piv = 1;
260 0 : desig->reserved1 = 0;
261 0 : desig->len = 8 + 16 + MAX_SERIAL_STRING;
262 0 : spdk_strcpy_pad(desig->desig, DEFAULT_DISK_VENDOR, 8, ' ');
263 0 : spdk_strcpy_pad(&desig->desig[8], product_name, 16, ' ');
264 0 : spdk_strcpy_pad(&desig->desig[24], name, MAX_SERIAL_STRING, ' ');
265 0 : len += sizeof(struct spdk_scsi_desig_desc) + 8 + 16 + MAX_SERIAL_STRING;
266 :
267 0 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
268 :
269 : /* SCSI Device Name designator */
270 0 : desig = (struct spdk_scsi_desig_desc *)buf;
271 0 : desig->code_set = SPDK_SPC_VPD_CODE_SET_UTF8;
272 0 : desig->protocol_id = protocol_id;
273 0 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
274 0 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_DEVICE;
275 0 : desig->reserved0 = 0;
276 0 : desig->piv = 1;
277 0 : desig->reserved1 = 0;
278 0 : desig->len = bdev_scsi_pad_scsi_name(desig->desig, dev->name);
279 0 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
280 :
281 0 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
282 :
283 : /* SCSI Port Name designator */
284 0 : desig = (struct spdk_scsi_desig_desc *)buf;
285 0 : desig->code_set = SPDK_SPC_VPD_CODE_SET_UTF8;
286 0 : desig->protocol_id = protocol_id;
287 0 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
288 0 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
289 0 : desig->reserved0 = 0;
290 0 : desig->piv = 1;
291 0 : desig->reserved1 = 0;
292 0 : desig->len = snprintf(desig->desig, SPDK_SCSI_PORT_MAX_NAME_LENGTH, "%s", port->name);
293 0 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
294 :
295 0 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
296 :
297 : /* Relative Target Port designator */
298 0 : desig = (struct spdk_scsi_desig_desc *)buf;
299 0 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
300 0 : desig->protocol_id = protocol_id;
301 0 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_RELATIVE_TARGET_PORT;
302 0 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
303 0 : desig->reserved0 = 0;
304 0 : desig->piv = 1;
305 0 : desig->reserved1 = 0;
306 0 : desig->len = 4;
307 0 : memset(desig->desig, 0, 2); /* Reserved */
308 0 : to_be16(&desig->desig[2], port->index);
309 0 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
310 :
311 0 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
312 :
313 : /* Target port group designator */
314 0 : desig = (struct spdk_scsi_desig_desc *)buf;
315 0 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
316 0 : desig->protocol_id = protocol_id;
317 0 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_TARGET_PORT_GROUP;
318 0 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
319 0 : desig->reserved0 = 0;
320 0 : desig->piv = 1;
321 0 : desig->reserved1 = 0;
322 0 : desig->len = 4;
323 0 : memset(desig->desig, 0, 4);
324 0 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
325 :
326 0 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
327 :
328 : /* Logical unit group designator */
329 0 : desig = (struct spdk_scsi_desig_desc *)buf;
330 0 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
331 0 : desig->protocol_id = protocol_id;
332 0 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_LOGICAL_UNIT_GROUP;
333 0 : desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
334 0 : desig->reserved0 = 0;
335 0 : desig->piv = 1;
336 0 : desig->reserved1 = 0;
337 0 : desig->len = 4;
338 0 : memset(desig->desig, 0, 2); /* Reserved */
339 0 : to_be16(&desig->desig[2], dev->id);
340 0 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
341 :
342 0 : to_be16(vpage->alloc_len, len);
343 :
344 0 : break;
345 0 : }
346 :
347 : 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 : break;
367 0 : }
368 :
369 : 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 : case SPDK_SPC_VPD_MODE_PAGE_POLICY: {
377 0 : struct spdk_scsi_mpage_policy_desc *pdesc =
378 0 : (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 : break;
403 0 : }
404 :
405 : 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 0 : struct spdk_scsi_port_desc *sdesc;
412 0 : 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 0 : 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 0 : 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 0 : }
471 :
472 0 : to_be16(vpage->alloc_len, len);
473 0 : break;
474 : }
475 :
476 : case SPDK_SPC_VPD_BLOCK_LIMITS: {
477 0 : uint32_t block_size = spdk_bdev_get_data_block_size(bdev);
478 :
479 : /* PAGE LENGTH */
480 0 : memset(&data[4], 0, 60);
481 :
482 0 : hlen = 4;
483 :
484 : /* WSNZ(0) */
485 : /* support zero length in WRITE SAME */
486 :
487 : /* MAXIMUM COMPARE AND WRITE LENGTH */
488 0 : blocks = SPDK_WORK_ATS_BLOCK_SIZE / block_size;
489 :
490 0 : if (blocks > 0xff) {
491 0 : blocks = 0xff;
492 0 : }
493 :
494 0 : data[5] = (uint8_t)blocks;
495 :
496 : /* force align to 4KB */
497 0 : if (block_size < 4096) {
498 0 : optimal_blocks = 4096 / block_size;
499 0 : } else {
500 0 : optimal_blocks = 1;
501 : }
502 :
503 : /* OPTIMAL TRANSFER LENGTH GRANULARITY */
504 0 : to_be16(&data[6], optimal_blocks);
505 :
506 0 : blocks = SPDK_WORK_BLOCK_SIZE / block_size;
507 :
508 : /* MAXIMUM TRANSFER LENGTH */
509 0 : to_be32(&data[8], blocks);
510 : /* OPTIMAL TRANSFER LENGTH */
511 0 : to_be32(&data[12], blocks);
512 :
513 : /* MAXIMUM PREFETCH XDREAD XDWRITE TRANSFER LENGTH */
514 :
515 0 : 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 0 : 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 0 : 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 0 : }
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 0 : to_be64(&data[36], blocks);
549 :
550 : /* Reserved */
551 : /* not specified */
552 0 : len = 64 - hlen;
553 :
554 0 : to_be16(vpage->alloc_len, len);
555 : break;
556 0 : }
557 :
558 : case SPDK_SPC_VPD_BLOCK_DEV_CHARS: {
559 : /* PAGE LENGTH */
560 0 : hlen = 4;
561 0 : len = 64 - hlen;
562 :
563 0 : to_be16(&data[4], DEFAULT_DISK_ROTATION_RATE);
564 :
565 : /* Reserved */
566 0 : data[6] = 0;
567 : /* NOMINAL FORM FACTOR(3-0) */
568 0 : data[7] = DEFAULT_DISK_FORM_FACTOR << 4;
569 : /* Reserved */
570 0 : memset(&data[8], 0, 64 - 8);
571 :
572 0 : to_be16(vpage->alloc_len, len);
573 0 : break;
574 : }
575 :
576 : case SPDK_SPC_VPD_BLOCK_THIN_PROVISION: {
577 0 : if (!spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
578 0 : goto inq_error;
579 : }
580 :
581 0 : hlen = 4;
582 0 : 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 0 : 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 0 : data[4] = 0;
596 :
597 : /*
598 : * Set the LBPU bit to indicate the support for UNMAP
599 : * command.
600 : */
601 0 : data[5] |= SPDK_SCSI_UNMAP_LBPU;
602 :
603 : /*
604 : * Set the provisioning type to thin provision.
605 : */
606 0 : data[6] = SPDK_SCSI_UNMAP_THIN_PROVISIONING;
607 :
608 0 : to_be16(vpage->alloc_len, len);
609 0 : break;
610 : }
611 :
612 : default:
613 0 : if (pc >= 0xc0 && pc <= 0xff) {
614 0 : SPDK_DEBUGLOG(scsi, "Vendor specific INQUIRY VPD page 0x%x\n", pc);
615 0 : } else {
616 0 : SPDK_NOTICELOG("unsupported INQUIRY VPD page 0x%x\n", pc);
617 : }
618 0 : goto inq_error;
619 : }
620 0 : } else {
621 514 : struct spdk_scsi_cdb_inquiry_data *inqdata =
622 257 : (struct spdk_scsi_cdb_inquiry_data *)data;
623 :
624 : /* Standard INQUIRY data */
625 : /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
626 257 : inqdata->peripheral_device_type = pd;
627 257 : inqdata->peripheral_qualifier = SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED;
628 :
629 : /* RMB(7) */
630 257 : inqdata->rmb = 0;
631 :
632 : /* VERSION */
633 : /* See SPC3/SBC2/MMC4/SAM2 for more details */
634 257 : inqdata->version = SPDK_SPC_VERSION_SPC3;
635 :
636 : /* NORMACA(5) HISUP(4) RESPONSE DATA FORMAT(3-0) */
637 : /* format 2 */ /* hierarchical support */
638 257 : inqdata->response = 2 | 1 << 4;
639 :
640 257 : hlen = 5;
641 :
642 : /* SCCS(7) ACC(6) TPGS(5-4) 3PC(3) PROTECT(0) */
643 : /* Not support TPGS */
644 257 : inqdata->flags = 0;
645 :
646 : /* MULTIP */
647 257 : inqdata->flags2 = 0x10;
648 :
649 : /* WBUS16(5) SYNC(4) LINKED(3) CMDQUE(1) VS(0) */
650 : /* CMDQUE */
651 257 : inqdata->flags3 = 0x2;
652 :
653 : /* T10 VENDOR IDENTIFICATION */
654 257 : spdk_strcpy_pad(inqdata->t10_vendor_id, DEFAULT_DISK_VENDOR, 8, ' ');
655 :
656 : /* PRODUCT IDENTIFICATION */
657 257 : spdk_strcpy_pad(inqdata->product_id, spdk_bdev_get_product_name(bdev), 16, ' ');
658 :
659 : /* PRODUCT REVISION LEVEL */
660 257 : 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 257 : len = INQUIRY_OFFSET(product_rev) - 5;
667 :
668 257 : if (alloc_len >= INQUIRY_OFFSET(vendor)) {
669 : /* Vendor specific */
670 257 : memset(inqdata->vendor, 0x20, 20);
671 257 : len += sizeof(inqdata->vendor);
672 257 : }
673 :
674 257 : if (alloc_len >= INQUIRY_OFFSET(ius)) {
675 : /* CLOCKING(3-2) QAS(1) IUS(0) */
676 257 : inqdata->ius = 0;
677 257 : len += sizeof(inqdata->ius);
678 257 : }
679 :
680 257 : if (alloc_len >= INQUIRY_OFFSET(reserved)) {
681 : /* Reserved */
682 257 : inqdata->reserved = 0;
683 257 : len += sizeof(inqdata->reserved);
684 257 : }
685 :
686 : /* VERSION DESCRIPTOR 1-8 */
687 257 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 2) {
688 257 : to_be16(&inqdata->desc[0], 0x0960);
689 257 : len += 2;
690 257 : }
691 :
692 257 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 4) {
693 257 : to_be16(&inqdata->desc[2], 0x0300); /* SPC-3 (no version claimed) */
694 257 : len += 2;
695 257 : }
696 :
697 257 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 6) {
698 257 : to_be16(&inqdata->desc[4], 0x320); /* SBC-2 (no version claimed) */
699 257 : len += 2;
700 257 : }
701 :
702 257 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 8) {
703 257 : to_be16(&inqdata->desc[6], 0x0040); /* SAM-2 (no version claimed) */
704 257 : len += 2;
705 257 : }
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 257 : if (alloc_len > INQUIRY_OFFSET(reserved) + 8) {
715 257 : i = alloc_len - (INQUIRY_OFFSET(reserved) + 8);
716 257 : if (i > 30) {
717 257 : i = 30;
718 257 : }
719 257 : memset(&inqdata->desc[8], 0, i);
720 257 : len += i;
721 257 : }
722 :
723 : /* ADDITIONAL LENGTH */
724 257 : inqdata->add_len = len;
725 257 : }
726 :
727 257 : return hlen + len;
728 :
729 : inq_error:
730 0 : task->data_transferred = 0;
731 0 : 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 0 : return -1;
736 258 : }
737 :
738 : static void
739 32 : mode_sense_page_init(uint8_t *buf, int len, int page, int subpage)
740 : {
741 32 : if (!buf) {
742 16 : return;
743 : }
744 :
745 16 : memset(buf, 0, len);
746 16 : 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 0 : } else {
751 16 : buf[0] = page;
752 16 : buf[1] = len - 2;
753 : }
754 32 : }
755 :
756 : static int
757 252 : 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 252 : uint8_t *cp = data;
762 252 : int len = 0;
763 252 : int plen;
764 252 : int i;
765 :
766 252 : if (pc == 0x00) {
767 : /* Current values */
768 252 : } 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 0 : } 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 252 : switch (page) {
784 : case 0x00:
785 : /* Vendor specific */
786 4 : break;
787 : case 0x01:
788 : /* Read-Write Error Recovery */
789 4 : SPDK_DEBUGLOG(scsi,
790 : "MODE_SENSE Read-Write Error Recovery\n");
791 4 : if (subpage != 0x00) {
792 0 : break;
793 : }
794 4 : plen = 0x0a + 2;
795 4 : mode_sense_page_init(cp, plen, page, subpage);
796 4 : len += plen;
797 4 : break;
798 : case 0x02:
799 : /* Disconnect-Reconnect */
800 4 : SPDK_DEBUGLOG(scsi,
801 : "MODE_SENSE Disconnect-Reconnect\n");
802 4 : if (subpage != 0x00) {
803 0 : break;
804 : }
805 4 : plen = 0x0e + 2;
806 4 : mode_sense_page_init(cp, plen, page, subpage);
807 4 : len += plen;
808 4 : break;
809 : case 0x03:
810 : /* Obsolete (Format Device) */
811 4 : break;
812 : case 0x04:
813 : /* Obsolete (Rigid Disk Geometry) */
814 4 : break;
815 : case 0x05:
816 : /* Obsolete (Rigid Disk Geometry) */
817 4 : break;
818 : case 0x06:
819 : /* Reserved */
820 4 : break;
821 : case 0x07:
822 : /* Verify Error Recovery */
823 4 : SPDK_DEBUGLOG(scsi,
824 : "MODE_SENSE Verify Error Recovery\n");
825 :
826 4 : if (subpage != 0x00) {
827 0 : break;
828 : }
829 :
830 4 : plen = 0x0a + 2;
831 4 : mode_sense_page_init(cp, plen, page, subpage);
832 4 : len += plen;
833 4 : break;
834 : case 0x08: {
835 : /* Caching */
836 4 : SPDK_DEBUGLOG(scsi, "MODE_SENSE Caching\n");
837 4 : if (subpage != 0x00) {
838 0 : break;
839 : }
840 :
841 4 : plen = 0x12 + 2;
842 4 : mode_sense_page_init(cp, plen, page, subpage);
843 :
844 4 : if (cp && spdk_bdev_has_write_cache(bdev) && pc != 0x01) {
845 0 : cp[2] |= 0x4; /* WCE */
846 0 : }
847 :
848 : /* Read Cache Disable (RCD) = 1 */
849 4 : if (cp && pc != 0x01) {
850 2 : cp[2] |= 0x1;
851 2 : }
852 :
853 4 : len += plen;
854 4 : break;
855 : }
856 : case 0x09:
857 : /* Obsolete */
858 4 : break;
859 : case 0x0a:
860 4 : switch (subpage) {
861 : case 0x00:
862 : /* Control */
863 4 : SPDK_DEBUGLOG(scsi,
864 : "MODE_SENSE Control\n");
865 4 : plen = 0x0a + 2;
866 4 : mode_sense_page_init(cp, plen, page, subpage);
867 4 : len += plen;
868 4 : break;
869 : 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 : case 0xff:
878 : /* All subpages */
879 0 : len += bdev_scsi_mode_sense_page(bdev,
880 0 : cdb, pc, page,
881 : 0x00,
882 0 : cp ? &cp[len] : NULL, task);
883 0 : len += bdev_scsi_mode_sense_page(bdev,
884 0 : cdb, pc, page,
885 : 0x01,
886 0 : cp ? &cp[len] : NULL, task);
887 0 : break;
888 : default:
889 : /* 0x02-0x3e: Reserved */
890 0 : break;
891 : }
892 4 : break;
893 : case 0x0b:
894 : /* Obsolete (Medium Types Supported) */
895 4 : break;
896 : case 0x0c:
897 : /* Obsolete (Notch And Partition) */
898 4 : break;
899 : case 0x0d:
900 : /* Obsolete */
901 4 : break;
902 : case 0x0e:
903 : case 0x0f:
904 : /* Reserved */
905 8 : break;
906 : case 0x10:
907 : /* XOR Control */
908 4 : SPDK_DEBUGLOG(scsi, "MODE_SENSE XOR Control\n");
909 4 : if (subpage != 0x00) {
910 0 : break;
911 : }
912 4 : plen = 0x16 + 2;
913 4 : mode_sense_page_init(cp, plen, page, subpage);
914 4 : len += plen;
915 4 : break;
916 : case 0x11:
917 : case 0x12:
918 : case 0x13:
919 : /* Reserved */
920 12 : break;
921 : case 0x14:
922 : /* Enclosure Services Management */
923 4 : break;
924 : case 0x15:
925 : case 0x16:
926 : case 0x17:
927 : /* Reserved */
928 12 : break;
929 : case 0x18:
930 : /* Protocol-Specific LUN */
931 4 : break;
932 : case 0x19:
933 : /* Protocol-Specific Port */
934 4 : break;
935 : case 0x1a:
936 : /* Power Condition */
937 4 : SPDK_DEBUGLOG(scsi,
938 : "MODE_SENSE Power Condition\n");
939 4 : if (subpage != 0x00) {
940 0 : break;
941 : }
942 4 : plen = 0x0a + 2;
943 4 : mode_sense_page_init(cp, plen, page, subpage);
944 4 : len += plen;
945 4 : break;
946 : case 0x1b:
947 : /* Reserved */
948 4 : break;
949 : case 0x1c:
950 : /* Informational Exceptions Control */
951 4 : SPDK_DEBUGLOG(scsi,
952 : "MODE_SENSE Informational Exceptions Control\n");
953 4 : if (subpage != 0x00) {
954 0 : break;
955 : }
956 :
957 4 : plen = 0x0a + 2;
958 4 : mode_sense_page_init(cp, plen, page, subpage);
959 4 : len += plen;
960 4 : break;
961 : case 0x1d:
962 : case 0x1e:
963 : case 0x1f:
964 : /* Reserved */
965 12 : break;
966 : 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 120 : break;
999 : case 0x3f:
1000 4 : switch (subpage) {
1001 : case 0x00:
1002 : /* All mode pages */
1003 252 : for (i = 0x00; i < 0x3e; i ++) {
1004 248 : len += bdev_scsi_mode_sense_page(
1005 248 : bdev, cdb, pc, i, 0x00,
1006 248 : cp ? &cp[len] : NULL, task);
1007 248 : }
1008 4 : break;
1009 : 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 0 : bdev, cdb, pc, i, 0x00,
1014 0 : cp ? &cp[len] : NULL, task);
1015 0 : }
1016 0 : for (i = 0x00; i < 0x3e; i ++) {
1017 0 : len += bdev_scsi_mode_sense_page(
1018 0 : bdev, cdb, pc, i, 0xff,
1019 0 : cp ? &cp[len] : NULL, task);
1020 0 : }
1021 0 : break;
1022 : default:
1023 : /* 0x01-0x3e: Reserved */
1024 0 : break;
1025 : }
1026 4 : }
1027 :
1028 252 : return len;
1029 252 : }
1030 :
1031 : static int
1032 4 : 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 4 : uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev);
1037 4 : uint32_t block_size = spdk_bdev_get_data_block_size(bdev);
1038 4 : uint8_t *hdr, *bdesc, *pages;
1039 4 : int hlen;
1040 4 : int blen;
1041 4 : int plen, total;
1042 :
1043 4 : assert(md == 6 || md == 10);
1044 :
1045 4 : if (md == 6) {
1046 2 : hlen = 4;
1047 2 : blen = 8; /* For MODE SENSE 6 only short LBA */
1048 2 : } else {
1049 2 : hlen = 8;
1050 2 : blen = llbaa ? 16 : 8;
1051 : }
1052 :
1053 4 : if (dbd) {
1054 0 : blen = 0;
1055 0 : }
1056 :
1057 4 : pages = data ? &data[hlen + blen] : NULL;
1058 8 : plen = bdev_scsi_mode_sense_page(bdev, cdb, pc, page,
1059 4 : subpage,
1060 4 : pages, task);
1061 4 : if (plen < 0) {
1062 0 : return -1;
1063 : }
1064 :
1065 4 : total = hlen + blen + plen;
1066 4 : if (data == NULL) {
1067 2 : return total;
1068 : }
1069 :
1070 2 : hdr = &data[0];
1071 2 : if (hlen == 4) {
1072 1 : hdr[0] = total - 1; /* Mode Data Length */
1073 1 : hdr[1] = 0; /* Medium Type */
1074 1 : hdr[2] = 0; /* Device-Specific Parameter */
1075 1 : hdr[3] = blen; /* Block Descriptor Length */
1076 1 : } else {
1077 1 : to_be16(&hdr[0], total - 2); /* Mode Data Length */
1078 1 : hdr[2] = 0; /* Medium Type */
1079 1 : hdr[3] = 0; /* Device-Specific Parameter */
1080 1 : hdr[4] = llbaa ? 0x1 : 0; /* Long/short LBA */
1081 1 : hdr[5] = 0; /* Reserved */
1082 1 : to_be16(&hdr[6], blen); /* Block Descriptor Length */
1083 : }
1084 :
1085 2 : bdesc = &data[hlen];
1086 2 : 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 2 : } else if (blen == 8) {
1094 : /* Number of Blocks */
1095 2 : if (num_blocks > 0xffffffffULL) {
1096 0 : memset(&bdesc[0], 0xff, 4);
1097 0 : } else {
1098 2 : to_be32(&bdesc[0], num_blocks);
1099 : }
1100 :
1101 : /* Block Length */
1102 2 : to_be32(&bdesc[4], block_size);
1103 2 : }
1104 :
1105 2 : return total;
1106 4 : }
1107 :
1108 : static void
1109 7 : bdev_scsi_task_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
1110 : void *cb_arg)
1111 : {
1112 7 : struct spdk_scsi_task *task = cb_arg;
1113 7 : int sc, sk, asc, ascq;
1114 :
1115 7 : spdk_bdev_io_get_scsi_status(bdev_io, &sc, &sk, &asc, &ascq);
1116 :
1117 7 : spdk_bdev_free_io(bdev_io);
1118 :
1119 7 : spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
1120 7 : scsi_lun_complete_task(task->lun, task);
1121 7 : }
1122 :
1123 : static void
1124 6 : bdev_scsi_read_task_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
1125 : void *cb_arg)
1126 : {
1127 6 : struct spdk_scsi_task *task = cb_arg;
1128 6 : int sc, sk, asc, ascq;
1129 :
1130 6 : task->bdev_io = bdev_io;
1131 :
1132 6 : spdk_bdev_io_get_scsi_status(bdev_io, &sc, &sk, &asc, &ascq);
1133 :
1134 6 : spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
1135 6 : scsi_lun_complete_task(task->lun, task);
1136 6 : }
1137 :
1138 : static void
1139 0 : bdev_scsi_task_complete_reset(struct spdk_bdev_io *bdev_io, bool success,
1140 : void *cb_arg)
1141 : {
1142 0 : struct spdk_scsi_task *task = cb_arg;
1143 :
1144 0 : spdk_bdev_free_io(bdev_io);
1145 :
1146 0 : if (success) {
1147 0 : task->response = SPDK_SCSI_TASK_MGMT_RESP_SUCCESS;
1148 0 : }
1149 :
1150 0 : scsi_lun_complete_reset_task(task->lun, task);
1151 0 : }
1152 :
1153 : static void
1154 7 : bdev_scsi_queue_io(struct spdk_scsi_task *task, spdk_bdev_io_wait_cb cb_fn, void *cb_arg)
1155 : {
1156 7 : struct spdk_scsi_lun *lun = task->lun;
1157 7 : struct spdk_bdev *bdev = lun->bdev;
1158 7 : struct spdk_io_channel *ch = lun->io_channel;
1159 7 : int rc;
1160 :
1161 7 : task->bdev_io_wait.bdev = bdev;
1162 7 : task->bdev_io_wait.cb_fn = cb_fn;
1163 7 : task->bdev_io_wait.cb_arg = cb_arg;
1164 :
1165 7 : rc = spdk_bdev_queue_io_wait(bdev, ch, &task->bdev_io_wait);
1166 7 : if (rc != 0) {
1167 0 : assert(false);
1168 : }
1169 7 : }
1170 :
1171 : static int
1172 3 : 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 3 : uint64_t bdev_num_blocks;
1177 3 : int rc;
1178 :
1179 3 : if (num_blocks == 0) {
1180 0 : return SPDK_SCSI_TASK_COMPLETE;
1181 : }
1182 :
1183 3 : bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
1184 :
1185 3 : if (lba >= bdev_num_blocks || num_blocks > bdev_num_blocks ||
1186 3 : 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 6 : rc = spdk_bdev_flush_blocks(bdev_desc, bdev_ch, lba, num_blocks,
1196 3 : bdev_scsi_task_complete_cmd, task);
1197 :
1198 3 : if (rc) {
1199 1 : if (rc == -ENOMEM) {
1200 1 : bdev_scsi_queue_io(task, bdev_scsi_process_block_resubmit, task);
1201 1 : 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 2 : task->data_transferred = 0;
1211 2 : return SPDK_SCSI_TASK_PENDING;
1212 3 : }
1213 :
1214 : static uint64_t
1215 10 : _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 10 : uint8_t shift_cnt;
1219 :
1220 : /* Avoid expensive div operations if possible. These spdk_u32 functions are very cheap. */
1221 10 : if (spdk_likely(spdk_u32_is_pow2(block_size))) {
1222 10 : shift_cnt = spdk_u32log2(block_size);
1223 10 : *offset_blocks = offset_bytes >> shift_cnt;
1224 10 : *num_blocks = num_bytes >> shift_cnt;
1225 20 : return (offset_bytes - (*offset_blocks << shift_cnt)) |
1226 10 : (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 10 : }
1233 :
1234 : static int
1235 15 : 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 15 : uint64_t bdev_num_blocks, offset_blocks, num_blocks;
1240 15 : uint32_t max_xfer_len, block_size;
1241 15 : int sk = SPDK_SCSI_SENSE_NO_SENSE, asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
1242 15 : int rc;
1243 :
1244 15 : task->data_transferred = 0;
1245 :
1246 15 : 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 15 : bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
1253 15 : if (spdk_unlikely(bdev_num_blocks <= lba || bdev_num_blocks - lba < xfer_len)) {
1254 3 : SPDK_DEBUGLOG(scsi, "end of media\n");
1255 3 : sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
1256 3 : asc = SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1257 3 : goto check_condition;
1258 : }
1259 :
1260 12 : if (spdk_unlikely(xfer_len == 0)) {
1261 1 : task->status = SPDK_SCSI_STATUS_GOOD;
1262 1 : return SPDK_SCSI_TASK_COMPLETE;
1263 : }
1264 :
1265 11 : 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 11 : max_xfer_len = SPDK_WORK_BLOCK_SIZE / block_size;
1269 11 : if (spdk_unlikely(xfer_len > max_xfer_len)) {
1270 1 : SPDK_ERRLOG("xfer_len %" PRIu32 " > maximum transfer length %" PRIu32 "\n",
1271 : xfer_len, max_xfer_len);
1272 1 : sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
1273 1 : asc = SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB;
1274 1 : goto check_condition;
1275 : }
1276 :
1277 10 : if (!is_read) {
1278 : /* Additional check for Transfer Length */
1279 3 : 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 3 : }
1285 :
1286 10 : 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 10 : offset_blocks += lba;
1293 :
1294 10 : SPDK_DEBUGLOG(scsi,
1295 : "%s: lba=%"PRIu64", len=%"PRIu64"\n",
1296 : is_read ? "Read" : "Write", offset_blocks, num_blocks);
1297 :
1298 10 : if (is_read) {
1299 7 : rc = spdk_bdev_readv_blocks(bdev_desc, bdev_ch, task->iovs, task->iovcnt,
1300 7 : offset_blocks, num_blocks,
1301 7 : bdev_scsi_read_task_complete_cmd, task);
1302 10 : } else if (is_compare) {
1303 0 : struct iovec *iov;
1304 0 : 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 0 : } 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 0 : &task->caw_iov, 1, offset_blocks, 1, bdev_scsi_task_complete_cmd, task);
1326 0 : } else {
1327 3 : rc = spdk_bdev_writev_blocks(bdev_desc, bdev_ch, task->iovs, task->iovcnt,
1328 3 : offset_blocks, num_blocks,
1329 3 : bdev_scsi_task_complete_cmd, task);
1330 : }
1331 :
1332 10 : if (rc) {
1333 2 : if (rc == -ENOMEM) {
1334 2 : bdev_scsi_queue_io(task, bdev_scsi_process_block_resubmit, task);
1335 2 : 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 8 : task->data_transferred = task->length;
1343 8 : return SPDK_SCSI_TASK_PENDING;
1344 :
1345 : check_condition:
1346 4 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, sk, asc,
1347 : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1348 4 : return SPDK_SCSI_TASK_COMPLETE;
1349 15 : }
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 4 : bdev_scsi_split_resubmit(void *arg)
1367 : {
1368 4 : struct spdk_bdev_scsi_split_ctx *ctx = arg;
1369 :
1370 4 : bdev_scsi_split(ctx);
1371 4 : }
1372 :
1373 : static int
1374 9 : bdev_scsi_split(struct spdk_bdev_scsi_split_ctx *ctx)
1375 : {
1376 9 : struct spdk_scsi_task *task = ctx->task;
1377 9 : uint8_t opcode = task->cdb[0];
1378 9 : int rc;
1379 :
1380 19 : while (ctx->remaining_count != 0) {
1381 16 : rc = ctx->fn(ctx);
1382 16 : if (rc == 0) {
1383 10 : ctx->current_count++;
1384 10 : ctx->remaining_count--;
1385 10 : ctx->outstanding_count++;
1386 10 : continue;
1387 6 : } else if (rc == -ENOMEM) {
1388 6 : 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 9 : 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 5 : return SPDK_SCSI_TASK_PENDING;
1406 : }
1407 :
1408 4 : 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 4 : bdev_scsi_queue_io(task, bdev_scsi_split_resubmit, ctx);
1412 4 : return SPDK_SCSI_TASK_PENDING;
1413 : }
1414 :
1415 0 : free(ctx);
1416 0 : return SPDK_SCSI_TASK_COMPLETE;
1417 9 : }
1418 :
1419 : static void
1420 10 : bdev_scsi_task_complete_split_cmd(struct spdk_bdev_io *bdev_io, bool success,
1421 : void *cb_arg)
1422 : {
1423 10 : struct spdk_bdev_scsi_split_ctx *ctx = cb_arg;
1424 10 : struct spdk_scsi_task *task = ctx->task;
1425 :
1426 10 : spdk_bdev_free_io(bdev_io);
1427 :
1428 10 : 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 0 : }
1437 :
1438 10 : ctx->outstanding_count--;
1439 10 : if (ctx->outstanding_count != 0) {
1440 : /* Any child I/O is still outstanding. */
1441 5 : return;
1442 : }
1443 :
1444 5 : if (ctx->remaining_count == 0) {
1445 : /* SCSI task finishes when all descriptors are consumed. */
1446 3 : scsi_lun_complete_task(task->lun, task);
1447 3 : free(ctx);
1448 3 : return;
1449 : }
1450 :
1451 : /* Continue with splitting process. */
1452 2 : bdev_scsi_split(ctx);
1453 10 : }
1454 :
1455 : static int
1456 3 : __copy_desc(struct spdk_bdev_scsi_split_ctx *ctx, uint8_t *data, size_t data_len)
1457 : {
1458 3 : uint16_t desc_data_len;
1459 3 : uint16_t desc_count;
1460 :
1461 3 : if (!data) {
1462 0 : return -EINVAL;
1463 : }
1464 :
1465 3 : if (data_len < 8) {
1466 : /* We can't even get the reported length, so fail. */
1467 0 : return -EINVAL;
1468 : }
1469 :
1470 3 : desc_data_len = from_be16(&data[2]);
1471 3 : desc_count = desc_data_len / 16;
1472 :
1473 3 : 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 3 : 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 3 : memcpy(ctx->desc, &data[8], desc_data_len);
1486 3 : return desc_count;
1487 3 : }
1488 :
1489 : static int
1490 16 : _bdev_scsi_unmap(struct spdk_bdev_scsi_split_ctx *ctx)
1491 : {
1492 16 : struct spdk_scsi_task *task = ctx->task;
1493 16 : struct spdk_scsi_lun *lun = task->lun;
1494 16 : struct spdk_scsi_unmap_bdesc *desc;
1495 16 : uint64_t offset_blocks;
1496 16 : uint64_t num_blocks;
1497 :
1498 16 : desc = &ctx->desc[ctx->current_count];
1499 :
1500 16 : offset_blocks = from_be64(&desc->lba);
1501 16 : num_blocks = from_be32(&desc->block_count);
1502 :
1503 48 : return spdk_bdev_unmap_blocks(lun->bdev_desc,
1504 16 : lun->io_channel,
1505 16 : offset_blocks,
1506 16 : num_blocks,
1507 : bdev_scsi_task_complete_split_cmd,
1508 16 : ctx);
1509 16 : }
1510 :
1511 : static int
1512 3 : bdev_scsi_unmap(struct spdk_bdev *bdev, struct spdk_scsi_task *task)
1513 : {
1514 3 : struct spdk_bdev_scsi_split_ctx *ctx;
1515 3 : uint8_t *data;
1516 3 : int desc_count = -1;
1517 3 : int data_len;
1518 :
1519 3 : assert(task->status == SPDK_SCSI_STATUS_GOOD);
1520 :
1521 3 : ctx = calloc(1, sizeof(*ctx));
1522 3 : 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 3 : ctx->task = task;
1531 3 : ctx->current_count = 0;
1532 3 : ctx->outstanding_count = 0;
1533 3 : ctx->fn = _bdev_scsi_unmap;
1534 :
1535 3 : if (task->iovcnt == 1) {
1536 3 : data = (uint8_t *)task->iovs[0].iov_base;
1537 3 : data_len = task->iovs[0].iov_len;
1538 3 : desc_count = __copy_desc(ctx, data, data_len);
1539 3 : } 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 0 : }
1545 : }
1546 :
1547 3 : if (desc_count > 0) {
1548 3 : ctx->remaining_count = desc_count;
1549 3 : 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 0 : }
1558 :
1559 0 : free(ctx);
1560 0 : return SPDK_SCSI_TASK_COMPLETE;
1561 3 : }
1562 :
1563 : static int
1564 0 : _bdev_scsi_write_same(struct spdk_bdev_scsi_split_ctx *ctx)
1565 : {
1566 0 : struct spdk_scsi_task *task = ctx->task;
1567 0 : struct spdk_scsi_lun *lun = task->lun;
1568 0 : uint64_t offset_blocks;
1569 :
1570 0 : offset_blocks = ctx->start_offset_blocks + ctx->current_count;
1571 0 : return spdk_bdev_writev_blocks(lun->bdev_desc, lun->io_channel, task->iovs, task->iovcnt,
1572 0 : offset_blocks, 1, bdev_scsi_task_complete_split_cmd, ctx);
1573 0 : }
1574 :
1575 : static int
1576 0 : 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 0 : struct spdk_bdev_scsi_split_ctx *ctx;
1581 0 : uint64_t bdev_num_blocks, offset_blocks, num_blocks;
1582 0 : uint32_t max_xfer_len, block_size;
1583 0 : int sk = SPDK_SCSI_SENSE_NO_SENSE, asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
1584 :
1585 0 : task->data_transferred = 0;
1586 :
1587 0 : 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 0 : block_size = spdk_bdev_get_data_block_size(bdev);
1593 0 : 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 0 : if (spdk_unlikely(xfer_len == 0)) {
1600 0 : task->status = SPDK_SCSI_STATUS_GOOD;
1601 0 : return SPDK_SCSI_TASK_COMPLETE;
1602 : }
1603 :
1604 0 : bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
1605 0 : 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 0 : max_xfer_len = SPDK_WORK_BLOCK_SIZE / block_size;
1614 0 : 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 0 : if (_bytes_to_blocks(block_size, task->offset, &offset_blocks,
1623 0 : (uint64_t)task->length * xfer_len,
1624 0 : &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 0 : offset_blocks += lba;
1631 0 : SPDK_DEBUGLOG(scsi, "Writesame: lba=%"PRIu64", len=%"PRIu64"\n",
1632 : offset_blocks, num_blocks);
1633 :
1634 0 : ctx = calloc(1, sizeof(*ctx));
1635 0 : if (!ctx) {
1636 0 : SPDK_ERRLOG("No enough memory on SCSI WRITE SAME\n");
1637 0 : goto check_condition;
1638 : }
1639 :
1640 0 : ctx->task = task;
1641 0 : ctx->start_offset_blocks = offset_blocks;
1642 0 : ctx->current_count = 0;
1643 0 : ctx->outstanding_count = 0;
1644 0 : ctx->remaining_count = xfer_len;
1645 0 : ctx->fn = _bdev_scsi_write_same;
1646 :
1647 0 : task->data_transferred = task->length;
1648 :
1649 0 : return bdev_scsi_split(ctx);
1650 :
1651 : check_condition:
1652 0 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
1653 0 : sk, asc, SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1654 0 : return SPDK_SCSI_TASK_COMPLETE;
1655 0 : }
1656 :
1657 : static int
1658 283 : bdev_scsi_process_block(struct spdk_scsi_task *task)
1659 : {
1660 283 : struct spdk_scsi_lun *lun = task->lun;
1661 283 : struct spdk_bdev *bdev = lun->bdev;
1662 283 : uint64_t lba;
1663 283 : uint32_t xfer_len;
1664 283 : uint32_t len = 0;
1665 283 : uint8_t *cdb = task->cdb;
1666 :
1667 : /* XXX: We need to support FUA bit for writes! */
1668 283 : switch (cdb[0]) {
1669 : 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 0 : }
1678 0 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1679 0 : task, lba, xfer_len,
1680 0 : cdb[0] == SPDK_SBC_READ_6, false);
1681 :
1682 : case SPDK_SBC_READ_10:
1683 : case SPDK_SBC_WRITE_10:
1684 0 : lba = from_be32(&cdb[2]);
1685 0 : xfer_len = from_be16(&cdb[7]);
1686 0 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1687 0 : task, lba, xfer_len,
1688 0 : cdb[0] == SPDK_SBC_READ_10, false);
1689 :
1690 : 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 0 : task, lba, xfer_len,
1696 0 : cdb[0] == SPDK_SBC_READ_12, false);
1697 : case SPDK_SBC_READ_16:
1698 : case SPDK_SBC_WRITE_16:
1699 15 : lba = from_be64(&cdb[2]);
1700 15 : xfer_len = from_be32(&cdb[10]);
1701 30 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
1702 15 : task, lba, xfer_len,
1703 15 : cdb[0] == SPDK_SBC_READ_16, false);
1704 :
1705 : 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 0 : task, lba, num_blocks, false, true);
1734 0 : }
1735 :
1736 : case SPDK_SBC_READ_CAPACITY_10: {
1737 0 : uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev);
1738 0 : uint8_t buffer[8];
1739 :
1740 0 : if (num_blocks - 1 > 0xffffffffULL) {
1741 0 : memset(buffer, 0xff, 4);
1742 0 : } else {
1743 0 : to_be32(buffer, num_blocks - 1);
1744 : }
1745 0 : to_be32(&buffer[4], spdk_bdev_get_data_block_size(bdev));
1746 :
1747 0 : len = spdk_min(task->length, sizeof(buffer));
1748 0 : if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) {
1749 0 : break;
1750 : }
1751 :
1752 0 : task->data_transferred = len;
1753 0 : task->status = SPDK_SCSI_STATUS_GOOD;
1754 0 : break;
1755 0 : }
1756 :
1757 : case SPDK_SPC_SERVICE_ACTION_IN_16:
1758 0 : switch (cdb[1] & 0x1f) { /* SERVICE ACTION */
1759 : case SPDK_SBC_SAI_READ_CAPACITY_16: {
1760 0 : uint8_t buffer[32] = {0};
1761 0 : uint32_t lbppb, lbppbe;
1762 :
1763 0 : to_be64(&buffer[0], spdk_bdev_get_num_blocks(bdev) - 1);
1764 0 : to_be32(&buffer[8], spdk_bdev_get_data_block_size(bdev));
1765 0 : lbppb = spdk_bdev_get_physical_block_size(bdev) / spdk_bdev_get_data_block_size(bdev);
1766 0 : lbppbe = spdk_u32log2(lbppb);
1767 0 : if (lbppbe > 0xf) {
1768 0 : SPDK_ERRLOG("lbppbe(0x%x) > 0xf\n", lbppbe);
1769 0 : } else {
1770 0 : 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 0 : if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
1778 0 : buffer[14] |= 1 << 7;
1779 0 : }
1780 :
1781 0 : len = spdk_min(from_be32(&cdb[10]), sizeof(buffer));
1782 0 : if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) {
1783 0 : break;
1784 : }
1785 :
1786 0 : task->data_transferred = len;
1787 0 : task->status = SPDK_SCSI_STATUS_GOOD;
1788 0 : break;
1789 0 : }
1790 :
1791 : default:
1792 0 : return SPDK_SCSI_TASK_UNKNOWN;
1793 : }
1794 0 : break;
1795 :
1796 : case SPDK_SBC_SYNCHRONIZE_CACHE_10:
1797 : case SPDK_SBC_SYNCHRONIZE_CACHE_16:
1798 3 : if (cdb[0] == SPDK_SBC_SYNCHRONIZE_CACHE_10) {
1799 0 : lba = from_be32(&cdb[2]);
1800 0 : len = from_be16(&cdb[7]);
1801 0 : } else {
1802 3 : lba = from_be64(&cdb[2]);
1803 3 : len = from_be32(&cdb[10]);
1804 : }
1805 :
1806 3 : if (len == 0) {
1807 0 : len = spdk_bdev_get_num_blocks(bdev) - lba;
1808 0 : }
1809 :
1810 3 : return bdev_scsi_sync(bdev, lun->bdev_desc, lun->io_channel, task, lba, len);
1811 : break;
1812 :
1813 : case SPDK_SBC_UNMAP:
1814 3 : return bdev_scsi_unmap(bdev, task);
1815 :
1816 : case SPDK_SBC_WRITE_SAME_10:
1817 0 : lba = from_be32(&cdb[2]);
1818 0 : xfer_len = from_be16(&cdb[7]);
1819 0 : return bdev_scsi_write_same(bdev, lun->bdev_desc, lun->io_channel,
1820 0 : task, lba, xfer_len, cdb[1]);
1821 :
1822 : 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 : default:
1830 262 : return SPDK_SCSI_TASK_UNKNOWN;
1831 : }
1832 :
1833 0 : return SPDK_SCSI_TASK_COMPLETE;
1834 283 : }
1835 :
1836 : static void
1837 3 : bdev_scsi_process_block_resubmit(void *arg)
1838 : {
1839 3 : struct spdk_scsi_task *task = arg;
1840 :
1841 3 : bdev_scsi_process_block(task);
1842 3 : }
1843 :
1844 : static int
1845 2 : bdev_scsi_check_len(struct spdk_scsi_task *task, int len, int min_len)
1846 : {
1847 2 : if (len >= min_len) {
1848 2 : 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 2 : }
1858 :
1859 : static int
1860 262 : bdev_scsi_process_primary(struct spdk_scsi_task *task)
1861 : {
1862 262 : struct spdk_scsi_lun *lun = task->lun;
1863 262 : struct spdk_bdev *bdev = lun->bdev;
1864 262 : int alloc_len = -1;
1865 262 : int data_len = -1;
1866 262 : uint8_t *cdb = task->cdb;
1867 262 : uint8_t *data = NULL;
1868 262 : int rc = 0;
1869 262 : int pllen, md = 0;
1870 262 : int llba;
1871 262 : int dbd, pc, page, subpage;
1872 262 : int cmd_parsed = 0;
1873 :
1874 262 : switch (cdb[0]) {
1875 : case SPDK_SPC_INQUIRY:
1876 258 : alloc_len = from_be16(&cdb[3]);
1877 258 : data_len = spdk_max(4096, alloc_len);
1878 258 : data = calloc(1, data_len);
1879 258 : assert(data != NULL);
1880 258 : rc = bdev_scsi_inquiry(bdev, task, cdb, data, data_len);
1881 258 : data_len = spdk_min(rc, data_len);
1882 258 : if (rc < 0) {
1883 1 : break;
1884 : }
1885 :
1886 257 : SPDK_LOGDUMP(scsi, "INQUIRY", data, data_len);
1887 257 : break;
1888 :
1889 : case SPDK_SPC_REPORT_LUNS: {
1890 0 : int sel;
1891 :
1892 0 : sel = cdb[2];
1893 0 : SPDK_DEBUGLOG(scsi, "sel=%x\n", sel);
1894 :
1895 0 : alloc_len = from_be32(&cdb[6]);
1896 0 : rc = bdev_scsi_check_len(task, alloc_len, 16);
1897 0 : if (rc < 0) {
1898 0 : break;
1899 : }
1900 :
1901 0 : data_len = spdk_max(4096, alloc_len);
1902 0 : data = calloc(1, data_len);
1903 0 : assert(data != NULL);
1904 0 : rc = bdev_scsi_report_luns(task->lun, sel, data, data_len);
1905 0 : data_len = rc;
1906 0 : 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 0 : SPDK_LOGDUMP(scsi, "REPORT LUNS", data, data_len);
1915 0 : break;
1916 0 : }
1917 :
1918 : case SPDK_SPC_MODE_SELECT_6:
1919 : case SPDK_SPC_MODE_SELECT_10:
1920 2 : if (cdb[0] == SPDK_SPC_MODE_SELECT_6) {
1921 : /* MODE_SELECT(6) must have at least a 4 byte header. */
1922 2 : md = 4;
1923 2 : pllen = cdb[4];
1924 2 : } 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 2 : if (pllen == 0) {
1931 1 : break;
1932 : }
1933 :
1934 1 : rc = bdev_scsi_check_len(task, pllen, md);
1935 1 : if (rc < 0) {
1936 0 : break;
1937 : }
1938 :
1939 1 : data = spdk_scsi_task_gather_data(task, &rc);
1940 1 : if (rc < 0) {
1941 0 : break;
1942 : }
1943 1 : data_len = rc;
1944 :
1945 1 : rc = bdev_scsi_check_len(task, data_len, spdk_max(pllen, md));
1946 1 : if (rc < 0) {
1947 0 : break;
1948 : }
1949 :
1950 1 : rc = pllen;
1951 1 : data_len = 0;
1952 1 : break;
1953 :
1954 : case SPDK_SPC_MODE_SENSE_6:
1955 1 : alloc_len = cdb[4];
1956 1 : md = 6;
1957 : /* FALLTHROUGH */
1958 : case SPDK_SPC_MODE_SENSE_10:
1959 2 : llba = 0;
1960 :
1961 2 : if (md == 0) {
1962 1 : alloc_len = from_be16(&cdb[7]);
1963 1 : llba = !!(cdb[1] & 0x10);
1964 1 : md = 10;
1965 1 : }
1966 :
1967 2 : dbd = !!(cdb[1] & 0x8);
1968 2 : pc = (cdb[2] & 0xc0) >> 6;
1969 2 : page = cdb[2] & 0x3f;
1970 2 : subpage = cdb[3];
1971 :
1972 : /* First call with no buffer to discover needed buffer size */
1973 4 : rc = bdev_scsi_mode_sense(bdev, md,
1974 2 : cdb, dbd, llba, pc,
1975 2 : page, subpage,
1976 2 : NULL, task);
1977 2 : if (rc < 0) {
1978 0 : break;
1979 : }
1980 :
1981 2 : data_len = rc;
1982 2 : data = calloc(1, data_len);
1983 2 : assert(data != NULL);
1984 :
1985 : /* First call with no buffer to discover needed buffer size */
1986 4 : rc = bdev_scsi_mode_sense(bdev, md,
1987 2 : cdb, dbd, llba, pc,
1988 2 : page, subpage,
1989 2 : data, task);
1990 2 : 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 2 : break;
1999 :
2000 : case SPDK_SPC_REQUEST_SENSE: {
2001 0 : int desc;
2002 0 : 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 0 : }
2029 :
2030 : case SPDK_SPC_LOG_SELECT:
2031 0 : SPDK_DEBUGLOG(scsi, "LOG_SELECT\n");
2032 0 : cmd_parsed = 1;
2033 : /* FALLTHROUGH */
2034 : case SPDK_SPC_LOG_SENSE:
2035 0 : if (!cmd_parsed) {
2036 0 : SPDK_DEBUGLOG(scsi, "LOG_SENSE\n");
2037 0 : }
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 : case SPDK_SPC_TEST_UNIT_READY:
2048 0 : SPDK_DEBUGLOG(scsi, "TEST_UNIT_READY\n");
2049 0 : cmd_parsed = 1;
2050 : /* FALLTHROUGH */
2051 : case SPDK_SBC_START_STOP_UNIT:
2052 0 : if (!cmd_parsed) {
2053 0 : SPDK_DEBUGLOG(scsi, "START_STOP_UNIT\n");
2054 0 : }
2055 :
2056 0 : rc = 0;
2057 0 : break;
2058 :
2059 : 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 : 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 : 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 0 : }
2099 0 : data_len = 0;
2100 0 : }
2101 0 : break;
2102 :
2103 : case SPDK_SPC2_RELEASE_6:
2104 : case SPDK_SPC2_RELEASE_10:
2105 0 : rc = scsi2_release(task);
2106 0 : break;
2107 :
2108 : default:
2109 0 : return SPDK_SCSI_TASK_UNKNOWN;
2110 : }
2111 :
2112 262 : if (rc >= 0 && data_len > 0) {
2113 259 : assert(alloc_len >= 0);
2114 259 : spdk_scsi_task_scatter_data(task, data, spdk_min(alloc_len, data_len));
2115 259 : rc = spdk_min(data_len, alloc_len);
2116 259 : }
2117 :
2118 262 : if (rc >= 0) {
2119 261 : task->data_transferred = rc;
2120 261 : task->status = SPDK_SCSI_STATUS_GOOD;
2121 261 : }
2122 :
2123 262 : if (data) {
2124 261 : free(data);
2125 261 : }
2126 :
2127 262 : return SPDK_SCSI_TASK_COMPLETE;
2128 262 : }
2129 :
2130 : int
2131 280 : bdev_scsi_execute(struct spdk_scsi_task *task)
2132 : {
2133 280 : int rc;
2134 :
2135 280 : if ((rc = bdev_scsi_process_block(task)) == SPDK_SCSI_TASK_UNKNOWN) {
2136 262 : if ((rc = bdev_scsi_process_primary(task)) == SPDK_SCSI_TASK_UNKNOWN) {
2137 0 : SPDK_DEBUGLOG(scsi, "unsupported SCSI OP=0x%x\n", task->cdb[0]);
2138 : /* INVALID COMMAND OPERATION CODE */
2139 0 : 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 0 : return SPDK_SCSI_TASK_COMPLETE;
2144 : }
2145 262 : }
2146 :
2147 280 : return rc;
2148 280 : }
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 0 : bdev_scsi_reset(struct spdk_scsi_task *task)
2160 : {
2161 0 : struct spdk_scsi_lun *lun = task->lun;
2162 0 : int rc;
2163 :
2164 0 : rc = spdk_bdev_reset(lun->bdev_desc, lun->io_channel, bdev_scsi_task_complete_reset,
2165 0 : task);
2166 0 : if (rc == -ENOMEM) {
2167 0 : bdev_scsi_queue_io(task, bdev_scsi_reset_resubmit, task);
2168 0 : }
2169 0 : }
2170 :
2171 : bool
2172 3 : bdev_scsi_get_dif_ctx(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
2173 : struct spdk_dif_ctx *dif_ctx)
2174 : {
2175 3 : uint32_t ref_tag = 0, dif_check_flags = 0, data_offset;
2176 3 : uint8_t *cdb;
2177 3 : int rc;
2178 3 : struct spdk_dif_ctx_init_ext_opts dif_opts;
2179 :
2180 3 : if (spdk_likely(spdk_bdev_get_md_size(bdev) == 0)) {
2181 0 : return false;
2182 : }
2183 :
2184 3 : cdb = task->cdb;
2185 3 : data_offset = task->offset;
2186 :
2187 : /* We use lower 32 bits of LBA as Reference. Tag */
2188 3 : switch (cdb[0]) {
2189 : case SPDK_SBC_READ_6:
2190 : case SPDK_SBC_WRITE_6:
2191 1 : ref_tag = (uint32_t)cdb[1] << 16;
2192 1 : ref_tag |= (uint32_t)cdb[2] << 8;
2193 1 : ref_tag |= (uint32_t)cdb[3];
2194 1 : break;
2195 : case SPDK_SBC_READ_10:
2196 : case SPDK_SBC_WRITE_10:
2197 : case SPDK_SBC_READ_12:
2198 : case SPDK_SBC_WRITE_12:
2199 1 : ref_tag = from_be32(&cdb[2]);
2200 1 : break;
2201 : case SPDK_SBC_READ_16:
2202 : case SPDK_SBC_WRITE_16:
2203 1 : ref_tag = (uint32_t)from_be64(&cdb[2]);
2204 1 : break;
2205 : default:
2206 0 : return false;
2207 : }
2208 :
2209 3 : if (spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_REFTAG)) {
2210 0 : dif_check_flags |= SPDK_DIF_FLAGS_REFTAG_CHECK;
2211 0 : }
2212 :
2213 3 : if (spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_GUARD)) {
2214 0 : dif_check_flags |= SPDK_DIF_FLAGS_GUARD_CHECK;
2215 0 : }
2216 :
2217 3 : dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
2218 3 : dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
2219 6 : rc = spdk_dif_ctx_init(dif_ctx,
2220 3 : spdk_bdev_get_block_size(bdev),
2221 3 : spdk_bdev_get_md_size(bdev),
2222 3 : spdk_bdev_is_md_interleaved(bdev),
2223 3 : spdk_bdev_is_dif_head_of_md(bdev),
2224 3 : spdk_bdev_get_dif_type(bdev),
2225 3 : dif_check_flags,
2226 3 : ref_tag, 0, 0, data_offset, 0, &dif_opts);
2227 :
2228 3 : return (rc == 0) ? true : false;
2229 3 : }
|