Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2016 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : /*
7 : : * NVMe end-to-end data protection test
8 : : */
9 : :
10 : : #include "spdk/stdinc.h"
11 : :
12 : : #include "spdk/nvme.h"
13 : : #include "spdk/env.h"
14 : : #include "spdk/crc16.h"
15 : : #include "spdk/endian.h"
16 : : #include "spdk/memory.h"
17 : :
18 : : #define MAX_DEVS 64
19 : :
20 : : #define DATA_PATTERN 0x5A
21 : :
22 : : struct dev {
23 : : struct spdk_nvme_ctrlr *ctrlr;
24 : : char name[SPDK_NVMF_TRADDR_MAX_LEN + 1];
25 : : };
26 : :
27 : : static struct dev devs[MAX_DEVS];
28 : : static int num_devs = 0;
29 : : static struct spdk_nvme_transport_id g_trid = {};
30 : :
31 : : #define foreach_dev(iter) \
32 : : for (iter = devs; iter - devs < num_devs; iter++)
33 : :
34 : : static int io_complete_flag = 0;
35 : :
36 : : struct io_request {
37 : : void *contig;
38 : : void *metadata;
39 : : bool use_extended_lba;
40 : : bool use_sgl;
41 : : uint32_t sgl_offset;
42 : : uint32_t buf_size;
43 : : uint64_t lba;
44 : : uint32_t lba_count;
45 : : uint16_t apptag_mask;
46 : : uint16_t apptag;
47 : : };
48 : :
49 : : static void
50 : 0 : io_complete(void *ctx, const struct spdk_nvme_cpl *cpl)
51 : : {
52 [ # # # # ]: 0 : if (spdk_nvme_cpl_is_error(cpl)) {
53 : 0 : io_complete_flag = 2;
54 : : } else {
55 : 0 : io_complete_flag = 1;
56 : : }
57 : 0 : }
58 : :
59 : : static void
60 : 0 : ns_data_buffer_reset(struct spdk_nvme_ns *ns, struct io_request *req, uint8_t data_pattern)
61 : : {
62 : : uint32_t md_size, sector_size;
63 : 0 : uint32_t i, offset = 0;
64 : : uint8_t *buf;
65 : :
66 : 0 : sector_size = spdk_nvme_ns_get_sector_size(ns);
67 : 0 : md_size = spdk_nvme_ns_get_md_size(ns);
68 : :
69 [ # # ]: 0 : for (i = 0; i < req->lba_count; i++) {
70 [ # # # # ]: 0 : if (req->use_extended_lba) {
71 : 0 : offset = (sector_size + md_size) * i;
72 : : } else {
73 : 0 : offset = sector_size * i;
74 : : }
75 : :
76 : 0 : buf = (uint8_t *)req->contig + offset;
77 [ # # ]: 0 : memset(buf, data_pattern, sector_size);
78 : : }
79 : 0 : }
80 : :
81 : : static void
82 : 0 : nvme_req_reset_sgl(void *cb_arg, uint32_t sgl_offset)
83 : : {
84 : 0 : struct io_request *req = (struct io_request *)cb_arg;
85 : :
86 : 0 : req->sgl_offset = sgl_offset;
87 : 0 : return;
88 : : }
89 : :
90 : : static int
91 : 0 : nvme_req_next_sge(void *cb_arg, void **address, uint32_t *length)
92 : : {
93 : 0 : struct io_request *req = (struct io_request *)cb_arg;
94 : : void *payload;
95 : :
96 : 0 : payload = req->contig + req->sgl_offset;
97 : 0 : *address = payload;
98 : :
99 : 0 : *length = req->buf_size - req->sgl_offset;
100 : :
101 : 0 : return 0;
102 : : }
103 : :
104 : : /* CRC-16 Guard checked for extended lba format */
105 : : static uint32_t
106 : 0 : dp_guard_check_extended_lba_test(struct spdk_nvme_ns *ns, struct io_request *req,
107 : : uint32_t *io_flags)
108 : : {
109 : : struct spdk_nvme_protection_info *pi;
110 : : uint32_t md_size, sector_size, chksum_size;
111 : :
112 : 0 : req->lba_count = 2;
113 : :
114 : : /* extended LBA only for the test case */
115 [ # # ]: 0 : if (!(spdk_nvme_ns_supports_extended_lba(ns))) {
116 : 0 : return 0;
117 : : }
118 : :
119 : 0 : sector_size = spdk_nvme_ns_get_sector_size(ns);
120 : 0 : md_size = spdk_nvme_ns_get_md_size(ns);
121 : 0 : chksum_size = sector_size + md_size - 8;
122 : 0 : req->contig = spdk_zmalloc((sector_size + md_size) * req->lba_count, 0x1000, NULL,
123 : : SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
124 [ # # ]: 0 : assert(req->contig);
125 : :
126 : 0 : req->lba = 0;
127 : 0 : req->use_extended_lba = true;
128 : 0 : req->use_sgl = true;
129 : 0 : req->buf_size = (sector_size + md_size) * req->lba_count;
130 : 0 : req->metadata = NULL;
131 : 0 : ns_data_buffer_reset(ns, req, DATA_PATTERN);
132 : 0 : pi = (struct spdk_nvme_protection_info *)(req->contig + chksum_size);
133 : : /* big-endian for guard */
134 : 0 : to_be16(&pi->guard, spdk_crc16_t10dif(0, req->contig, chksum_size));
135 : :
136 : 0 : pi = (struct spdk_nvme_protection_info *)(req->contig + (sector_size + md_size) * 2 - 8);
137 : 0 : to_be16(&pi->guard, spdk_crc16_t10dif(0, req->contig + sector_size + md_size, chksum_size));
138 : :
139 : 0 : *io_flags = SPDK_NVME_IO_FLAGS_PRCHK_GUARD;
140 : :
141 : 0 : return req->lba_count;
142 : : }
143 : :
144 : : /*
145 : : * No protection information with PRACT setting to 1,
146 : : * both extended LBA format and separate metadata can
147 : : * run the test case.
148 : : */
149 : : static uint32_t
150 : 0 : dp_with_pract_test(struct spdk_nvme_ns *ns, struct io_request *req,
151 : : uint32_t *io_flags)
152 : : {
153 : : uint32_t md_size, sector_size, data_len;
154 : :
155 : 0 : req->lba_count = 8;
156 : 0 : req->use_extended_lba = spdk_nvme_ns_supports_extended_lba(ns) ? true : false;
157 : :
158 : 0 : sector_size = spdk_nvme_ns_get_sector_size(ns);
159 : 0 : md_size = spdk_nvme_ns_get_md_size(ns);
160 [ # # ]: 0 : if (md_size == 8) {
161 : : /* No additional metadata buffer provided */
162 : 0 : data_len = sector_size * req->lba_count;
163 : 0 : req->use_extended_lba = false;
164 : : } else {
165 : 0 : data_len = (sector_size + md_size) * req->lba_count;
166 : : }
167 : 0 : req->contig = spdk_zmalloc(data_len, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
168 : : SPDK_MALLOC_DMA);
169 [ # # ]: 0 : assert(req->contig);
170 : :
171 : 0 : req->metadata = spdk_zmalloc(md_size * req->lba_count, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
172 : : SPDK_MALLOC_DMA);
173 [ # # ]: 0 : assert(req->metadata);
174 : :
175 [ # # # ]: 0 : switch (spdk_nvme_ns_get_pi_type(ns)) {
176 : 0 : case SPDK_NVME_FMT_NVM_PROTECTION_TYPE3:
177 : 0 : *io_flags = SPDK_NVME_IO_FLAGS_PRCHK_GUARD | SPDK_NVME_IO_FLAGS_PRACT;
178 : 0 : break;
179 : 0 : case SPDK_NVME_FMT_NVM_PROTECTION_TYPE1:
180 : : case SPDK_NVME_FMT_NVM_PROTECTION_TYPE2:
181 : 0 : *io_flags = SPDK_NVME_IO_FLAGS_PRCHK_GUARD | SPDK_NVME_IO_FLAGS_PRCHK_REFTAG |
182 : : SPDK_NVME_IO_FLAGS_PRACT;
183 : 0 : break;
184 : 0 : default:
185 : 0 : *io_flags = 0;
186 : 0 : break;
187 : : }
188 : :
189 : 0 : req->lba = 0;
190 : :
191 : 0 : return req->lba_count;
192 : : }
193 : :
194 : : /* Block Reference Tag checked for TYPE1 and TYPE2 with PRACT setting to 0 */
195 : : static uint32_t
196 : 0 : dp_without_pract_extended_lba_test(struct spdk_nvme_ns *ns, struct io_request *req,
197 : : uint32_t *io_flags)
198 : : {
199 : : struct spdk_nvme_protection_info *pi;
200 : : uint32_t md_size, sector_size;
201 : :
202 : 0 : req->lba_count = 2;
203 : :
204 [ # # ]: 0 : switch (spdk_nvme_ns_get_pi_type(ns)) {
205 : 0 : case SPDK_NVME_FMT_NVM_PROTECTION_TYPE3:
206 : 0 : return 0;
207 : 0 : default:
208 : 0 : break;
209 : : }
210 : :
211 : : /* extended LBA only for the test case */
212 [ # # ]: 0 : if (!(spdk_nvme_ns_supports_extended_lba(ns))) {
213 : 0 : return 0;
214 : : }
215 : :
216 : 0 : sector_size = spdk_nvme_ns_get_sector_size(ns);
217 : 0 : md_size = spdk_nvme_ns_get_md_size(ns);
218 : 0 : req->contig = spdk_zmalloc((sector_size + md_size) * req->lba_count, 0x1000, NULL,
219 : : SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
220 [ # # ]: 0 : assert(req->contig);
221 : :
222 : 0 : req->lba = 0;
223 : 0 : req->use_extended_lba = true;
224 : 0 : req->metadata = NULL;
225 : 0 : pi = (struct spdk_nvme_protection_info *)(req->contig + sector_size + md_size - 8);
226 : : /* big-endian for reference tag */
227 : 0 : to_be32(&pi->ref_tag, (uint32_t)req->lba);
228 : :
229 : 0 : pi = (struct spdk_nvme_protection_info *)(req->contig + (sector_size + md_size) * 2 - 8);
230 : : /* is incremented for each subsequent logical block */
231 : 0 : to_be32(&pi->ref_tag, (uint32_t)(req->lba + 1));
232 : :
233 : 0 : *io_flags = SPDK_NVME_IO_FLAGS_PRCHK_REFTAG;
234 : :
235 : 0 : return req->lba_count;
236 : : }
237 : :
238 : : /* LBA + Metadata without data protection bits setting */
239 : : static uint32_t
240 : 0 : dp_without_flags_extended_lba_test(struct spdk_nvme_ns *ns, struct io_request *req,
241 : : uint32_t *io_flags)
242 : : {
243 : : uint32_t md_size, sector_size;
244 : :
245 : 0 : req->lba_count = 16;
246 : :
247 : : /* extended LBA only for the test case */
248 [ # # ]: 0 : if (!(spdk_nvme_ns_supports_extended_lba(ns))) {
249 : 0 : return 0;
250 : : }
251 : :
252 : 0 : sector_size = spdk_nvme_ns_get_sector_size(ns);
253 : 0 : md_size = spdk_nvme_ns_get_md_size(ns);
254 : 0 : req->contig = spdk_zmalloc((sector_size + md_size) * req->lba_count, 0x1000, NULL,
255 : : SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
256 [ # # ]: 0 : assert(req->contig);
257 : :
258 : 0 : req->lba = 0;
259 : 0 : req->use_extended_lba = true;
260 : 0 : req->metadata = NULL;
261 : 0 : *io_flags = 0;
262 : :
263 : 0 : return req->lba_count;
264 : : }
265 : :
266 : : /* Block Reference Tag checked for TYPE1 and TYPE2 with PRACT setting to 0 */
267 : : static uint32_t
268 : 0 : dp_without_pract_separate_meta_test(struct spdk_nvme_ns *ns, struct io_request *req,
269 : : uint32_t *io_flags)
270 : : {
271 : : struct spdk_nvme_protection_info *pi;
272 : : uint32_t md_size, sector_size;
273 : :
274 : 0 : req->lba_count = 2;
275 : :
276 [ # # ]: 0 : switch (spdk_nvme_ns_get_pi_type(ns)) {
277 : 0 : case SPDK_NVME_FMT_NVM_PROTECTION_TYPE3:
278 : 0 : return 0;
279 : 0 : default:
280 : 0 : break;
281 : : }
282 : :
283 : : /* separate metadata payload for the test case */
284 [ # # ]: 0 : if (spdk_nvme_ns_supports_extended_lba(ns)) {
285 : 0 : return 0;
286 : : }
287 : :
288 : 0 : sector_size = spdk_nvme_ns_get_sector_size(ns);
289 : 0 : md_size = spdk_nvme_ns_get_md_size(ns);
290 : 0 : req->contig = spdk_zmalloc(sector_size * req->lba_count, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
291 : : SPDK_MALLOC_DMA);
292 [ # # ]: 0 : assert(req->contig);
293 : :
294 : 0 : req->metadata = spdk_zmalloc(md_size * req->lba_count, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
295 : : SPDK_MALLOC_DMA);
296 [ # # ]: 0 : assert(req->metadata);
297 : :
298 : 0 : req->lba = 0;
299 : 0 : req->use_extended_lba = false;
300 : :
301 : : /* last 8 bytes if the metadata size bigger than 8 */
302 : 0 : pi = (struct spdk_nvme_protection_info *)(req->metadata + md_size - 8);
303 : : /* big-endian for reference tag */
304 : 0 : to_be32(&pi->ref_tag, (uint32_t)req->lba);
305 : :
306 : 0 : pi = (struct spdk_nvme_protection_info *)(req->metadata + md_size * 2 - 8);
307 : : /* is incremented for each subsequent logical block */
308 : 0 : to_be32(&pi->ref_tag, (uint32_t)(req->lba + 1));
309 : :
310 : 0 : *io_flags = SPDK_NVME_IO_FLAGS_PRCHK_REFTAG;
311 : :
312 : 0 : return req->lba_count;
313 : : }
314 : :
315 : : /* Application Tag checked with PRACT setting to 0 */
316 : : static uint32_t
317 : 0 : dp_without_pract_separate_meta_apptag_test(struct spdk_nvme_ns *ns,
318 : : struct io_request *req,
319 : : uint32_t *io_flags)
320 : : {
321 : : struct spdk_nvme_protection_info *pi;
322 : : uint32_t md_size, sector_size;
323 : :
324 : 0 : req->lba_count = 1;
325 : :
326 : : /* separate metadata payload for the test case */
327 [ # # ]: 0 : if (spdk_nvme_ns_supports_extended_lba(ns)) {
328 : 0 : return 0;
329 : : }
330 : :
331 : 0 : sector_size = spdk_nvme_ns_get_sector_size(ns);
332 : 0 : md_size = spdk_nvme_ns_get_md_size(ns);
333 : 0 : req->contig = spdk_zmalloc(sector_size * req->lba_count, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
334 : : SPDK_MALLOC_DMA);
335 [ # # ]: 0 : assert(req->contig);
336 : :
337 : 0 : req->metadata = spdk_zmalloc(md_size * req->lba_count, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
338 : : SPDK_MALLOC_DMA);
339 [ # # ]: 0 : assert(req->metadata);
340 : :
341 : 0 : req->lba = 0;
342 : 0 : req->use_extended_lba = false;
343 : 0 : req->apptag_mask = 0xFFFF;
344 : 0 : req->apptag = req->lba_count;
345 : :
346 : : /* last 8 bytes if the metadata size bigger than 8 */
347 : 0 : pi = (struct spdk_nvme_protection_info *)(req->metadata + md_size - 8);
348 : 0 : to_be16(&pi->app_tag, req->lba_count);
349 : :
350 : 0 : *io_flags = SPDK_NVME_IO_FLAGS_PRCHK_APPTAG;
351 : :
352 : 0 : return req->lba_count;
353 : : }
354 : :
355 : : /*
356 : : * LBA + Metadata without data protection bits setting,
357 : : * separate metadata payload for the test case.
358 : : */
359 : : static uint32_t
360 : 0 : dp_without_flags_separate_meta_test(struct spdk_nvme_ns *ns, struct io_request *req,
361 : : uint32_t *io_flags)
362 : : {
363 : : uint32_t md_size, sector_size;
364 : :
365 : 0 : req->lba_count = 16;
366 : :
367 : : /* separate metadata payload for the test case */
368 [ # # ]: 0 : if (spdk_nvme_ns_supports_extended_lba(ns)) {
369 : 0 : return 0;
370 : : }
371 : :
372 : 0 : sector_size = spdk_nvme_ns_get_sector_size(ns);
373 : 0 : md_size = spdk_nvme_ns_get_md_size(ns);
374 : 0 : req->contig = spdk_zmalloc(sector_size * req->lba_count, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
375 : : SPDK_MALLOC_DMA);
376 [ # # ]: 0 : assert(req->contig);
377 : :
378 : 0 : req->metadata = spdk_zmalloc(md_size * req->lba_count, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
379 : : SPDK_MALLOC_DMA);
380 [ # # ]: 0 : assert(req->metadata);
381 : :
382 : 0 : req->lba = 0;
383 : 0 : req->use_extended_lba = false;
384 : 0 : *io_flags = 0;
385 : :
386 : 0 : return req->lba_count;
387 : : }
388 : :
389 : : typedef uint32_t (*nvme_build_io_req_fn_t)(struct spdk_nvme_ns *ns, struct io_request *req,
390 : : uint32_t *lba_count);
391 : :
392 : : static void
393 : 0 : free_req(struct io_request *req)
394 : : {
395 [ # # ]: 0 : if (req == NULL) {
396 : 0 : return;
397 : : }
398 : :
399 [ # # ]: 0 : if (req->contig) {
400 : 0 : spdk_free(req->contig);
401 : : }
402 : :
403 [ # # ]: 0 : if (req->metadata) {
404 : 0 : spdk_free(req->metadata);
405 : : }
406 : :
407 : 0 : spdk_free(req);
408 : : }
409 : :
410 : : static int
411 : 0 : ns_data_buffer_compare(struct spdk_nvme_ns *ns, struct io_request *req, uint8_t data_pattern)
412 : : {
413 : : uint32_t md_size, sector_size;
414 : 0 : uint32_t i, j, offset = 0;
415 : : uint8_t *buf;
416 : :
417 : 0 : sector_size = spdk_nvme_ns_get_sector_size(ns);
418 : 0 : md_size = spdk_nvme_ns_get_md_size(ns);
419 : :
420 [ # # ]: 0 : for (i = 0; i < req->lba_count; i++) {
421 [ # # # # ]: 0 : if (req->use_extended_lba) {
422 : 0 : offset = (sector_size + md_size) * i;
423 : : } else {
424 : 0 : offset = sector_size * i;
425 : : }
426 : :
427 : 0 : buf = (uint8_t *)req->contig + offset;
428 [ # # ]: 0 : for (j = 0; j < sector_size; j++) {
429 [ # # ]: 0 : if (buf[j] != data_pattern) {
430 : 0 : return -1;
431 : : }
432 : : }
433 : : }
434 : :
435 : 0 : return 0;
436 : : }
437 : :
438 : : static int
439 : 70 : write_read_e2e_dp_tests(struct dev *dev, nvme_build_io_req_fn_t build_io_fn, const char *test_name)
440 : : {
441 : 70 : int rc = 0;
442 : : uint32_t lba_count;
443 : 70 : uint32_t io_flags = 0;
444 : :
445 : : struct io_request *req;
446 : : struct spdk_nvme_ns *ns;
447 : : struct spdk_nvme_qpair *qpair;
448 : : const struct spdk_nvme_ns_data *nsdata;
449 : :
450 : 70 : ns = spdk_nvme_ctrlr_get_ns(dev->ctrlr, 1);
451 [ - + ]: 70 : if (!ns) {
452 [ # # ]: 0 : printf("Null namespace\n");
453 : 0 : return 0;
454 : : }
455 : :
456 [ + - ]: 70 : if (!(spdk_nvme_ns_get_flags(ns) & SPDK_NVME_NS_DPS_PI_SUPPORTED)) {
457 : 70 : return 0;
458 : : }
459 : :
460 : 0 : nsdata = spdk_nvme_ns_get_data(ns);
461 [ # # # # ]: 0 : if (!nsdata || !spdk_nvme_ns_get_sector_size(ns)) {
462 [ # # # # ]: 0 : fprintf(stderr, "Empty nsdata or wrong sector size\n");
463 : 0 : return -EINVAL;
464 : : }
465 : :
466 : 0 : req = spdk_zmalloc(sizeof(*req), 0, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
467 [ # # ]: 0 : assert(req);
468 : :
469 : : /* IO parameters setting */
470 : 0 : lba_count = build_io_fn(ns, req, &io_flags);
471 [ # # ]: 0 : if (!lba_count) {
472 [ # # ]: 0 : printf("%s: %s bypass the test case\n", dev->name, test_name);
473 : 0 : free_req(req);
474 : 0 : return 0;
475 : : }
476 : :
477 : 0 : qpair = spdk_nvme_ctrlr_alloc_io_qpair(dev->ctrlr, NULL, 0);
478 [ # # ]: 0 : if (!qpair) {
479 : 0 : free_req(req);
480 : 0 : return -1;
481 : : }
482 : :
483 : 0 : ns_data_buffer_reset(ns, req, DATA_PATTERN);
484 [ # # # # : 0 : if (req->use_extended_lba && req->use_sgl) {
# # # # ]
485 : 0 : rc = spdk_nvme_ns_cmd_writev(ns, qpair, req->lba, lba_count, io_complete, req, io_flags,
486 : : nvme_req_reset_sgl, nvme_req_next_sge);
487 [ # # # # ]: 0 : } else if (req->use_extended_lba) {
488 : 0 : rc = spdk_nvme_ns_cmd_write(ns, qpair, req->contig, req->lba, lba_count,
489 : : io_complete, req, io_flags);
490 : : } else {
491 : 0 : rc = spdk_nvme_ns_cmd_write_with_md(ns, qpair, req->contig, req->metadata, req->lba, lba_count,
492 : 0 : io_complete, req, io_flags, req->apptag_mask, req->apptag);
493 : : }
494 : :
495 [ # # ]: 0 : if (rc != 0) {
496 [ # # # # ]: 0 : fprintf(stderr, "%s: %s write submit failed\n", dev->name, test_name);
497 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
498 : 0 : free_req(req);
499 : 0 : return -1;
500 : : }
501 : :
502 : 0 : io_complete_flag = 0;
503 : :
504 [ # # ]: 0 : while (!io_complete_flag) {
505 : 0 : spdk_nvme_qpair_process_completions(qpair, 1);
506 : : }
507 : :
508 [ # # ]: 0 : if (io_complete_flag != 1) {
509 [ # # # # ]: 0 : fprintf(stderr, "%s: %s write exec failed\n", dev->name, test_name);
510 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
511 : 0 : free_req(req);
512 : 0 : return -1;
513 : : }
514 : :
515 : : /* reset completion flag */
516 : 0 : io_complete_flag = 0;
517 : :
518 : 0 : ns_data_buffer_reset(ns, req, 0);
519 [ # # # # : 0 : if (req->use_extended_lba && req->use_sgl) {
# # # # ]
520 : 0 : rc = spdk_nvme_ns_cmd_readv(ns, qpair, req->lba, lba_count, io_complete, req, io_flags,
521 : : nvme_req_reset_sgl, nvme_req_next_sge);
522 : :
523 [ # # # # ]: 0 : } else if (req->use_extended_lba) {
524 : 0 : rc = spdk_nvme_ns_cmd_read(ns, qpair, req->contig, req->lba, lba_count,
525 : : io_complete, req, io_flags);
526 : : } else {
527 : 0 : rc = spdk_nvme_ns_cmd_read_with_md(ns, qpair, req->contig, req->metadata, req->lba, lba_count,
528 : 0 : io_complete, req, io_flags, req->apptag_mask, req->apptag);
529 : : }
530 : :
531 [ # # ]: 0 : if (rc != 0) {
532 [ # # # # ]: 0 : fprintf(stderr, "%s: %s read failed\n", dev->name, test_name);
533 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
534 : 0 : free_req(req);
535 : 0 : return -1;
536 : : }
537 : :
538 [ # # ]: 0 : while (!io_complete_flag) {
539 : 0 : spdk_nvme_qpair_process_completions(qpair, 1);
540 : : }
541 : :
542 [ # # ]: 0 : if (io_complete_flag != 1) {
543 [ # # # # ]: 0 : fprintf(stderr, "%s: %s read failed\n", dev->name, test_name);
544 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
545 : 0 : free_req(req);
546 : 0 : return -1;
547 : : }
548 : :
549 : 0 : rc = ns_data_buffer_compare(ns, req, DATA_PATTERN);
550 [ # # ]: 0 : if (rc < 0) {
551 [ # # # # ]: 0 : fprintf(stderr, "%s: %s write/read success, but memcmp Failed\n", dev->name, test_name);
552 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
553 : 0 : free_req(req);
554 : 0 : return -1;
555 : : }
556 : :
557 [ # # ]: 0 : printf("%s: %s test passed\n", dev->name, test_name);
558 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
559 : 0 : free_req(req);
560 : 0 : return 0;
561 : : }
562 : :
563 : : static bool
564 : 0 : probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
565 : : struct spdk_nvme_ctrlr_opts *opts)
566 : : {
567 [ # # ]: 0 : printf("Attaching to %s\n", trid->traddr);
568 : :
569 : 0 : return true;
570 : : }
571 : :
572 : : static void
573 : 10 : add_ctrlr(struct spdk_nvme_ctrlr *ctrlr)
574 : : {
575 : : struct dev *dev;
576 : :
577 : : /* add to dev list */
578 : 10 : dev = &devs[num_devs++];
579 : :
580 : 10 : dev->ctrlr = ctrlr;
581 : :
582 [ - + ]: 10 : snprintf(dev->name, sizeof(dev->name), "%s",
583 : 10 : spdk_nvme_ctrlr_get_transport_id(ctrlr)->traddr);
584 : :
585 [ - + ]: 10 : printf("Attached to %s\n", dev->name);
586 : 10 : }
587 : :
588 : : static void
589 : 10 : attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
590 : : struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
591 : : {
592 : 10 : add_ctrlr(ctrlr);
593 : 10 : }
594 : :
595 : : static int
596 : 6 : parse_args(int argc, char **argv)
597 : : {
598 : : int op;
599 : :
600 : 6 : spdk_nvme_trid_populate_transport(&g_trid, SPDK_NVME_TRANSPORT_PCIE);
601 [ - + ]: 6 : snprintf(g_trid.subnqn, sizeof(g_trid.subnqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
602 : :
603 [ - + - + : 6 : while ((op = getopt(argc, argv, "r:")) != -1) {
- + ]
604 [ # # ]: 0 : switch (op) {
605 : 0 : case 'r':
606 [ # # ]: 0 : if (spdk_nvme_transport_id_parse(&g_trid, optarg) != 0) {
607 [ # # # # ]: 0 : fprintf(stderr, "Error parsing transport address\n");
608 : 0 : return -EINVAL;
609 : : }
610 : 0 : break;
611 : 0 : default:
612 [ # # # # ]: 0 : fprintf(stderr, "Usage: %s [-r trid]\n", argv[0]);
613 : 0 : return -EINVAL;
614 : : }
615 : : }
616 : :
617 : 6 : return 0;
618 : : }
619 : :
620 : : int
621 : 6 : main(int argc, char **argv)
622 : : {
623 : : struct dev *iter;
624 : : int rc;
625 : 6 : struct spdk_env_opts opts;
626 : 6 : struct spdk_nvme_detach_ctx *detach_ctx = NULL;
627 : : struct spdk_nvme_ctrlr *ctrlr;
628 : :
629 : 6 : spdk_env_opts_init(&opts);
630 : 6 : opts.name = "nvme_dp";
631 : 6 : opts.core_mask = "0x1";
632 : 6 : opts.shm_id = 0;
633 [ - + ]: 6 : if (spdk_env_init(&opts) < 0) {
634 [ # # # # ]: 0 : fprintf(stderr, "Unable to initialize SPDK env\n");
635 : 0 : return 1;
636 : : }
637 : :
638 [ - + ]: 6 : if (parse_args(argc, argv) != 0) {
639 : 0 : return 1;
640 : : }
641 : :
642 [ - + ]: 6 : printf("NVMe Write/Read with End-to-End data protection test\n");
643 : :
644 [ - + ]: 6 : if (g_trid.traddr[0] != '\0') {
645 : 0 : ctrlr = spdk_nvme_connect(&g_trid, NULL, 0);
646 [ # # ]: 0 : if (ctrlr == NULL) {
647 [ # # # # ]: 0 : fprintf(stderr, "nvme_connect() failed\n");
648 : 0 : return 1;
649 : : }
650 : :
651 : 0 : add_ctrlr(ctrlr);
652 [ - + ]: 6 : } else if (spdk_nvme_probe(&g_trid, NULL, probe_cb, attach_cb, NULL) != 0) {
653 [ # # # # ]: 0 : fprintf(stderr, "nvme_probe() failed\n");
654 : 0 : exit(1);
655 : : }
656 : :
657 [ - + ]: 6 : if (num_devs == 0) {
658 [ # # # # ]: 0 : fprintf(stderr, "No valid NVMe controllers found\n");
659 : 0 : return 1;
660 : : }
661 : :
662 : 6 : rc = 0;
663 [ + + ]: 16 : foreach_dev(iter) {
664 : : #define TEST(x) write_read_e2e_dp_tests(iter, x, #x)
665 [ + - ]: 10 : if (TEST(dp_with_pract_test)
666 [ + - ]: 10 : || TEST(dp_guard_check_extended_lba_test)
667 [ + - ]: 10 : || TEST(dp_without_pract_extended_lba_test)
668 [ + - ]: 10 : || TEST(dp_without_flags_extended_lba_test)
669 [ + - ]: 10 : || TEST(dp_without_pract_separate_meta_test)
670 [ + - ]: 10 : || TEST(dp_without_pract_separate_meta_apptag_test)
671 [ - + ]: 10 : || TEST(dp_without_flags_separate_meta_test)) {
672 : : #undef TEST
673 : 0 : rc = 1;
674 [ # # ]: 0 : printf("%s: failed End-to-End data protection tests\n", iter->name);
675 : : }
676 : : }
677 : :
678 [ - + ]: 6 : printf("Cleaning up...\n");
679 : :
680 [ + + ]: 16 : foreach_dev(iter) {
681 : 10 : spdk_nvme_detach_async(iter->ctrlr, &detach_ctx);
682 : : }
683 : :
684 [ - + ]: 6 : if (detach_ctx) {
685 : 0 : spdk_nvme_detach_poll(detach_ctx);
686 : : }
687 : :
688 : 6 : return rc;
689 : : }
|