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 : 1186 : bdev_scsi_set_naa_ieee_extended(const char *name, uint8_t *buf)
33 : : {
34 : : int i;
35 : 1186 : uint64_t local_value = 0, id_a, seed = 131;
36 : :
37 [ + + # # : 33515 : for (i = 0; name[i] != '\0'; i++) {
# # # # ]
38 [ # # # # ]: 32329 : 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 : 1186 : id_a = local_value & 0x0000000fff000000ull;
46 [ # # ]: 1186 : id_a = id_a << 24;
47 : :
48 : 1186 : local_value &= 0x0000000000ffffffull;
49 : : /* NAA 02, and 00 03 47 for IEEE Intel */
50 : 1186 : local_value |= 0x2000000347000000ull;
51 : 1186 : local_value |= id_a;
52 : :
53 : 1186 : to_be64((void *)buf, local_value);
54 : 1186 : }
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 : 0 : } 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 : 0 : }
100 : :
101 : : /* LUN LIST LENGTH */
102 : 139 : to_be32(data, len);
103 : :
104 [ # # ]: 139 : return hlen + len;
105 : 0 : }
106 : :
107 : : static int
108 : 1198 : bdev_scsi_pad_scsi_name(char *dst, const char *name)
109 : : {
110 : : size_t len;
111 : :
112 [ - + ]: 1198 : len = strlen(name);
113 [ - + - + ]: 1198 : memcpy(dst, name, len);
114 : 3 : do {
115 [ # # # # ]: 2568 : dst[len++] = '\0';
116 [ + + ]: 2568 : } while (len & 3);
117 : :
118 : 1198 : return len;
119 : : }
120 : :
121 : : static int
122 : 8663 : 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 : 8663 : int hlen = 0, plen, plen2;
130 : 8663 : uint16_t len = 0;
131 : : int pc;
132 : : int pd;
133 : : int evpd;
134 : : int i;
135 : 8663 : struct spdk_scsi_cdb_inquiry *inq = (struct spdk_scsi_cdb_inquiry *)cdb;
136 : :
137 : : /* standard inquiry command at lease with 36 Bytes */
138 [ - + ]: 8663 : if (alloc_len < 0x24) {
139 : 0 : goto inq_error;
140 : : }
141 : :
142 [ # # # # ]: 8663 : lun = task->lun;
143 [ # # # # ]: 8663 : dev = lun->dev;
144 [ # # # # ]: 8663 : port = task->target_port;
145 : :
146 : 8663 : pd = SPDK_SPC_PERIPHERAL_DEVICE_TYPE_DISK;
147 [ # # # # ]: 8663 : pc = inq->page_code;
148 [ # # # # ]: 8663 : evpd = inq->evpd & 0x1;
149 : :
150 [ + + + + ]: 8663 : 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 [ + + ]: 8659 : if (evpd) {
159 : 6261 : struct spdk_scsi_vpd_page *vpage = (struct spdk_scsi_vpd_page *)data;
160 : :
161 : : /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
162 [ # # ]: 6261 : vpage->peripheral_device_type = pd;
163 [ # # ]: 6261 : vpage->peripheral_qualifier = SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED;
164 : : /* PAGE CODE */
165 [ # # # # ]: 6261 : vpage->page_code = pc;
166 : :
167 : : /* Vital product data */
168 [ + + + - : 6261 : switch (pc) {
- - - + +
+ + ]
169 : 2959 : case SPDK_SPC_VPD_SUPPORTED_VPD_PAGES:
170 : 2959 : hlen = 4;
171 : :
172 [ # # # # : 2959 : vpage->params[0] = SPDK_SPC_VPD_SUPPORTED_VPD_PAGES;
# # ]
173 [ # # # # : 2959 : vpage->params[1] = SPDK_SPC_VPD_UNIT_SERIAL_NUMBER;
# # ]
174 [ # # # # : 2959 : vpage->params[2] = SPDK_SPC_VPD_DEVICE_IDENTIFICATION;
# # ]
175 [ # # # # : 2959 : vpage->params[3] = SPDK_SPC_VPD_MANAGEMENT_NETWORK_ADDRESSES;
# # ]
176 [ # # # # : 2959 : vpage->params[4] = SPDK_SPC_VPD_EXTENDED_INQUIRY_DATA;
# # ]
177 [ # # # # : 2959 : vpage->params[5] = SPDK_SPC_VPD_MODE_PAGE_POLICY;
# # ]
178 [ # # # # : 2959 : vpage->params[6] = SPDK_SPC_VPD_SCSI_PORTS;
# # ]
179 [ # # # # : 2959 : vpage->params[7] = SPDK_SPC_VPD_BLOCK_LIMITS;
# # ]
180 [ # # # # : 2959 : vpage->params[8] = SPDK_SPC_VPD_BLOCK_DEV_CHARS;
# # ]
181 : 2959 : len = 9;
182 [ + + ]: 2959 : if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
183 [ # # # # : 2931 : vpage->params[9] = SPDK_SPC_VPD_BLOCK_THIN_PROVISION;
# # ]
184 : 2931 : len++;
185 : 0 : }
186 : :
187 : : /* PAGE LENGTH */
188 [ # # ]: 2959 : to_be16(vpage->alloc_len, len);
189 : 2959 : break;
190 : :
191 : 1186 : case SPDK_SPC_VPD_UNIT_SERIAL_NUMBER: {
192 : 1186 : const char *name = spdk_bdev_get_name(bdev);
193 : :
194 : 1186 : hlen = 4;
195 : :
196 : : /* PRODUCT SERIAL NUMBER */
197 [ - + ]: 1186 : len = strlen(name) + 1;
198 [ + + ]: 1186 : if (len > MAX_SERIAL_STRING) {
199 : 829 : len = MAX_SERIAL_STRING;
200 : 0 : }
201 : :
202 [ - + - + : 1186 : memcpy(vpage->params, name, len - 1);
# # # # ]
203 [ # # # # : 1186 : vpage->params[len - 1] = 0;
# # # # ]
204 : :
205 : : /* PAGE LENGTH */
206 [ # # ]: 1186 : to_be16(vpage->alloc_len, len);
207 : 1186 : break;
208 : : }
209 : :
210 : 1186 : case SPDK_SPC_VPD_DEVICE_IDENTIFICATION: {
211 : 1186 : const char *name = spdk_bdev_get_name(bdev);
212 : 1186 : const char *product_name = spdk_bdev_get_product_name(bdev);
213 [ # # # # ]: 1186 : uint8_t protocol_id = dev->protocol_id;
214 [ # # ]: 1186 : uint8_t *buf = vpage->params;
215 : : struct spdk_scsi_desig_desc *desig;
216 : :
217 : 1186 : hlen = 4;
218 : :
219 : : /* Check total length by calculated how much space all entries take */
220 : 1186 : len = sizeof(struct spdk_scsi_desig_desc) + 8;
221 : 1186 : len += sizeof(struct spdk_scsi_desig_desc) + 8 + 16 + MAX_SERIAL_STRING;
222 : 1186 : len += sizeof(struct spdk_scsi_desig_desc) + SPDK_SCSI_DEV_MAX_NAME + 1;
223 : 1186 : len += sizeof(struct spdk_scsi_desig_desc) + SPDK_SCSI_PORT_MAX_NAME_LENGTH;
224 : 1186 : len += sizeof(struct spdk_scsi_desig_desc) + 4;
225 : 1186 : len += sizeof(struct spdk_scsi_desig_desc) + 4;
226 : 1186 : len += sizeof(struct spdk_scsi_desig_desc) + 4;
227 [ - + ]: 1186 : 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 : 1186 : desig = (struct spdk_scsi_desig_desc *)buf;
239 [ # # ]: 1186 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
240 [ # # ]: 1186 : desig->protocol_id = protocol_id;
241 [ # # ]: 1186 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_NAA;
242 [ # # ]: 1186 : desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
243 [ # # ]: 1186 : desig->reserved0 = 0;
244 [ # # ]: 1186 : desig->piv = 1;
245 [ # # # # ]: 1186 : desig->reserved1 = 0;
246 [ # # # # ]: 1186 : desig->len = 8;
247 [ # # ]: 1186 : bdev_scsi_set_naa_ieee_extended(name, desig->desig);
248 : 1186 : len = sizeof(struct spdk_scsi_desig_desc) + 8;
249 : :
250 [ # # # # : 1186 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
# # ]
251 : :
252 : : /* T10 Vendor ID designator */
253 : 1186 : desig = (struct spdk_scsi_desig_desc *)buf;
254 [ # # ]: 1186 : desig->code_set = SPDK_SPC_VPD_CODE_SET_ASCII;
255 [ # # ]: 1186 : desig->protocol_id = protocol_id;
256 [ # # ]: 1186 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_T10_VENDOR_ID;
257 [ # # ]: 1186 : desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
258 [ # # ]: 1186 : desig->reserved0 = 0;
259 [ # # ]: 1186 : desig->piv = 1;
260 [ # # # # ]: 1186 : desig->reserved1 = 0;
261 [ # # # # ]: 1186 : desig->len = 8 + 16 + MAX_SERIAL_STRING;
262 [ # # ]: 1186 : spdk_strcpy_pad(desig->desig, DEFAULT_DISK_VENDOR, 8, ' ');
263 [ # # # # ]: 1186 : spdk_strcpy_pad(&desig->desig[8], product_name, 16, ' ');
264 [ # # # # ]: 1186 : spdk_strcpy_pad(&desig->desig[24], name, MAX_SERIAL_STRING, ' ');
265 : 1186 : len += sizeof(struct spdk_scsi_desig_desc) + 8 + 16 + MAX_SERIAL_STRING;
266 : :
267 [ # # # # : 1186 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
# # ]
268 : :
269 : : /* SCSI Device Name designator */
270 : 1186 : desig = (struct spdk_scsi_desig_desc *)buf;
271 [ # # ]: 1186 : desig->code_set = SPDK_SPC_VPD_CODE_SET_UTF8;
272 [ # # ]: 1186 : desig->protocol_id = protocol_id;
273 [ # # ]: 1186 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
274 [ # # ]: 1186 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_DEVICE;
275 [ # # ]: 1186 : desig->reserved0 = 0;
276 [ # # ]: 1186 : desig->piv = 1;
277 [ # # # # ]: 1186 : desig->reserved1 = 0;
278 [ # # # # : 1186 : desig->len = bdev_scsi_pad_scsi_name(desig->desig, dev->name);
# # # # ]
279 [ # # # # ]: 1186 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
280 : :
281 [ # # # # : 1186 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
# # ]
282 : :
283 : : /* SCSI Port Name designator */
284 : 1186 : desig = (struct spdk_scsi_desig_desc *)buf;
285 [ # # ]: 1186 : desig->code_set = SPDK_SPC_VPD_CODE_SET_UTF8;
286 [ # # ]: 1186 : desig->protocol_id = protocol_id;
287 [ # # ]: 1186 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
288 [ # # ]: 1186 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
289 [ # # ]: 1186 : desig->reserved0 = 0;
290 [ # # ]: 1186 : desig->piv = 1;
291 [ # # # # ]: 1186 : desig->reserved1 = 0;
292 [ # # # # : 1186 : desig->len = snprintf(desig->desig, SPDK_SCSI_PORT_MAX_NAME_LENGTH, "%s", port->name);
# # # # ]
293 [ # # # # ]: 1186 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
294 : :
295 [ # # # # : 1186 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
# # ]
296 : :
297 : : /* Relative Target Port designator */
298 : 1186 : desig = (struct spdk_scsi_desig_desc *)buf;
299 [ # # ]: 1186 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
300 [ # # ]: 1186 : desig->protocol_id = protocol_id;
301 [ # # ]: 1186 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_RELATIVE_TARGET_PORT;
302 [ # # ]: 1186 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
303 [ # # ]: 1186 : desig->reserved0 = 0;
304 [ # # ]: 1186 : desig->piv = 1;
305 [ # # # # ]: 1186 : desig->reserved1 = 0;
306 [ # # # # ]: 1186 : desig->len = 4;
307 [ - + # # ]: 1186 : memset(desig->desig, 0, 2); /* Reserved */
308 [ # # # # : 1186 : to_be16(&desig->desig[2], port->index);
# # # # ]
309 [ # # # # ]: 1186 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
310 : :
311 [ # # # # : 1186 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
# # ]
312 : :
313 : : /* Target port group designator */
314 : 1186 : desig = (struct spdk_scsi_desig_desc *)buf;
315 [ # # ]: 1186 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
316 [ # # ]: 1186 : desig->protocol_id = protocol_id;
317 [ # # ]: 1186 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_TARGET_PORT_GROUP;
318 [ # # ]: 1186 : desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
319 [ # # ]: 1186 : desig->reserved0 = 0;
320 [ # # ]: 1186 : desig->piv = 1;
321 [ # # # # ]: 1186 : desig->reserved1 = 0;
322 [ # # # # ]: 1186 : desig->len = 4;
323 [ - + # # ]: 1186 : memset(desig->desig, 0, 4);
324 [ # # # # ]: 1186 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
325 : :
326 [ # # # # : 1186 : buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
# # ]
327 : :
328 : : /* Logical unit group designator */
329 : 1186 : desig = (struct spdk_scsi_desig_desc *)buf;
330 [ # # ]: 1186 : desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
331 [ # # ]: 1186 : desig->protocol_id = protocol_id;
332 [ # # ]: 1186 : desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_LOGICAL_UNIT_GROUP;
333 [ # # ]: 1186 : desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
334 [ # # ]: 1186 : desig->reserved0 = 0;
335 [ # # ]: 1186 : desig->piv = 1;
336 [ # # # # ]: 1186 : desig->reserved1 = 0;
337 [ # # # # ]: 1186 : desig->len = 4;
338 [ - + # # ]: 1186 : memset(desig->desig, 0, 2); /* Reserved */
339 [ # # # # : 1186 : to_be16(&desig->desig[2], dev->id);
# # # # ]
340 [ # # # # ]: 1186 : len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
341 : :
342 [ # # ]: 1186 : to_be16(vpage->alloc_len, len);
343 : :
344 : 1186 : 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 [ # # ]: 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 : 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 [ # # # # ]: 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 : 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 : 0 : }
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 : 0 : } 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 : 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 [ # # ]: 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 : 76 : default:
613 [ - + - - ]: 76 : if (pc >= 0xc0 && pc <= 0xff) {
614 [ # # # # : 0 : SPDK_DEBUGLOG(scsi, "Vendor specific INQUIRY VPD page 0x%x\n", pc);
# # ]
615 : 0 : } else {
616 : 76 : SPDK_NOTICELOG("unsupported INQUIRY VPD page 0x%x\n", pc);
617 : : }
618 : 76 : goto inq_error;
619 : : }
620 : 0 : } else {
621 : 2398 : 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 [ # # ]: 2398 : inqdata->peripheral_device_type = pd;
627 [ # # ]: 2398 : inqdata->peripheral_qualifier = SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED;
628 : :
629 : : /* RMB(7) */
630 [ # # # # ]: 2398 : inqdata->rmb = 0;
631 : :
632 : : /* VERSION */
633 : : /* See SPC3/SBC2/MMC4/SAM2 for more details */
634 [ # # # # ]: 2398 : inqdata->version = SPDK_SPC_VERSION_SPC3;
635 : :
636 : : /* NORMACA(5) HISUP(4) RESPONSE DATA FORMAT(3-0) */
637 : : /* format 2 */ /* hierarchical support */
638 [ # # # # : 2398 : inqdata->response = 2 | 1 << 4;
# # # # ]
639 : :
640 : 2398 : hlen = 5;
641 : :
642 : : /* SCCS(7) ACC(6) TPGS(5-4) 3PC(3) PROTECT(0) */
643 : : /* Not support TPGS */
644 [ # # # # ]: 2398 : inqdata->flags = 0;
645 : :
646 : : /* MULTIP */
647 [ # # # # ]: 2398 : inqdata->flags2 = 0x10;
648 : :
649 : : /* WBUS16(5) SYNC(4) LINKED(3) CMDQUE(1) VS(0) */
650 : : /* CMDQUE */
651 [ # # # # ]: 2398 : inqdata->flags3 = 0x2;
652 : :
653 : : /* T10 VENDOR IDENTIFICATION */
654 [ # # ]: 2398 : spdk_strcpy_pad(inqdata->t10_vendor_id, DEFAULT_DISK_VENDOR, 8, ' ');
655 : :
656 : : /* PRODUCT IDENTIFICATION */
657 [ # # ]: 2398 : spdk_strcpy_pad(inqdata->product_id, spdk_bdev_get_product_name(bdev), 16, ' ');
658 : :
659 : : /* PRODUCT REVISION LEVEL */
660 [ # # ]: 2398 : 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 : 2398 : len = INQUIRY_OFFSET(product_rev) - 5;
667 : :
668 [ + + ]: 2398 : if (alloc_len >= INQUIRY_OFFSET(vendor)) {
669 : : /* Vendor specific */
670 [ - + # # ]: 2398 : memset(inqdata->vendor, 0x20, 20);
671 : 2398 : len += sizeof(inqdata->vendor);
672 : 257 : }
673 : :
674 [ + + ]: 2398 : if (alloc_len >= INQUIRY_OFFSET(ius)) {
675 : : /* CLOCKING(3-2) QAS(1) IUS(0) */
676 [ # # # # ]: 2398 : inqdata->ius = 0;
677 : 2398 : len += sizeof(inqdata->ius);
678 : 257 : }
679 : :
680 [ + + ]: 2398 : if (alloc_len >= INQUIRY_OFFSET(reserved)) {
681 : : /* Reserved */
682 [ # # # # ]: 2398 : inqdata->reserved = 0;
683 : 2398 : len += sizeof(inqdata->reserved);
684 : 257 : }
685 : :
686 : : /* VERSION DESCRIPTOR 1-8 */
687 [ + + ]: 2398 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 2) {
688 [ # # # # ]: 2398 : to_be16(&inqdata->desc[0], 0x0960);
689 [ # # ]: 2398 : len += 2;
690 : 257 : }
691 : :
692 [ + + ]: 2398 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 4) {
693 [ # # # # ]: 2398 : to_be16(&inqdata->desc[2], 0x0300); /* SPC-3 (no version claimed) */
694 [ # # ]: 2398 : len += 2;
695 : 257 : }
696 : :
697 [ + + ]: 2398 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 6) {
698 [ # # # # ]: 2398 : to_be16(&inqdata->desc[4], 0x320); /* SBC-2 (no version claimed) */
699 [ # # ]: 2398 : len += 2;
700 : 257 : }
701 : :
702 [ + + ]: 2398 : if (alloc_len >= INQUIRY_OFFSET(reserved) + 8) {
703 [ # # # # ]: 2398 : to_be16(&inqdata->desc[6], 0x0040); /* SAM-2 (no version claimed) */
704 [ # # ]: 2398 : 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 [ + + ]: 2398 : if (alloc_len > INQUIRY_OFFSET(reserved) + 8) {
715 : 2398 : i = alloc_len - (INQUIRY_OFFSET(reserved) + 8);
716 [ + + ]: 2398 : if (i > 30) {
717 : 2398 : i = 30;
718 : 257 : }
719 [ - + # # : 2398 : memset(&inqdata->desc[8], 0, i);
# # ]
720 [ # # ]: 2398 : len += i;
721 : 257 : }
722 : :
723 : : /* ADDITIONAL LENGTH */
724 [ # # # # ]: 2398 : inqdata->add_len = len;
725 : : }
726 : :
727 [ # # ]: 8582 : return hlen + len;
728 : :
729 : 77 : inq_error:
730 [ # # # # ]: 77 : task->data_transferred = 0;
731 : 77 : 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 : 77 : return -1;
736 : 258 : }
737 : :
738 : : static void
739 : 20828 : mode_sense_page_init(uint8_t *buf, int len, int page, int subpage)
740 : : {
741 [ + + ]: 20828 : if (!buf) {
742 : 10414 : return;
743 : : }
744 : :
745 [ - + ]: 10414 : memset(buf, 0, len);
746 [ + + ]: 10414 : 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 [ # # # # ]: 10414 : buf[0] = page;
752 [ # # # # : 10414 : buf[1] = len - 2;
# # ]
753 : : }
754 : 32 : }
755 : :
756 : : static int
757 : 135558 : 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 : 135558 : uint8_t *cp = data;
762 : 135558 : int len = 0;
763 : : int plen;
764 : : int i;
765 : :
766 [ - + ]: 135558 : 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 [ + + + + : 135558 : switch (page) {
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + ]
784 : 2082 : case 0x00:
785 : : /* Vendor specific */
786 : 2086 : break;
787 : 2082 : case 0x01:
788 : : /* Read-Write Error Recovery */
789 [ + + - + : 2086 : SPDK_DEBUGLOG(scsi,
# # ]
790 : : "MODE_SENSE Read-Write Error Recovery\n");
791 [ - + ]: 2086 : if (subpage != 0x00) {
792 : 0 : break;
793 : : }
794 : 2086 : plen = 0x0a + 2;
795 : 2086 : mode_sense_page_init(cp, plen, page, subpage);
796 [ # # ]: 2086 : len += plen;
797 : 2086 : break;
798 : 2082 : case 0x02:
799 : : /* Disconnect-Reconnect */
800 [ + + - + : 2086 : SPDK_DEBUGLOG(scsi,
# # ]
801 : : "MODE_SENSE Disconnect-Reconnect\n");
802 [ - + ]: 2086 : if (subpage != 0x00) {
803 : 0 : break;
804 : : }
805 : 2086 : plen = 0x0e + 2;
806 : 2086 : mode_sense_page_init(cp, plen, page, subpage);
807 [ # # ]: 2086 : len += plen;
808 : 2086 : break;
809 : 2082 : case 0x03:
810 : : /* Obsolete (Format Device) */
811 : 2086 : break;
812 : 2082 : case 0x04:
813 : : /* Obsolete (Rigid Disk Geometry) */
814 : 2086 : break;
815 : 2082 : case 0x05:
816 : : /* Obsolete (Rigid Disk Geometry) */
817 : 2086 : break;
818 : 2082 : case 0x06:
819 : : /* Reserved */
820 : 2086 : break;
821 : 2082 : case 0x07:
822 : : /* Verify Error Recovery */
823 [ + + - + : 2086 : SPDK_DEBUGLOG(scsi,
# # ]
824 : : "MODE_SENSE Verify Error Recovery\n");
825 : :
826 [ - + ]: 2086 : if (subpage != 0x00) {
827 : 0 : break;
828 : : }
829 : :
830 : 2086 : plen = 0x0a + 2;
831 : 2086 : mode_sense_page_init(cp, plen, page, subpage);
832 [ # # ]: 2086 : len += plen;
833 : 2086 : break;
834 : 6222 : case 0x08: {
835 : : /* Caching */
836 [ + + - + : 6226 : SPDK_DEBUGLOG(scsi, "MODE_SENSE Caching\n");
# # ]
837 [ - + ]: 6226 : if (subpage != 0x00) {
838 : 0 : break;
839 : : }
840 : :
841 : 6226 : plen = 0x12 + 2;
842 : 6226 : mode_sense_page_init(cp, plen, page, subpage);
843 : :
844 [ + + + + : 6226 : if (cp && spdk_bdev_has_write_cache(bdev) && pc != 0x01) {
+ - ]
845 [ # # # # ]: 765 : cp[2] |= 0x4; /* WCE */
846 : 0 : }
847 : :
848 : : /* Read Cache Disable (RCD) = 1 */
849 [ + + + + ]: 6226 : if (cp && pc != 0x01) {
850 [ # # # # ]: 3113 : cp[2] |= 0x1;
851 : 2 : }
852 : :
853 [ # # ]: 6226 : len += plen;
854 : 6226 : break;
855 : : }
856 : 2082 : case 0x09:
857 : : /* Obsolete */
858 : 2086 : break;
859 [ + - - - ]: 2082 : case 0x0a:
860 [ + + - - ]: 2074 : switch (subpage) {
861 : 2082 : case 0x00:
862 : : /* Control */
863 [ + + - + : 2086 : SPDK_DEBUGLOG(scsi,
# # ]
864 : : "MODE_SENSE Control\n");
865 : 2086 : plen = 0x0a + 2;
866 : 2086 : mode_sense_page_init(cp, plen, page, subpage);
867 [ # # ]: 2086 : len += plen;
868 : 2086 : 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 : 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 : 0 : default:
889 : : /* 0x02-0x3e: Reserved */
890 : 0 : break;
891 : : }
892 : 2086 : break;
893 : 2082 : case 0x0b:
894 : : /* Obsolete (Medium Types Supported) */
895 : 2086 : break;
896 : 2082 : case 0x0c:
897 : : /* Obsolete (Notch And Partition) */
898 : 2086 : break;
899 : 2082 : case 0x0d:
900 : : /* Obsolete */
901 : 2086 : break;
902 : 4164 : case 0x0e:
903 : : case 0x0f:
904 : : /* Reserved */
905 : 4172 : break;
906 : 2082 : case 0x10:
907 : : /* XOR Control */
908 [ + + - + : 2086 : SPDK_DEBUGLOG(scsi, "MODE_SENSE XOR Control\n");
# # ]
909 [ - + ]: 2086 : if (subpage != 0x00) {
910 : 0 : break;
911 : : }
912 : 2086 : plen = 0x16 + 2;
913 : 2086 : mode_sense_page_init(cp, plen, page, subpage);
914 [ # # ]: 2086 : len += plen;
915 : 2086 : break;
916 : 6246 : case 0x11:
917 : : case 0x12:
918 : : case 0x13:
919 : : /* Reserved */
920 : 6258 : break;
921 : 2082 : case 0x14:
922 : : /* Enclosure Services Management */
923 : 2086 : break;
924 : 6246 : case 0x15:
925 : : case 0x16:
926 : : case 0x17:
927 : : /* Reserved */
928 : 6258 : break;
929 : 2082 : case 0x18:
930 : : /* Protocol-Specific LUN */
931 : 2086 : break;
932 : 2082 : case 0x19:
933 : : /* Protocol-Specific Port */
934 : 2086 : break;
935 : 2082 : case 0x1a:
936 : : /* Power Condition */
937 [ + + - + : 2086 : SPDK_DEBUGLOG(scsi,
# # ]
938 : : "MODE_SENSE Power Condition\n");
939 [ - + ]: 2086 : if (subpage != 0x00) {
940 : 0 : break;
941 : : }
942 : 2086 : plen = 0x0a + 2;
943 : 2086 : mode_sense_page_init(cp, plen, page, subpage);
944 [ # # ]: 2086 : len += plen;
945 : 2086 : break;
946 : 2082 : case 0x1b:
947 : : /* Reserved */
948 : 2086 : break;
949 : 2082 : case 0x1c:
950 : : /* Informational Exceptions Control */
951 [ + + - + : 2086 : SPDK_DEBUGLOG(scsi,
# # ]
952 : : "MODE_SENSE Informational Exceptions Control\n");
953 [ - + ]: 2086 : if (subpage != 0x00) {
954 : 0 : break;
955 : : }
956 : :
957 : 2086 : plen = 0x0a + 2;
958 : 2086 : mode_sense_page_init(cp, plen, page, subpage);
959 [ # # ]: 2086 : len += plen;
960 : 2086 : break;
961 : 6246 : case 0x1d:
962 : : case 0x1e:
963 : : case 0x1f:
964 : : /* Reserved */
965 : 6258 : break;
966 : 62460 : 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 : 62580 : break;
999 [ + - - ]: 2082 : case 0x3f:
1000 [ + + - ]: 2074 : switch (subpage) {
1001 : 2082 : case 0x00:
1002 : : /* All mode pages */
1003 [ + + # # ]: 131418 : for (i = 0x00; i < 0x3e; i ++) {
1004 [ + + ]: 193874 : len += bdev_scsi_mode_sense_page(
1005 : 248 : bdev, cdb, pc, i, 0x00,
1006 [ + + # # ]: 64790 : cp ? &cp[len] : NULL, task);
1007 : 248 : }
1008 : 2086 : 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 : 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 : 0 : default:
1023 : : /* 0x01-0x3e: Reserved */
1024 : 0 : break;
1025 : : }
1026 : 4 : }
1027 : :
1028 : 135558 : return len;
1029 : 252 : }
1030 : :
1031 : : static int
1032 : 6226 : 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 : 6226 : uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev);
1037 : 6226 : 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 [ + + + + : 6226 : assert(md == 6 || md == 10);
# # ]
1044 : :
1045 [ + + ]: 6226 : if (md == 6) {
1046 : 6218 : hlen = 4;
1047 : 6218 : blen = 8; /* For MODE SENSE 6 only short LBA */
1048 : 2 : } else {
1049 : 8 : hlen = 8;
1050 [ - + ]: 8 : blen = llbaa ? 16 : 8;
1051 : : }
1052 : :
1053 [ + + ]: 6226 : if (dbd) {
1054 : 0 : blen = 0;
1055 : 0 : }
1056 : :
1057 [ + + # # : 6226 : pages = data ? &data[hlen + blen] : NULL;
# # ]
1058 : 6230 : plen = bdev_scsi_mode_sense_page(bdev, cdb, pc, page,
1059 : 4 : subpage,
1060 : 4 : pages, task);
1061 [ + + ]: 6226 : if (plen < 0) {
1062 : 0 : return -1;
1063 : : }
1064 : :
1065 [ # # # # ]: 6226 : total = hlen + blen + plen;
1066 [ + + ]: 6226 : if (data == NULL) {
1067 : 3113 : return total;
1068 : : }
1069 : :
1070 [ # # ]: 3113 : hdr = &data[0];
1071 [ + + ]: 3113 : if (hlen == 4) {
1072 [ # # # # : 3109 : hdr[0] = total - 1; /* Mode Data Length */
# # ]
1073 [ # # # # ]: 3109 : hdr[1] = 0; /* Medium Type */
1074 [ # # # # ]: 3109 : hdr[2] = 0; /* Device-Specific Parameter */
1075 [ # # # # ]: 3109 : hdr[3] = blen; /* Block Descriptor Length */
1076 : 1 : } 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 [ # # ]: 3113 : bdesc = &data[hlen];
1086 [ - + ]: 3113 : 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 [ + + ]: 3113 : } else if (blen == 8) {
1094 : : /* Number of Blocks */
1095 [ + + ]: 3113 : if (num_blocks > 0xffffffffULL) {
1096 [ - + # # ]: 30 : memset(&bdesc[0], 0xff, 4);
1097 : 0 : } else {
1098 [ # # ]: 3083 : to_be32(&bdesc[0], num_blocks);
1099 : : }
1100 : :
1101 : : /* Block Length */
1102 [ # # ]: 3113 : to_be32(&bdesc[4], block_size);
1103 : 2 : }
1104 : :
1105 : 3113 : return total;
1106 : 4 : }
1107 : :
1108 : : static void
1109 : 3694793 : bdev_scsi_task_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
1110 : : void *cb_arg)
1111 : : {
1112 : 3694793 : struct spdk_scsi_task *task = cb_arg;
1113 : 817244 : int sc, sk, asc, ascq;
1114 : :
1115 : 3694793 : spdk_bdev_io_get_scsi_status(bdev_io, &sc, &sk, &asc, &ascq);
1116 : :
1117 : 3694793 : spdk_bdev_free_io(bdev_io);
1118 : :
1119 : 3694793 : spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
1120 [ # # # # ]: 3694793 : scsi_lun_complete_task(task->lun, task);
1121 : 3694793 : }
1122 : :
1123 : : static void
1124 : 5706429 : bdev_scsi_read_task_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
1125 : : void *cb_arg)
1126 : : {
1127 : 5706429 : struct spdk_scsi_task *task = cb_arg;
1128 : 854769 : int sc, sk, asc, ascq;
1129 : :
1130 [ # # # # ]: 5706429 : task->bdev_io = bdev_io;
1131 : :
1132 : 5706429 : spdk_bdev_io_get_scsi_status(bdev_io, &sc, &sk, &asc, &ascq);
1133 : :
1134 : 5706429 : spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
1135 [ # # # # ]: 5706429 : scsi_lun_complete_task(task->lun, task);
1136 : 5706429 : }
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 : 0 : }
1149 : :
1150 [ # # # # ]: 6 : scsi_lun_complete_reset_task(task->lun, task);
1151 : 6 : }
1152 : :
1153 : : static void
1154 : 188281 : bdev_scsi_queue_io(struct spdk_scsi_task *task, spdk_bdev_io_wait_cb cb_fn, void *cb_arg)
1155 : : {
1156 [ # # # # ]: 188281 : struct spdk_scsi_lun *lun = task->lun;
1157 [ # # # # ]: 188281 : struct spdk_bdev *bdev = lun->bdev;
1158 [ # # # # ]: 188281 : struct spdk_io_channel *ch = lun->io_channel;
1159 : : int rc;
1160 : :
1161 [ # # # # : 188281 : task->bdev_io_wait.bdev = bdev;
# # ]
1162 [ # # # # : 188281 : task->bdev_io_wait.cb_fn = cb_fn;
# # ]
1163 [ # # # # : 188281 : task->bdev_io_wait.cb_arg = cb_arg;
# # ]
1164 : :
1165 [ # # ]: 188281 : rc = spdk_bdev_queue_io_wait(bdev, ch, &task->bdev_io_wait);
1166 [ - + ]: 188281 : if (rc != 0) {
1167 [ # # ]: 0 : assert(false);
1168 : : }
1169 : 188281 : }
1170 : :
1171 : : static int
1172 : 486221 : 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 [ + + ]: 486221 : if (num_blocks == 0) {
1180 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1181 : : }
1182 : :
1183 : 486221 : bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
1184 : :
1185 [ + - + - : 486221 : if (lba >= bdev_num_blocks || num_blocks > bdev_num_blocks ||
- + ]
1186 [ - + ]: 486221 : 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 : 486224 : rc = spdk_bdev_flush_blocks(bdev_desc, bdev_ch, lba, num_blocks,
1196 : 3 : bdev_scsi_task_complete_cmd, task);
1197 : :
1198 [ + + ]: 486221 : if (rc) {
1199 [ + - ]: 59713 : if (rc == -ENOMEM) {
1200 : 59713 : bdev_scsi_queue_io(task, bdev_scsi_process_block_resubmit, task);
1201 : 59713 : 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 [ # # # # ]: 426508 : task->data_transferred = 0;
1211 : 426508 : return SPDK_SCSI_TASK_PENDING;
1212 : 3 : }
1213 : :
1214 : : static uint64_t
1215 : 9061067 : _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 [ + - ]: 9061067 : if (spdk_likely(spdk_u32_is_pow2(block_size))) {
1222 : 9061067 : shift_cnt = spdk_u32log2(block_size);
1223 [ - + # # ]: 9061067 : *offset_blocks = offset_bytes >> shift_cnt;
1224 [ - + # # ]: 9061067 : *num_blocks = num_bytes >> shift_cnt;
1225 [ - + # # ]: 9061077 : return (offset_bytes - (*offset_blocks << shift_cnt)) |
1226 [ - + # # ]: 9061067 : (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 : 9060992 : 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 : 1672018 : uint64_t bdev_num_blocks, offset_blocks, num_blocks;
1240 : : uint32_t max_xfer_len, block_size;
1241 : 9060992 : int sk = SPDK_SCSI_SENSE_NO_SENSE, asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
1242 : : int rc;
1243 : :
1244 [ # # # # ]: 9060992 : task->data_transferred = 0;
1245 : :
1246 [ + + + + : 9060992 : 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 : 9060992 : bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
1253 [ + + + + ]: 9060992 : if (spdk_unlikely(bdev_num_blocks <= lba || bdev_num_blocks - lba < xfer_len)) {
1254 [ + + - + : 14 : SPDK_DEBUGLOG(scsi, "end of media\n");
# # ]
1255 : 14 : sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
1256 : 14 : asc = SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1257 : 14 : goto check_condition;
1258 : : }
1259 : :
1260 [ + + ]: 9060978 : if (spdk_unlikely(xfer_len == 0)) {
1261 [ # # # # ]: 4 : task->status = SPDK_SCSI_STATUS_GOOD;
1262 : 4 : return SPDK_SCSI_TASK_COMPLETE;
1263 : : }
1264 : :
1265 : 9060974 : 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 [ - + ]: 9060974 : max_xfer_len = SPDK_WORK_BLOCK_SIZE / block_size;
1269 [ + + ]: 9060974 : 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 [ + + # # ]: 9060970 : if (!is_read) {
1278 : : /* Additional check for Transfer Length */
1279 [ - + # # : 3308330 : 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 [ - + # # : 9060970 : 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 : 9060970 : offset_blocks += lba;
1293 : :
1294 [ + + - + : 9060970 : SPDK_DEBUGLOG(scsi,
- - # # ]
1295 : : "%s: lba=%"PRIu64", len=%"PRIu64"\n",
1296 : : is_read ? "Read" : "Write", offset_blocks, num_blocks);
1297 : :
1298 [ + + # # ]: 9060970 : if (is_read) {
1299 [ # # # # : 5752647 : 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 [ - + # # ]: 3308337 : } 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 : 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 [ # # # # : 3308333 : 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 [ + + ]: 9060970 : if (rc) {
1333 [ + - ]: 86268 : if (rc == -ENOMEM) {
1334 : 86268 : bdev_scsi_queue_io(task, bdev_scsi_process_block_resubmit, task);
1335 : 86268 : 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 [ # # # # : 8974702 : task->data_transferred = task->length;
# # # # ]
1343 : 8974702 : return SPDK_SCSI_TASK_PENDING;
1344 : :
1345 : 14 : check_condition:
1346 : 18 : spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, sk, asc,
1347 : : SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
1348 : 18 : 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 : 42300 : bdev_scsi_split_resubmit(void *arg)
1367 : : {
1368 : 42300 : struct spdk_bdev_scsi_split_ctx *ctx = arg;
1369 : :
1370 : 42300 : bdev_scsi_split(ctx);
1371 : 42300 : }
1372 : :
1373 : : static int
1374 : 797570 : bdev_scsi_split(struct spdk_bdev_scsi_split_ctx *ctx)
1375 : : {
1376 [ # # # # ]: 797570 : struct spdk_scsi_task *task = ctx->task;
1377 [ # # # # : 797570 : uint8_t opcode = task->cdb[0];
# # # # ]
1378 : : int rc;
1379 : :
1380 [ + + # # : 1830965 : while (ctx->remaining_count != 0) {
# # ]
1381 [ # # # # : 1075713 : rc = ctx->fn(ctx);
# # # # ]
1382 [ + + ]: 1075713 : if (rc == 0) {
1383 [ # # ]: 1033395 : ctx->current_count++;
1384 [ # # ]: 1033395 : ctx->remaining_count--;
1385 [ # # ]: 1033395 : ctx->outstanding_count++;
1386 : 1033395 : continue;
1387 [ + - ]: 42318 : } else if (rc == -ENOMEM) {
1388 : 42318 : 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 [ + + # # : 797570 : 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 : 755270 : return SPDK_SCSI_TASK_PENDING;
1406 : : }
1407 : :
1408 [ + - ]: 42300 : 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 : 42300 : bdev_scsi_queue_io(task, bdev_scsi_split_resubmit, ctx);
1412 : 42300 : 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 : 1033395 : bdev_scsi_task_complete_split_cmd(struct spdk_bdev_io *bdev_io, bool success,
1421 : : void *cb_arg)
1422 : : {
1423 : 1033395 : struct spdk_bdev_scsi_split_ctx *ctx = cb_arg;
1424 [ # # # # ]: 1033395 : struct spdk_scsi_task *task = ctx->task;
1425 : :
1426 : 1033395 : spdk_bdev_free_io(bdev_io);
1427 : :
1428 [ + + # # ]: 1033395 : 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 [ # # ]: 1033395 : ctx->outstanding_count--;
1439 [ + + # # : 1033395 : if (ctx->outstanding_count != 0) {
# # ]
1440 : : /* Any child I/O is still outstanding. */
1441 : 278125 : return;
1442 : : }
1443 : :
1444 [ + + # # : 755270 : if (ctx->remaining_count == 0) {
# # ]
1445 : : /* SCSI task finishes when all descriptors are consumed. */
1446 [ # # # # ]: 755252 : scsi_lun_complete_task(task->lun, task);
1447 : 755252 : free(ctx);
1448 : 755252 : return;
1449 : : }
1450 : :
1451 : : /* Continue with splitting process. */
1452 : 18 : bdev_scsi_split(ctx);
1453 : 10 : }
1454 : :
1455 : : static int
1456 : 755155 : __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 [ + + ]: 755155 : if (!data) {
1462 : 0 : return -EINVAL;
1463 : : }
1464 : :
1465 [ - + ]: 755155 : if (data_len < 8) {
1466 : : /* We can't even get the reported length, so fail. */
1467 : 0 : return -EINVAL;
1468 : : }
1469 : :
1470 [ # # ]: 755155 : desc_data_len = from_be16(&data[2]);
1471 [ # # ]: 755155 : desc_count = desc_data_len / 16;
1472 : :
1473 [ - + ]: 755155 : 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 [ - + ]: 755155 : 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 [ - + - + : 755155 : memcpy(ctx->desc, &data[8], desc_data_len);
# # # # #
# ]
1486 : 755155 : return desc_count;
1487 : 3 : }
1488 : :
1489 : : static int
1490 : 797483 : _bdev_scsi_unmap(struct spdk_bdev_scsi_split_ctx *ctx)
1491 : : {
1492 [ # # # # ]: 797483 : struct spdk_scsi_task *task = ctx->task;
1493 [ # # # # ]: 797483 : 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 [ # # # # : 797483 : desc = &ctx->desc[ctx->current_count];
# # # # #
# # # ]
1499 : :
1500 [ # # ]: 797483 : offset_blocks = from_be64(&desc->lba);
1501 [ # # ]: 797483 : num_blocks = from_be32(&desc->block_count);
1502 : :
1503 [ # # # # ]: 797499 : 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 : : }
1510 : :
1511 : : static int
1512 : 755155 : 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 : 755155 : int desc_count = -1;
1517 : 18 : int data_len;
1518 : :
1519 [ + + # # : 755155 : assert(task->status == SPDK_SCSI_STATUS_GOOD);
# # # # ]
1520 : :
1521 : 755155 : ctx = calloc(1, sizeof(*ctx));
1522 [ + + ]: 755155 : 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 [ # # # # ]: 755155 : ctx->task = task;
1531 [ # # # # ]: 755155 : ctx->current_count = 0;
1532 [ # # # # ]: 755155 : ctx->outstanding_count = 0;
1533 [ # # # # ]: 755155 : ctx->fn = _bdev_scsi_unmap;
1534 : :
1535 [ + - # # : 755155 : if (task->iovcnt == 1) {
# # ]
1536 [ # # # # : 755155 : data = (uint8_t *)task->iovs[0].iov_base;
# # # # #
# ]
1537 [ # # # # : 755155 : data_len = task->iovs[0].iov_len;
# # # # #
# ]
1538 : 755155 : 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 [ + - ]: 755155 : if (desc_count > 0) {
1548 [ # # # # ]: 755155 : ctx->remaining_count = desc_count;
1549 : 755155 : 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 : 278230 : _bdev_scsi_write_same(struct spdk_bdev_scsi_split_ctx *ctx)
1565 : : {
1566 [ # # # # ]: 278230 : struct spdk_scsi_task *task = ctx->task;
1567 [ # # # # ]: 278230 : struct spdk_scsi_lun *lun = task->lun;
1568 : : uint64_t offset_blocks;
1569 : :
1570 [ # # # # : 278230 : offset_blocks = ctx->start_offset_blocks + ctx->current_count;
# # # # #
# ]
1571 [ # # # # : 278230 : 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 : : }
1574 : :
1575 : : static int
1576 : 97 : 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 : 43 : uint64_t bdev_num_blocks, offset_blocks, num_blocks;
1582 : : uint32_t max_xfer_len, block_size;
1583 : 97 : int sk = SPDK_SCSI_SENSE_NO_SENSE, asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
1584 : :
1585 [ # # # # ]: 97 : task->data_transferred = 0;
1586 : :
1587 [ - + # # : 97 : 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 : 97 : block_size = spdk_bdev_get_data_block_size(bdev);
1593 [ - + # # : 97 : 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 [ - + ]: 97 : if (spdk_unlikely(xfer_len == 0)) {
1600 [ # # # # ]: 0 : task->status = SPDK_SCSI_STATUS_GOOD;
1601 : 0 : return SPDK_SCSI_TASK_COMPLETE;
1602 : : }
1603 : :
1604 : 97 : bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
1605 [ + - - + ]: 97 : 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 [ - + ]: 97 : max_xfer_len = SPDK_WORK_BLOCK_SIZE / block_size;
1614 [ - + ]: 97 : 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 [ - + # # : 97 : if (_bytes_to_blocks(block_size, task->offset, &offset_blocks,
# # # # ]
1623 [ # # # # ]: 97 : (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 : 97 : offset_blocks += lba;
1631 [ - + - + : 97 : SPDK_DEBUGLOG(scsi, "Writesame: lba=%"PRIu64", len=%"PRIu64"\n",
# # ]
1632 : : offset_blocks, num_blocks);
1633 : :
1634 : 97 : ctx = calloc(1, sizeof(*ctx));
1635 [ - + ]: 97 : if (!ctx) {
1636 : 0 : SPDK_ERRLOG("No enough memory on SCSI WRITE SAME\n");
1637 : 0 : goto check_condition;
1638 : : }
1639 : :
1640 [ # # # # ]: 97 : ctx->task = task;
1641 [ # # # # : 97 : ctx->start_offset_blocks = offset_blocks;
# # ]
1642 [ # # # # ]: 97 : ctx->current_count = 0;
1643 [ # # # # ]: 97 : ctx->outstanding_count = 0;
1644 [ # # # # ]: 97 : ctx->remaining_count = xfer_len;
1645 [ # # # # ]: 97 : ctx->fn = _bdev_scsi_write_same;
1646 : :
1647 [ # # # # : 97 : task->data_transferred = task->length;
# # # # ]
1648 : :
1649 : 97 : return bdev_scsi_split(ctx);
1650 : :
1651 : 0 : 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 : 10316981 : bdev_scsi_process_block(struct spdk_scsi_task *task)
1659 : : {
1660 [ # # # # ]: 10316981 : struct spdk_scsi_lun *lun = task->lun;
1661 [ # # # # ]: 10316981 : struct spdk_bdev *bdev = lun->bdev;
1662 : : uint64_t lba;
1663 : : uint32_t xfer_len;
1664 : 10316981 : uint32_t len = 0;
1665 [ # # # # ]: 10316981 : uint8_t *cdb = task->cdb;
1666 : :
1667 : : /* XXX: We need to support FUA bit for writes! */
1668 [ - + + + : 10316981 : 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 : 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 : 7961553 : case SPDK_SBC_READ_10:
1683 : : case SPDK_SBC_WRITE_10:
1684 [ # # ]: 7961553 : lba = from_be32(&cdb[2]);
1685 [ # # ]: 7961553 : xfer_len = from_be16(&cdb[7]);
1686 [ # # # # : 7961553 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
# # # # ]
1687 : 0 : task, lba, xfer_len,
1688 [ # # # # ]: 7961553 : cdb[0] == SPDK_SBC_READ_10, false);
1689 : :
1690 : 1 : case SPDK_SBC_READ_12:
1691 : : case SPDK_SBC_WRITE_12:
1692 [ # # ]: 1 : lba = from_be32(&cdb[2]);
1693 [ # # ]: 1 : xfer_len = from_be32(&cdb[6]);
1694 [ # # # # : 1 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
# # # # ]
1695 : 0 : task, lba, xfer_len,
1696 [ # # # # ]: 1 : cdb[0] == SPDK_SBC_READ_12, false);
1697 : 1099423 : case SPDK_SBC_READ_16:
1698 : : case SPDK_SBC_WRITE_16:
1699 [ # # ]: 1099438 : lba = from_be64(&cdb[2]);
1700 [ # # ]: 1099438 : xfer_len = from_be32(&cdb[10]);
1701 [ # # # # : 1099453 : return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
# # # # ]
1702 : 15 : task, lba, xfer_len,
1703 [ # # # # ]: 1099438 : 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 : 0 : task, lba, num_blocks, false, true);
1734 : : }
1735 : :
1736 : 177 : case SPDK_SBC_READ_CAPACITY_10: {
1737 : 177 : uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev);
1738 : 7 : uint8_t buffer[8];
1739 : :
1740 [ + + ]: 177 : if (num_blocks - 1 > 0xffffffffULL) {
1741 [ - + ]: 2 : memset(buffer, 0xff, 4);
1742 : 0 : } else {
1743 : 175 : to_be32(buffer, num_blocks - 1);
1744 : : }
1745 [ # # # # ]: 177 : to_be32(&buffer[4], spdk_bdev_get_data_block_size(bdev));
1746 : :
1747 [ # # # # : 177 : len = spdk_min(task->length, sizeof(buffer));
# # # # #
# ]
1748 [ - + ]: 177 : if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) {
1749 : 0 : break;
1750 : : }
1751 : :
1752 [ # # # # ]: 177 : task->data_transferred = len;
1753 [ # # # # ]: 177 : task->status = SPDK_SCSI_STATUS_GOOD;
1754 : 177 : break;
1755 : : }
1756 : :
1757 : 1045 : case SPDK_SPC_SERVICE_ACTION_IN_16:
1758 [ + - # # : 1045 : switch (cdb[1] & 0x1f) { /* SERVICE ACTION */
# # ]
1759 : 1045 : case SPDK_SBC_SAI_READ_CAPACITY_16: {
1760 : 1045 : uint8_t buffer[32] = {0};
1761 : : uint32_t lbppb, lbppbe;
1762 : :
1763 [ # # # # ]: 1045 : to_be64(&buffer[0], spdk_bdev_get_num_blocks(bdev) - 1);
1764 [ # # # # ]: 1045 : to_be32(&buffer[8], spdk_bdev_get_data_block_size(bdev));
1765 [ - + ]: 1045 : lbppb = spdk_bdev_get_physical_block_size(bdev) / spdk_bdev_get_data_block_size(bdev);
1766 : 1045 : lbppbe = spdk_u32log2(lbppb);
1767 [ - + ]: 1045 : if (lbppbe > 0xf) {
1768 : 0 : SPDK_ERRLOG("lbppbe(0x%x) > 0xf\n", lbppbe);
1769 : 0 : } else {
1770 [ # # # # : 1045 : 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 [ + + ]: 1045 : if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
1778 [ # # # # : 1035 : buffer[14] |= 1 << 7;
# # # # #
# ]
1779 : 0 : }
1780 : :
1781 [ - + # # : 1045 : len = spdk_min(from_be32(&cdb[10]), sizeof(buffer));
# # ]
1782 [ - + ]: 1045 : if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) {
1783 : 0 : break;
1784 : : }
1785 : :
1786 [ # # # # ]: 1045 : task->data_transferred = len;
1787 [ # # # # ]: 1045 : task->status = SPDK_SCSI_STATUS_GOOD;
1788 : 1045 : break;
1789 : : }
1790 : :
1791 : 0 : default:
1792 : 0 : return SPDK_SCSI_TASK_UNKNOWN;
1793 : : }
1794 : 964 : break;
1795 : :
1796 : 486218 : case SPDK_SBC_SYNCHRONIZE_CACHE_10:
1797 : : case SPDK_SBC_SYNCHRONIZE_CACHE_16:
1798 [ + + # # : 486221 : if (cdb[0] == SPDK_SBC_SYNCHRONIZE_CACHE_10) {
# # ]
1799 [ # # ]: 48 : lba = from_be32(&cdb[2]);
1800 [ # # ]: 48 : len = from_be16(&cdb[7]);
1801 : 0 : } else {
1802 [ # # ]: 486173 : lba = from_be64(&cdb[2]);
1803 [ # # ]: 486173 : len = from_be32(&cdb[10]);
1804 : : }
1805 : :
1806 [ + + ]: 486221 : if (len == 0) {
1807 : 48 : len = spdk_bdev_get_num_blocks(bdev) - lba;
1808 : 0 : }
1809 : :
1810 [ # # # # : 486221 : return bdev_scsi_sync(bdev, lun->bdev_desc, lun->io_channel, task, lba, len);
# # # # ]
1811 : : break;
1812 : :
1813 : 755152 : case SPDK_SBC_UNMAP:
1814 : 755155 : return bdev_scsi_unmap(bdev, task);
1815 : :
1816 : 97 : case SPDK_SBC_WRITE_SAME_10:
1817 [ # # ]: 97 : lba = from_be32(&cdb[2]);
1818 [ # # ]: 97 : xfer_len = from_be16(&cdb[7]);
1819 [ # # # # : 97 : return bdev_scsi_write_same(bdev, lun->bdev_desc, lun->io_channel,
# # # # ]
1820 [ # # # # ]: 97 : 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 : 13032 : default:
1830 : 13294 : return SPDK_SCSI_TASK_UNKNOWN;
1831 : : }
1832 : :
1833 : 1222 : return SPDK_SCSI_TASK_COMPLETE;
1834 : 283 : }
1835 : :
1836 : : static void
1837 : 145981 : bdev_scsi_process_block_resubmit(void *arg)
1838 : : {
1839 : 145981 : struct spdk_scsi_task *task = arg;
1840 : :
1841 : 145981 : bdev_scsi_process_block(task);
1842 : 145981 : }
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 : 2 : }
1858 : :
1859 : : static int
1860 : 13294 : bdev_scsi_process_primary(struct spdk_scsi_task *task)
1861 : : {
1862 [ # # # # ]: 13294 : struct spdk_scsi_lun *lun = task->lun;
1863 [ # # # # ]: 13294 : struct spdk_bdev *bdev = lun->bdev;
1864 : 13294 : int alloc_len = -1;
1865 : 13294 : int data_len = -1;
1866 [ # # # # ]: 13294 : uint8_t *cdb = task->cdb;
1867 : 13294 : uint8_t *data = NULL;
1868 : 13294 : int rc = 0;
1869 : 13294 : int pllen, md = 0;
1870 : : int llba;
1871 : : int dbd, pc, page, subpage;
1872 : 13294 : int cmd_parsed = 0;
1873 : :
1874 [ + + + + : 13294 : switch (cdb[0]) {
+ - - + +
+ - - - -
+ # # #
# ]
1875 : 8405 : case SPDK_SPC_INQUIRY:
1876 [ # # ]: 8663 : alloc_len = from_be16(&cdb[3]);
1877 [ + - ]: 8663 : data_len = spdk_max(4096, alloc_len);
1878 : 8663 : data = calloc(1, data_len);
1879 [ + + # # ]: 8663 : assert(data != NULL);
1880 : 8663 : rc = bdev_scsi_inquiry(bdev, task, cdb, data, data_len);
1881 [ + - ]: 8663 : data_len = spdk_min(rc, data_len);
1882 [ + + ]: 8663 : if (rc < 0) {
1883 : 81 : break;
1884 : : }
1885 : :
1886 [ + + - + : 8582 : SPDK_LOGDUMP(scsi, "INQUIRY", data, data_len);
# # ]
1887 : 8582 : 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 : 6 : 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 : 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 [ + + ]: 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 : 3108 : case SPDK_SPC_MODE_SENSE_6:
1955 [ # # # # ]: 3109 : alloc_len = cdb[4];
1956 : 3109 : md = 6;
1957 : : /* FALLTHROUGH */
1958 : 3111 : case SPDK_SPC_MODE_SENSE_10:
1959 : 3113 : llba = 0;
1960 : :
1961 [ + + ]: 3113 : if (md == 0) {
1962 [ # # ]: 4 : alloc_len = from_be16(&cdb[7]);
1963 [ # # # # ]: 4 : llba = !!(cdb[1] & 0x10);
1964 : 4 : md = 10;
1965 : 1 : }
1966 : :
1967 [ # # # # ]: 3113 : dbd = !!(cdb[1] & 0x8);
1968 [ # # # # : 3113 : pc = (cdb[2] & 0xc0) >> 6;
# # ]
1969 [ # # # # ]: 3113 : page = cdb[2] & 0x3f;
1970 [ # # # # ]: 3113 : subpage = cdb[3];
1971 : :
1972 : : /* First call with no buffer to discover needed buffer size */
1973 : 3115 : rc = bdev_scsi_mode_sense(bdev, md,
1974 : 2 : cdb, dbd, llba, pc,
1975 : 2 : page, subpage,
1976 : 2 : NULL, task);
1977 [ + + ]: 3113 : if (rc < 0) {
1978 : 0 : break;
1979 : : }
1980 : :
1981 : 3113 : data_len = rc;
1982 : 3113 : data = calloc(1, data_len);
1983 [ + + # # ]: 3113 : assert(data != NULL);
1984 : :
1985 : : /* First call with no buffer to discover needed buffer size */
1986 : 3115 : rc = bdev_scsi_mode_sense(bdev, md,
1987 : 2 : cdb, dbd, llba, pc,
1988 : 2 : page, subpage,
1989 : 2 : data, task);
1990 [ + + ]: 3113 : 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 : 3113 : 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 : 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 : 1231 : case SPDK_SPC_TEST_UNIT_READY:
2048 [ - + - + : 1231 : SPDK_DEBUGLOG(scsi, "TEST_UNIT_READY\n");
# # ]
2049 : 1231 : cmd_parsed = 1;
2050 : : /* FALLTHROUGH */
2051 : 1231 : case SPDK_SBC_START_STOP_UNIT:
2052 [ - + ]: 1231 : if (!cmd_parsed) {
2053 [ # # # # : 0 : SPDK_DEBUGLOG(scsi, "START_STOP_UNIT\n");
# # ]
2054 : 0 : }
2055 : :
2056 : 1231 : rc = 0;
2057 : 1231 : 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 : 0 : }
2099 : 0 : data_len = 0;
2100 : 0 : }
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 : 140 : default:
2109 : 140 : return SPDK_SCSI_TASK_UNKNOWN;
2110 : : }
2111 : :
2112 [ + + + + ]: 13154 : if (rc >= 0 && data_len > 0) {
2113 [ + + # # ]: 11834 : assert(alloc_len >= 0);
2114 [ + + ]: 11834 : spdk_scsi_task_scatter_data(task, data, spdk_min(alloc_len, data_len));
2115 [ + + ]: 11834 : rc = spdk_min(data_len, alloc_len);
2116 : 259 : }
2117 : :
2118 [ + + ]: 13154 : if (rc >= 0) {
2119 [ # # # # ]: 13073 : task->data_transferred = rc;
2120 [ # # # # ]: 13073 : task->status = SPDK_SCSI_STATUS_GOOD;
2121 : 261 : }
2122 : :
2123 [ + + ]: 13154 : if (data) {
2124 : 11919 : free(data);
2125 : 261 : }
2126 : :
2127 : 13154 : return SPDK_SCSI_TASK_COMPLETE;
2128 : 262 : }
2129 : :
2130 : : int
2131 : 10171000 : bdev_scsi_execute(struct spdk_scsi_task *task)
2132 : : {
2133 : : int rc;
2134 : :
2135 [ + + ]: 10171000 : if ((rc = bdev_scsi_process_block(task)) == SPDK_SCSI_TASK_UNKNOWN) {
2136 [ + + ]: 13294 : if ((rc = bdev_scsi_process_primary(task)) == SPDK_SCSI_TASK_UNKNOWN) {
2137 [ - + - + : 140 : SPDK_DEBUGLOG(scsi, "unsupported SCSI OP=0x%x\n", task->cdb[0]);
# # # # #
# # # #
# ]
2138 : : /* INVALID COMMAND OPERATION CODE */
2139 : 140 : 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 : 140 : return SPDK_SCSI_TASK_COMPLETE;
2144 : : }
2145 : 262 : }
2146 : :
2147 : 10170860 : 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 : 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 : 0 : task);
2166 [ - + ]: 6 : if (rc == -ENOMEM) {
2167 : 0 : bdev_scsi_queue_io(task, bdev_scsi_reset_resubmit, task);
2168 : 0 : }
2169 : 6 : }
2170 : :
2171 : : bool
2172 : 6107460 : bdev_scsi_get_dif_ctx(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
2173 : : struct spdk_dif_ctx *dif_ctx)
2174 : : {
2175 : 6107460 : uint32_t ref_tag = 0, dif_check_flags = 0, data_offset;
2176 : : uint8_t *cdb;
2177 : : int rc;
2178 : 9 : struct spdk_dif_ctx_init_ext_opts dif_opts;
2179 : :
2180 [ + + ]: 6107460 : if (spdk_likely(spdk_bdev_get_md_size(bdev) == 0)) {
2181 : 6107448 : 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 : 3 : 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 : 3 : 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 : 3 : 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 : 0 : }
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 : 0 : }
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 : 3 : spdk_bdev_get_block_size(bdev),
2221 : 3 : 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 : 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 : 12 : return (rc == 0) ? true : false;
2229 : 3 : }
|