Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : : #include "spdk/nvme.h"
8 : : #include "spdk/env.h"
9 : : #include "spdk/util.h"
10 : :
11 : : #define FDP_LOG_PAGE_SIZE 4096
12 : : #define FDP_NR_RUHS_DESC 256
13 : : #define MAX_FDP_EVENTS 0xFF
14 : :
15 : : #define SET_EVENT_TYPES ((uint8_t[]){0x0, 0x1, 0x2, 0x3, 0x80, 0x81})
16 : :
17 : : struct ns_entry {
18 : : struct spdk_nvme_ctrlr *ctrlr;
19 : : struct spdk_nvme_ns *ns;
20 : : struct ns_entry *next;
21 : : };
22 : :
23 : : static struct ns_entry *g_namespaces = NULL;
24 : : static struct spdk_nvme_transport_id g_trid;
25 : : static bool g_use_trid = false;
26 : :
27 : : static int g_outstanding_commands;
28 : : static int g_fdp_command_result;
29 : : static uint32_t g_feat_result;
30 : : static uint16_t ph_for_fdp_event;
31 : : static uint8_t rgif;
32 : : static uint8_t fdpci;
33 : : static uint16_t pid_for_ruhu;
34 : : static uint32_t g_spdk_sge_size = 4096;
35 : :
36 : : static union spdk_nvme_feat_fdp_cdw12 fdp_res;
37 : : static uint8_t g_fdp_cfg_log_page_buf[FDP_LOG_PAGE_SIZE];
38 : : static uint8_t g_fdp_ruhu_log_page_buf[FDP_LOG_PAGE_SIZE];
39 : : static uint8_t g_fdp_events_log_page_buf[FDP_LOG_PAGE_SIZE];
40 : :
41 : : static struct spdk_nvme_fdp_stats_log_page g_fdp_stats_log_page;
42 : : static struct spdk_nvme_fdp_cfg_log_page *g_fdp_cfg_log_page = (void *)g_fdp_cfg_log_page_buf;
43 : : static struct spdk_nvme_fdp_ruhu_log_page *g_fdp_ruhu_log_page = (void *)g_fdp_ruhu_log_page_buf;
44 : : static struct spdk_nvme_fdp_events_log_page *g_fdp_events_log_page = (void *)
45 : : g_fdp_events_log_page_buf;
46 : :
47 : : struct io_request {
48 : : void *contig;
49 : : uint32_t sgl_offset;
50 : : uint32_t buf_size;
51 : : };
52 : :
53 : : static void
54 : 2 : nvme_req_reset_sgl(void *cb_arg, uint32_t sgl_offset)
55 : : {
56 : 2 : struct io_request *req = (struct io_request *)cb_arg;
57 : :
58 : 2 : req->sgl_offset = sgl_offset;
59 : 2 : }
60 : :
61 : : static int
62 : 16 : nvme_req_next_sge(void *cb_arg, void **address, uint32_t *length)
63 : : {
64 : 16 : struct io_request *req = (struct io_request *)cb_arg;
65 : : uint32_t iov_len;
66 : :
67 : 16 : *address = req->contig;
68 : :
69 [ + + ]: 16 : if (req->sgl_offset) {
70 : 14 : *address += req->sgl_offset;
71 : : }
72 : :
73 : 16 : iov_len = req->buf_size - req->sgl_offset;
74 [ + + ]: 16 : if (iov_len > g_spdk_sge_size) {
75 : 14 : iov_len = g_spdk_sge_size;
76 : : }
77 : :
78 : 16 : req->sgl_offset += iov_len;
79 : 16 : *length = iov_len;
80 : :
81 : 16 : return 0;
82 : : }
83 : :
84 : : static void
85 : 3 : get_feat_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
86 : : {
87 [ + - - + ]: 3 : if (spdk_nvme_cpl_is_error(cpl)) {
88 : 0 : g_fdp_command_result = -1;
89 : : } else {
90 : 3 : g_fdp_command_result = 0;
91 : 3 : g_feat_result = cpl->cdw0;
92 : : }
93 : :
94 : 3 : g_outstanding_commands--;
95 : 3 : }
96 : :
97 : : static void
98 : 7 : cmd_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
99 : : {
100 [ + - - + ]: 7 : if (spdk_nvme_cpl_is_error(cpl)) {
101 : 0 : g_fdp_command_result = -1;
102 : : } else {
103 : 7 : g_fdp_command_result = 0;
104 : : }
105 : :
106 : 7 : g_outstanding_commands--;
107 : 7 : }
108 : :
109 : : static void
110 : 0 : print_uint128_hex(uint64_t *v)
111 : : {
112 : 0 : unsigned long long lo = v[0], hi = v[1];
113 [ # # ]: 0 : if (hi) {
114 [ # # ]: 0 : printf("0x%llX%016llX", hi, lo);
115 : : } else {
116 [ # # ]: 0 : printf("0x%llX", lo);
117 : : }
118 : 0 : }
119 : :
120 : : static void
121 : 3 : print_uint128_dec(uint64_t *v)
122 : : {
123 : 3 : unsigned long long lo = v[0], hi = v[1];
124 [ - + ]: 3 : if (hi) {
125 : : /* can't handle large (>64-bit) decimal values for now, so fall back to hex */
126 : 0 : print_uint128_hex(v);
127 : : } else {
128 [ - + ]: 3 : printf("%llu", (unsigned long long)lo);
129 : : }
130 : 3 : }
131 : :
132 : : static int
133 : 1 : set_fdp_events(struct spdk_nvme_ns *ns)
134 : : {
135 : : int ret;
136 : 1 : uint8_t fdp_event_type_list[6] = {};
137 : 1 : uint32_t nfdp_events = 6;
138 : : uint32_t cdw11, cdw12;
139 : 1 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
140 : 1 : int nsid = spdk_nvme_ns_get_id(ns);
141 : :
142 [ - + - + ]: 1 : memcpy(fdp_event_type_list, SET_EVENT_TYPES, nfdp_events);
143 : 1 : g_outstanding_commands = 0;
144 : 1 : g_fdp_command_result = -1;
145 : :
146 : 1 : cdw11 = (nfdp_events << 16) | ph_for_fdp_event;
147 : : /* Enable FDP event */
148 : 1 : cdw12 = 1;
149 : :
150 : 1 : ret = spdk_nvme_ctrlr_cmd_set_feature_ns(ctrlr, SPDK_NVME_FEAT_FDP_EVENTS, cdw11, cdw12,
151 : : fdp_event_type_list, nfdp_events,
152 : : get_feat_completion, NULL, nsid);
153 [ - + ]: 1 : if (ret) {
154 [ # # # # ]: 0 : fprintf(stderr, "Set Feature (fdp events) failed\n\n");
155 : 0 : return -1;
156 : : }
157 : :
158 : 1 : g_outstanding_commands++;
159 [ + + ]: 19 : while (g_outstanding_commands) {
160 : 18 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
161 : : }
162 : :
163 [ - + ]: 1 : if (g_fdp_command_result) {
164 [ # # # # ]: 0 : fprintf(stderr, "Set Feature (fdp events) failed\n\n");
165 : 0 : return -1;
166 : : }
167 : :
168 [ - + - + ]: 1 : fprintf(stdout, "Set Feature: Enabling FDP events on Placement handle: #%u Success\n\n",
169 : : ph_for_fdp_event);
170 : 1 : return 0;
171 : : }
172 : :
173 : : static int
174 : 1 : get_fdp_events(struct spdk_nvme_ns *ns)
175 : : {
176 : : int ret;
177 : : uint32_t i, cdw11;
178 : 1 : struct spdk_nvme_fdp_event_desc events[MAX_FDP_EVENTS];
179 : : struct spdk_nvme_fdp_event_desc *event_desc;
180 : 1 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
181 : 1 : int nsid = spdk_nvme_ns_get_id(ns);
182 : :
183 : 1 : g_outstanding_commands = 0;
184 : 1 : g_fdp_command_result = -1;
185 : 1 : g_feat_result = 0;
186 : :
187 : 1 : cdw11 = (MAX_FDP_EVENTS << 16) | ph_for_fdp_event;
188 : :
189 : 1 : ret = spdk_nvme_ctrlr_cmd_get_feature_ns(ctrlr, SPDK_NVME_FEAT_FDP_EVENTS, cdw11,
190 : : events, MAX_FDP_EVENTS * sizeof(struct spdk_nvme_fdp_event_desc),
191 : : get_feat_completion, NULL, nsid);
192 [ - + ]: 1 : if (ret) {
193 [ # # # # ]: 0 : fprintf(stderr, "Get Feature (fdp events) failed\n\n");
194 : 0 : return -1;
195 : : }
196 : :
197 : 1 : g_outstanding_commands++;
198 [ + + ]: 8 : while (g_outstanding_commands) {
199 : 7 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
200 : : }
201 : :
202 [ - + ]: 1 : if (g_fdp_command_result) {
203 [ # # # # ]: 0 : fprintf(stderr, "Get Feature (fdp events) failed\n\n");
204 : 0 : return -1;
205 : : }
206 : :
207 [ - + - + ]: 1 : fprintf(stdout, "Get Feature: FDP Events for Placement handle: #%u\n", ph_for_fdp_event);
208 [ - + - + ]: 1 : fprintf(stdout, "========================\n");
209 [ - + - + ]: 1 : fprintf(stdout, "Number of FDP Events: %u\n", g_feat_result);
210 : :
211 : 1 : event_desc = events;
212 [ + + ]: 7 : for (i = 0; i < g_feat_result; i++) {
213 [ - + - + ]: 6 : fprintf(stdout, "FDP Event: #%u Type: %s", i,
214 [ + + ]: 6 : event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_RU_NOT_WRITTEN_CAPACITY ?
215 : : "RU Not Written to Capacity " :
216 : 5 : event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_RU_TIME_LIMIT_EXCEEDED ?
217 [ + + ]: 9 : "RU Time Limit Exceeded " :
218 : 4 : event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_CTRLR_RESET_MODIFY_RUH ?
219 [ + + ]: 7 : "Ctrlr Reset Modified RUH's " :
220 : 3 : event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_INVALID_PLACEMENT_ID ?
221 [ + + ]: 5 : "Invalid Placement Identifier " :
222 [ + + ]: 3 : event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_MEDIA_REALLOCATED ? "Media Reallocated " :
223 : 1 : event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_IMPLICIT_MODIFIED_RUH ?
224 [ + - ]: 1 : "Implicitly modified RUH " :
225 : : "Reserved");
226 [ - + - + ]: 6 : fprintf(stdout, " Enabled: %s\n",
227 [ + + ]: 6 : event_desc->fdpeta.bits.fdp_ee ? "Yes" : "No");
228 : 6 : event_desc++;
229 : : }
230 : :
231 [ - + ]: 1 : fprintf(stdout, "\n");
232 : 1 : return 0;
233 : : }
234 : :
235 : : static int
236 : 1 : get_fdp(struct spdk_nvme_ns *ns)
237 : : {
238 : : int ret;
239 : : uint32_t cdw11;
240 : 1 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
241 : 1 : const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
242 : :
243 : 1 : g_outstanding_commands = 0;
244 : 1 : g_fdp_command_result = -1;
245 : 1 : g_feat_result = 0;
246 : :
247 : 1 : cdw11 = nsdata->endgid;
248 : :
249 : 1 : ret = spdk_nvme_ctrlr_cmd_get_feature(ctrlr, SPDK_NVME_FEAT_FDP, cdw11, NULL, 0,
250 : : get_feat_completion, NULL);
251 [ - + ]: 1 : if (ret) {
252 [ # # # # ]: 0 : fprintf(stderr, "Get Feature (fdp) failed\n\n");
253 : 0 : return -1;
254 : : }
255 : :
256 : 1 : g_outstanding_commands++;
257 [ + + ]: 3 : while (g_outstanding_commands) {
258 : 2 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
259 : : }
260 : :
261 [ - + ]: 1 : if (g_fdp_command_result) {
262 [ # # # # ]: 0 : fprintf(stderr, "Get Feature (fdp) failed\n\n");
263 : 0 : return -1;
264 : : }
265 : :
266 : 1 : fdp_res.raw = g_feat_result;
267 : :
268 [ - + - + ]: 1 : fprintf(stdout, "Get Feature: FDP:\n");
269 [ - + - + ]: 1 : fprintf(stdout, "=================\n");
270 [ - + - + ]: 1 : fprintf(stdout, " Enabled: %s\n",
271 [ + - ]: 1 : fdp_res.bits.fdpe ? "Yes" : "No");
272 [ - + - + ]: 1 : fprintf(stdout, " FDP configuration Index: %u\n\n", fdp_res.bits.fdpci);
273 : :
274 : 1 : return 0;
275 : : }
276 : :
277 : : static int
278 : 1 : check_fdp_write(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair)
279 : : {
280 : : int ret;
281 : : uint32_t sector_size, lba_count;
282 : : uint64_t lba;
283 : : struct io_request *req;
284 : 1 : struct spdk_nvme_ns_cmd_ext_io_opts ext_opts;
285 : :
286 : 1 : g_outstanding_commands = 0;
287 : 1 : g_fdp_command_result = -1;
288 : :
289 : 1 : ext_opts.size = SPDK_SIZEOF(&ext_opts, cdw13);
290 : 1 : ext_opts.io_flags = SPDK_NVME_IO_FLAGS_DATA_PLACEMENT_DIRECTIVE;
291 : 1 : ext_opts.metadata = NULL;
292 [ - + ]: 1 : ext_opts.cdw13 = (pid_for_ruhu << 16);
293 : :
294 : 1 : sector_size = spdk_nvme_ns_get_sector_size(ns);
295 : :
296 : 1 : req = spdk_zmalloc(sizeof(*req), 0, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
297 [ - + ]: 1 : assert(req);
298 : :
299 : 1 : lba = 0;
300 : 1 : lba_count = 8;
301 : 1 : req->buf_size = sector_size * lba_count;
302 : 1 : req->contig = spdk_zmalloc(req->buf_size, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
303 : : SPDK_MALLOC_DMA);
304 [ - + ]: 1 : assert(req->contig);
305 : :
306 : 1 : ret = spdk_nvme_ns_cmd_writev_ext(ns, qpair, lba, lba_count, cmd_completion, req,
307 : : nvme_req_reset_sgl, nvme_req_next_sge, &ext_opts);
308 : :
309 [ - + ]: 1 : if (ret) {
310 [ # # # # ]: 0 : fprintf(stderr, "spdk_nvme_ns_cmd_writev_ext failed\n\n");
311 : 0 : return -1;
312 : : }
313 : :
314 : 1 : g_outstanding_commands++;
315 [ + + ]: 167 : while (g_outstanding_commands) {
316 : 166 : spdk_nvme_qpair_process_completions(qpair, 100);
317 : : }
318 : :
319 [ - + ]: 1 : if (g_fdp_command_result) {
320 [ # # # # ]: 0 : fprintf(stderr, "FDP write on placement id: %u failed\n\n", pid_for_ruhu);
321 : : } else {
322 [ - + - + ]: 1 : fprintf(stdout, "FDP write on placement id: %u success\n\n", pid_for_ruhu);
323 : : }
324 : :
325 : 1 : spdk_free(req->contig);
326 : 1 : spdk_free(req);
327 : 1 : return g_fdp_command_result;
328 : : }
329 : :
330 : : static int
331 : 1 : reclaim_unit_handle_update(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair)
332 : : {
333 : : int ret;
334 : 1 : uint32_t npids = 1;
335 : 1 : uint16_t pid_list[1] = {};
336 : :
337 : 1 : memcpy(pid_list, &pid_for_ruhu, sizeof(pid_list));
338 : 1 : g_outstanding_commands = 0;
339 : 1 : g_fdp_command_result = -1;
340 : :
341 : 1 : ret = spdk_nvme_ns_cmd_io_mgmt_send(ns, qpair, pid_list, npids * sizeof(uint16_t),
342 : 1 : SPDK_NVME_FDP_IO_MGMT_SEND_RUHU, npids - 1, cmd_completion, NULL);
343 [ - + ]: 1 : if (ret) {
344 [ # # # # ]: 0 : fprintf(stderr, "IO management send: RUH update failed\n\n");
345 : 0 : return -1;
346 : : }
347 : :
348 : 1 : g_outstanding_commands++;
349 [ + + ]: 26 : while (g_outstanding_commands) {
350 : 25 : spdk_nvme_qpair_process_completions(qpair, 100);
351 : : }
352 : :
353 [ - + ]: 1 : if (g_fdp_command_result) {
354 [ # # # # ]: 0 : fprintf(stderr, "IO management send: RUH update failed\n\n");
355 : 0 : return -1;
356 : : }
357 : :
358 [ - + - + ]: 1 : fprintf(stdout, "IO mgmt send: RUH update for Placement ID: #%u Success\n\n",
359 : : pid_for_ruhu);
360 : 1 : return 0;
361 : : }
362 : :
363 : : static int
364 : 1 : reclaim_unit_handle_status(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair)
365 : : {
366 : : int ret;
367 : : uint32_t i;
368 : : size_t fdp_ruhs_size;
369 : : struct spdk_nvme_fdp_ruhs *fdp_ruhs;
370 : : struct spdk_nvme_fdp_ruhs_desc *ruhs_desc;
371 : :
372 : 1 : g_outstanding_commands = 0;
373 : 1 : g_fdp_command_result = -1;
374 : :
375 : 1 : fdp_ruhs_size = sizeof(struct spdk_nvme_fdp_ruhs) +
376 : : FDP_NR_RUHS_DESC * sizeof(struct spdk_nvme_fdp_ruhs_desc);
377 : 1 : fdp_ruhs = calloc(1, fdp_ruhs_size);
378 [ - + ]: 1 : if (fdp_ruhs == NULL) {
379 [ # # # # ]: 0 : fprintf(stderr, "FDP reclaim unit handle status allocation failed!\n\n");
380 : 0 : return -1;
381 : : }
382 : :
383 : 1 : ret = spdk_nvme_ns_cmd_io_mgmt_recv(ns, qpair, fdp_ruhs, fdp_ruhs_size,
384 : : SPDK_NVME_FDP_IO_MGMT_RECV_RUHS, 0, cmd_completion, NULL);
385 [ - + ]: 1 : if (ret) {
386 [ # # # # ]: 0 : fprintf(stderr, "IO management receive: RUH status failed\n\n");
387 : 0 : free(fdp_ruhs);
388 : 0 : return -1;
389 : : }
390 : :
391 : 1 : g_outstanding_commands++;
392 [ + + ]: 80 : while (g_outstanding_commands) {
393 : 79 : spdk_nvme_qpair_process_completions(qpair, 100);
394 : : }
395 : :
396 [ - + ]: 1 : if (g_fdp_command_result) {
397 [ # # # # ]: 0 : fprintf(stderr, "IO management receive: RUH status failed\n\n");
398 : 0 : free(fdp_ruhs);
399 : 0 : return -1;
400 : : }
401 : :
402 [ - + - + ]: 1 : fprintf(stdout, "FDP Reclaim unit handle status\n");
403 [ - + - + ]: 1 : fprintf(stdout, "==============================\n");
404 : :
405 [ - + - + ]: 1 : fprintf(stdout, "Number of RUHS descriptors: %u\n", fdp_ruhs->nruhsd);
406 [ + + ]: 3 : for (i = 0; i < fdp_ruhs->nruhsd; i++) {
407 : 2 : ruhs_desc = &fdp_ruhs->ruhs_desc[i];
408 : :
409 [ - + ]: 4 : fprintf(stdout,
410 : : "RUHS Desc: #%04u PID: 0x%04x RUHID: 0x%04x ERUT: 0x%08x RUAMW: 0x%016"PRIx64"\n",
411 [ - + ]: 2 : i, ruhs_desc->pid, ruhs_desc->ruhid, ruhs_desc->earutr, ruhs_desc->ruamw);
412 : : }
413 [ - + ]: 1 : fprintf(stdout, "\n");
414 : :
415 : : /* Use this Placement Identifier for Reclaim unit handle Update */
416 : 1 : pid_for_ruhu = (&fdp_ruhs->ruhs_desc[0])->pid;
417 : :
418 : : /* Use this Placement Handle to enable FDP events */
419 [ - + ]: 1 : ph_for_fdp_event = pid_for_ruhu & ((1 << (16 - rgif)) - 1);
420 : :
421 : 1 : free(fdp_ruhs);
422 : 1 : return 0;
423 : : }
424 : :
425 : : static int
426 : 1 : get_fdp_cfg_log_page(struct spdk_nvme_ns *ns)
427 : : {
428 : : uint32_t i, j;
429 : : struct spdk_nvme_fdp_cfg_descriptor *cfg_desc;
430 : 1 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
431 : 1 : const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
432 : : void *log;
433 : :
434 : 1 : g_outstanding_commands = 0;
435 : 1 : g_fdp_command_result = -1;
436 : :
437 : : /* Fetch the FDP configurations log page for only 4096 bytes */
438 [ + - ]: 1 : if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_CONFIGURATIONS, 0,
439 [ - + ]: 1 : g_fdp_cfg_log_page, FDP_LOG_PAGE_SIZE, 0, 0, (nsdata->endgid << 16),
440 : : 0, cmd_completion, NULL) == 0) {
441 : 1 : g_outstanding_commands++;
442 : : } else {
443 [ # # # # ]: 0 : fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP config) failed\n\n");
444 : 0 : return -1;
445 : : }
446 : :
447 [ + + ]: 3 : while (g_outstanding_commands) {
448 : 2 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
449 : : }
450 : :
451 [ - + ]: 1 : if (g_fdp_command_result) {
452 [ # # # # ]: 0 : fprintf(stderr, "Failed to get FDP configuration log page\n\n");
453 : 0 : return -1;
454 : : }
455 : :
456 [ - + - + ]: 1 : fprintf(stdout, "FDP configurations log page\n");
457 [ - + - + ]: 1 : fprintf(stdout, "===========================\n");
458 : :
459 [ - + - + ]: 1 : fprintf(stdout, "Number of FDP configurations: %u\n", g_fdp_cfg_log_page->ncfg + 1);
460 [ - + - + ]: 1 : fprintf(stdout, "Version: %u\n", g_fdp_cfg_log_page->version);
461 [ - + - + ]: 1 : fprintf(stdout, "Size: %u\n", g_fdp_cfg_log_page->size);
462 : :
463 : 1 : log = g_fdp_cfg_log_page->cfg_desc;
464 [ + + ]: 2 : for (i = 0; i <= g_fdp_cfg_log_page->ncfg; i++) {
465 : 1 : cfg_desc = log;
466 [ - + - + ]: 1 : fprintf(stdout, "FDP Configuration Descriptor: %u\n", i);
467 [ - + - + ]: 1 : fprintf(stdout, " Descriptor Size: %u\n", cfg_desc->ds);
468 [ - + ]: 1 : fprintf(stdout, " Reclaim Group Identifier format: %u\n",
469 [ - + ]: 1 : cfg_desc->fdpa.bits.rgif);
470 [ - + - + ]: 1 : fprintf(stdout, " FDP Volatile Write Cache: %s\n",
471 [ - + ]: 1 : cfg_desc->fdpa.bits.fdpvwc ? "Present" : "Not Present");
472 [ - + - + ]: 1 : fprintf(stdout, " FDP Configuration: %s\n",
473 [ + - ]: 1 : cfg_desc->fdpa.bits.fdpcv ? "Valid" : "Invalid");
474 [ - + - + ]: 1 : fprintf(stdout, " Vendor Specific Size: %u\n", cfg_desc->vss);
475 [ - + - + ]: 1 : fprintf(stdout, " Number of Reclaim Groups: %u\n", cfg_desc->nrg);
476 [ - + - + ]: 1 : fprintf(stdout, " Number of Recalim Unit Handles: %u\n", cfg_desc->nruh);
477 [ - + - + ]: 1 : fprintf(stdout, " Max Placement Identifiers: %u\n", cfg_desc->maxpids + 1);
478 [ - + - + ]: 1 : fprintf(stdout, " Number of Namespaces Suppprted: %u\n", cfg_desc->nns);
479 [ - + - + ]: 1 : fprintf(stdout, " Reclaim unit Nominal Size: %" PRIx64 " bytes\n", cfg_desc->runs);
480 [ - + - + ]: 1 : fprintf(stdout, " Estimated Reclaim Unit Time Limit: ");
481 [ - + ]: 1 : if (cfg_desc->erutl) {
482 [ # # # # ]: 0 : fprintf(stdout, "%u seconds\n", cfg_desc->erutl);
483 : : } else {
484 [ - + - + ]: 1 : fprintf(stdout, "Not Reported\n");
485 : : }
486 [ + + ]: 9 : for (j = 0; j < cfg_desc->nruh; j++) {
487 [ - + - + ]: 8 : fprintf(stdout, " RUH Desc #%03d: RUH Type: %s\n", j,
488 [ - + ]: 8 : cfg_desc->ruh_desc[j].ruht == SPDK_NVME_FDP_RUHT_INITIALLY_ISOLATED ? "Initially Isolated" :
489 [ # # ]: 0 : cfg_desc->ruh_desc[j].ruht == SPDK_NVME_FDP_RUHT_PERSISTENTLY_ISOLATED ? "Persistently Isolated" :
490 : : "Reserved");
491 : : }
492 [ + - ]: 1 : if (i == fdpci) {
493 : 1 : rgif = cfg_desc->fdpa.bits.rgif;
494 : : }
495 : 1 : log += cfg_desc->ds;
496 : : }
497 : :
498 [ - + ]: 1 : fprintf(stdout, "\n");
499 : 1 : return 0;
500 : : }
501 : :
502 : : static int
503 : 1 : get_fdp_ruhu_log_page(struct spdk_nvme_ns *ns)
504 : : {
505 : : uint32_t i;
506 : : struct spdk_nvme_fdp_ruhu_descriptor *ruhu_desc;
507 : 1 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
508 : 1 : const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
509 : :
510 : 1 : g_outstanding_commands = 0;
511 : 1 : g_fdp_command_result = -1;
512 : :
513 [ + - ]: 1 : if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_RECLAIM_UNIT_HANDLE_USAGE, 0,
514 [ - + ]: 1 : g_fdp_ruhu_log_page, FDP_LOG_PAGE_SIZE, 0, 0, (nsdata->endgid << 16),
515 : : 0, cmd_completion, NULL) == 0) {
516 : 1 : g_outstanding_commands++;
517 : : } else {
518 [ # # # # ]: 0 : fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(RUH usage) failed\n\n");
519 : 0 : return -1;
520 : : }
521 : :
522 [ + + ]: 4 : while (g_outstanding_commands) {
523 : 3 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
524 : : }
525 : :
526 [ - + ]: 1 : if (g_fdp_command_result) {
527 [ # # # # ]: 0 : fprintf(stderr, "Failed to get Reclaim Unit Handle usage log page\n\n");
528 : 0 : return -1;
529 : : }
530 : :
531 [ - + - + ]: 1 : fprintf(stdout, "FDP reclaim unit handle usage log page\n");
532 [ - + - + ]: 1 : fprintf(stdout, "======================================\n");
533 : :
534 [ - + - + ]: 1 : fprintf(stdout, "Number of Reclaim Unit Handles: %u\n", g_fdp_ruhu_log_page->nruh);
535 : :
536 [ + + ]: 9 : for (i = 0; i < g_fdp_ruhu_log_page->nruh; i++) {
537 : 8 : ruhu_desc = &g_fdp_ruhu_log_page->ruhu_desc[i];
538 : :
539 [ - + - + ]: 8 : fprintf(stdout, " RUH Usage Desc #%03d: RUH Attributes: %s\n", i,
540 [ + + ]: 8 : ruhu_desc->ruha == SPDK_NVME_FDP_RUHA_UNUSED ? "Unused" :
541 [ + - ]: 2 : ruhu_desc->ruha == SPDK_NVME_FDP_RUHA_HOST_SPECIFIED ? "Host Specified" :
542 [ + - ]: 1 : ruhu_desc->ruha == SPDK_NVME_FDP_RUHA_CTRLR_SPECIFIED ? "Controller Specified" :
543 : : "Reserved");
544 : : }
545 : :
546 [ - + ]: 1 : fprintf(stdout, "\n");
547 : 1 : return 0;
548 : : }
549 : :
550 : : static int
551 : 1 : get_fdp_stats_log_page(struct spdk_nvme_ns *ns)
552 : : {
553 : 1 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
554 : 1 : const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
555 : :
556 : 1 : g_outstanding_commands = 0;
557 : 1 : g_fdp_command_result = -1;
558 : :
559 [ + - ]: 1 : if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_STATISTICS, 0,
560 [ - + ]: 1 : &g_fdp_stats_log_page, 64, 0, 0, (nsdata->endgid << 16), 0,
561 : : cmd_completion, NULL) == 0) {
562 : 1 : g_outstanding_commands++;
563 : : } else {
564 [ # # # # ]: 0 : fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP stats) failed\n\n");
565 : 0 : return -1;
566 : : }
567 : :
568 [ + + ]: 5 : while (g_outstanding_commands) {
569 : 4 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
570 : : }
571 : :
572 [ - + ]: 1 : if (g_fdp_command_result) {
573 [ # # # # ]: 0 : fprintf(stderr, "Failed to get FDP statistics log page\n\n");
574 : 0 : return -1;
575 : : }
576 : :
577 [ - + - + ]: 1 : fprintf(stdout, "FDP statistics log page\n");
578 [ - + - + ]: 1 : fprintf(stdout, "=======================\n");
579 : :
580 [ - + - + ]: 1 : fprintf(stdout, "Host bytes with metadata written: ");
581 : 1 : print_uint128_dec(g_fdp_stats_log_page.hbmw);
582 [ - + ]: 1 : fprintf(stdout, "\n");
583 [ - + - + ]: 1 : fprintf(stdout, "Media bytes with metadata written: ");
584 : 1 : print_uint128_dec(g_fdp_stats_log_page.mbmw);
585 [ - + ]: 1 : fprintf(stdout, "\n");
586 [ - + - + ]: 1 : fprintf(stdout, "Media bytes erased: ");
587 : 1 : print_uint128_dec(g_fdp_stats_log_page.mbe);
588 [ - + - + ]: 1 : fprintf(stdout, "\n\n");
589 : :
590 : 1 : return 0;
591 : : }
592 : :
593 : : static int
594 : 1 : get_fdp_events_log_page(struct spdk_nvme_ns *ns)
595 : : {
596 : : uint32_t i;
597 : : struct spdk_nvme_fdp_event *event;
598 : : struct spdk_nvme_fdp_event_media_reallocated *media_reallocated;
599 : 1 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
600 : 1 : const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
601 : :
602 : 1 : g_outstanding_commands = 0;
603 : 1 : g_fdp_command_result = -1;
604 : :
605 : : /* Only fetch FDP host events here */
606 [ + - ]: 1 : if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_EVENTS, 0,
607 : : g_fdp_events_log_page, FDP_LOG_PAGE_SIZE, 0,
608 [ - + ]: 1 : (SPDK_NVME_FDP_REPORT_HOST_EVENTS << 8), (nsdata->endgid << 16),
609 : : 0, cmd_completion, NULL) == 0) {
610 : 1 : g_outstanding_commands++;
611 : : } else {
612 [ # # # # ]: 0 : fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP events) failed\n\n");
613 : 0 : return -1;
614 : : }
615 : :
616 [ + + ]: 6 : while (g_outstanding_commands) {
617 : 5 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
618 : : }
619 : :
620 [ - + ]: 1 : if (g_fdp_command_result) {
621 [ # # # # ]: 0 : fprintf(stderr, "Failed to get eventss log page\n\n");
622 : 0 : return -1;
623 : : }
624 : :
625 [ - + - + ]: 1 : fprintf(stdout, "FDP events log page\n");
626 [ - + - + ]: 1 : fprintf(stdout, "===================\n");
627 [ - + - + ]: 1 : fprintf(stdout, "Number of FDP events: %u\n", g_fdp_events_log_page->nevents);
628 : :
629 [ + + ]: 2 : for (i = 0; i < g_fdp_events_log_page->nevents; i++) {
630 : 1 : event = &g_fdp_events_log_page->event[i];
631 : :
632 [ - + - + ]: 1 : fprintf(stdout, "FDP Event #%u:\n", i);
633 [ - + - + ]: 1 : fprintf(stdout, " Event Type: %s\n",
634 [ - + ]: 1 : event->etype == SPDK_NVME_FDP_EVENT_RU_NOT_WRITTEN_CAPACITY ? "RU Not Written to Capacity" :
635 [ # # ]: 0 : event->etype == SPDK_NVME_FDP_EVENT_RU_TIME_LIMIT_EXCEEDED ? "RU Time Limit Exceeded" :
636 [ # # ]: 0 : event->etype == SPDK_NVME_FDP_EVENT_CTRLR_RESET_MODIFY_RUH ? "Ctrlr Reset Modified RUH's" :
637 [ # # ]: 0 : event->etype == SPDK_NVME_FDP_EVENT_INVALID_PLACEMENT_ID ? "Invalid Placement Identifier" :
638 [ # # ]: 0 : event->etype == SPDK_NVME_FDP_EVENT_MEDIA_REALLOCATED ? "Media Reallocated" :
639 [ # # ]: 0 : event->etype == SPDK_NVME_FDP_EVENT_IMPLICIT_MODIFIED_RUH ? "Implicitly modified RUH" :
640 : : "Reserved");
641 [ - + - + ]: 1 : fprintf(stdout, " Placement Identifier: %s\n",
642 [ + - ]: 1 : event->fdpef.bits.piv ? "Valid" : "Invalid");
643 [ - + - + ]: 1 : fprintf(stdout, " NSID: %s\n",
644 [ + - ]: 1 : event->fdpef.bits.nsidv ? "Valid" : "Invalid");
645 [ - + - + ]: 1 : fprintf(stdout, " Location: %s\n",
646 [ + - ]: 1 : event->fdpef.bits.lv ? "Valid" : "Invalid");
647 [ + - ]: 1 : if (event->fdpef.bits.piv) {
648 [ - + - + ]: 1 : fprintf(stdout, " Placement Identifier: %u\n", event->pid);
649 : : } else {
650 [ # # # # ]: 0 : fprintf(stdout, " Placement Identifier: Reserved\n");
651 : : }
652 [ - + - + ]: 1 : fprintf(stdout, " Event Timestamp: %" PRIx64 "\n", event->timestamp);
653 [ + - ]: 1 : if (event->fdpef.bits.nsidv) {
654 [ - + - + ]: 1 : fprintf(stdout, " Namespace Identifier: %u\n", event->nsid);
655 : : } else {
656 [ # # # # ]: 0 : fprintf(stdout, " Namespace Identifier: Ignore\n");
657 : : }
658 : :
659 [ - + ]: 1 : if (event->etype == SPDK_NVME_FDP_EVENT_MEDIA_REALLOCATED) {
660 : 0 : media_reallocated = (struct spdk_nvme_fdp_event_media_reallocated *)&event->event_type_specific;
661 : :
662 [ # # # # ]: 0 : fprintf(stdout, " LBA: %s\n",
663 [ # # ]: 0 : media_reallocated->sef.bits.lbav ? "Valid" : "Invalid");
664 [ # # # # ]: 0 : fprintf(stdout, " Number of LBA's Moved: %u\n", media_reallocated->nlbam);
665 [ # # ]: 0 : if (media_reallocated->sef.bits.lbav) {
666 [ # # # # ]: 0 : fprintf(stdout, " Logical Block Address: %u\n", event->nsid);
667 : : } else {
668 [ # # # # ]: 0 : fprintf(stdout, " Logical Block Address: Ignore\n");
669 : : }
670 : : }
671 : :
672 [ + - ]: 1 : if (event->fdpef.bits.lv) {
673 [ - + - + ]: 1 : fprintf(stdout, " Reclaim Group Identifier: %u\n", event->rgid);
674 : : } else {
675 [ # # # # ]: 0 : fprintf(stdout, " Reclaim Group Identifier: Ignore\n");
676 : : }
677 [ + - ]: 1 : if (event->fdpef.bits.lv) {
678 [ - + - + ]: 1 : fprintf(stdout, " Reclaim Unit Handle Identifier: %u\n", event->ruhid);
679 : : } else {
680 [ # # # # ]: 0 : fprintf(stdout, " Reclaim Unit Handle Identifier: Ignore\n");
681 : : }
682 : : }
683 : :
684 [ - + ]: 1 : fprintf(stdout, "\n");
685 : 1 : return 0;
686 : : }
687 : :
688 : : static int
689 : 1 : fdp_tests(struct spdk_nvme_ns *ns)
690 : : {
691 : : struct spdk_nvme_qpair *qpair;
692 : 1 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
693 : : int ret, err;
694 : :
695 : 1 : qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, NULL, 0);
696 [ - + ]: 1 : if (!qpair) {
697 [ # # # # ]: 0 : fprintf(stderr, "spdk_nvme_ctrlr_alloc_io_qpair() failed\n");
698 : 0 : return -EIO;
699 : : }
700 : :
701 : 1 : ret = 0;
702 : :
703 [ - + - + ]: 1 : fprintf(stdout, "==================================\n");
704 [ - + - + ]: 1 : fprintf(stdout, "== FDP tests for Namespace: #%02u ==\n", spdk_nvme_ns_get_id(ns));
705 [ - + - + ]: 1 : fprintf(stdout, "==================================\n\n");
706 : 1 : err = get_fdp(ns);
707 [ - + ]: 1 : if (err) {
708 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
709 : 0 : return err;
710 : : }
711 : :
712 [ - + ]: 1 : if (!fdp_res.bits.fdpe) {
713 [ # # # # ]: 0 : fprintf(stdout, "FDP support disabled\n");
714 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
715 : 0 : return 0;
716 : : }
717 : :
718 : 1 : fdpci = fdp_res.bits.fdpci;
719 : 1 : err = get_fdp_cfg_log_page(ns);
720 [ - + ]: 1 : if (err) {
721 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
722 : 0 : return err;
723 : : }
724 : :
725 : 1 : ret += get_fdp_ruhu_log_page(ns);
726 : 1 : ret += get_fdp_stats_log_page(ns);
727 : :
728 : 1 : err = reclaim_unit_handle_status(ns, qpair);
729 [ - + ]: 1 : if (err) {
730 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
731 : 0 : return err;
732 : : }
733 : :
734 : 1 : err = check_fdp_write(ns, qpair);
735 [ - + ]: 1 : if (err) {
736 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
737 : 0 : return err;
738 : : }
739 : :
740 : 1 : ret += set_fdp_events(ns);
741 : 1 : ret += reclaim_unit_handle_update(ns, qpair);
742 : :
743 : 1 : ret += get_fdp_events(ns);
744 : 1 : ret += get_fdp_events_log_page(ns);
745 : :
746 : 1 : return ret;
747 : : }
748 : :
749 : : static void
750 : 1 : register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
751 : : {
752 : : struct ns_entry *entry;
753 : 1 : const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
754 : :
755 : 1 : entry = malloc(sizeof(struct ns_entry));
756 [ - + ]: 1 : if (entry == NULL) {
757 : 0 : perror("ns_entry malloc");
758 : 0 : exit(1);
759 : : }
760 : :
761 : 1 : entry->ctrlr = ctrlr;
762 : 1 : entry->ns = ns;
763 : 1 : entry->next = g_namespaces;
764 : 1 : g_namespaces = entry;
765 : :
766 [ - + ]: 1 : printf("Namespace ID: %d Endurance Group ID: %d\n", spdk_nvme_ns_get_id(ns),
767 : 1 : nsdata->endgid);
768 : 1 : }
769 : :
770 : : static bool
771 : 1 : probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
772 : : struct spdk_nvme_ctrlr_opts *opts)
773 : : {
774 [ - + - + ]: 1 : fprintf(stdout, "Attaching to %s\n", trid->traddr);
775 : :
776 : 1 : return true;
777 : : }
778 : :
779 : : static void
780 : 1 : attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
781 : : struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
782 : : {
783 : : int num_ns, nsid;
784 : : struct spdk_nvme_ns *ns;
785 : : const struct spdk_nvme_ctrlr_data *cdata;
786 : :
787 : 1 : cdata = spdk_nvme_ctrlr_get_data(ctrlr);
788 : :
789 [ + - ]: 1 : if (cdata->ctratt.fdps) {
790 [ - + - + ]: 1 : fprintf(stdout, "Controller supports FDP Attached to %s\n", trid->traddr);
791 : 1 : num_ns = spdk_nvme_ctrlr_get_num_ns(ctrlr);
792 [ - + ]: 1 : if (num_ns < 1) {
793 [ # # ]: 0 : printf("No valid namespaces in controller\n");
794 : : } else {
795 [ + + ]: 2 : for (nsid = spdk_nvme_ctrlr_get_first_active_ns(ctrlr); nsid != 0;
796 : 1 : nsid = spdk_nvme_ctrlr_get_next_active_ns(ctrlr, nsid)) {
797 : 1 : ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid);
798 : 1 : register_ns(ctrlr, ns);
799 : : }
800 : : }
801 : : } else {
802 [ # # # # ]: 0 : fprintf(stdout, "Controller attached to: %s doesn't support FDP\n", trid->traddr);
803 : : }
804 : 1 : }
805 : :
806 : : static void
807 : 1 : cleanup(void)
808 : : {
809 : 1 : struct ns_entry *ns_entry = g_namespaces;
810 : 1 : struct spdk_nvme_detach_ctx *detach_ctx = NULL;
811 : :
812 [ + + ]: 2 : while (ns_entry) {
813 : 1 : struct ns_entry *next = ns_entry->next;
814 : :
815 : 1 : spdk_nvme_detach_async(ns_entry->ctrlr, &detach_ctx);
816 : :
817 : 1 : free(ns_entry);
818 : 1 : ns_entry = next;
819 : : }
820 : :
821 [ + - ]: 1 : if (detach_ctx) {
822 : 1 : spdk_nvme_detach_poll(detach_ctx);
823 : : }
824 : 1 : }
825 : :
826 : : static void
827 : 0 : usage(const char *program_name)
828 : : {
829 [ # # ]: 0 : printf("%s [options]", program_name);
830 : 0 : printf("\n");
831 [ # # ]: 0 : printf("options:\n");
832 [ # # ]: 0 : printf(" -r trid remote NVMe over Fabrics target address\n");
833 [ # # ]: 0 : printf(" Format: 'key:value [key:value] ...'\n");
834 [ # # ]: 0 : printf(" Keys:\n");
835 [ # # ]: 0 : printf(" trtype Transport type (e.g. RDMA)\n");
836 [ # # ]: 0 : printf(" adrfam Address family (e.g. IPv4, IPv6)\n");
837 [ # # ]: 0 : printf(" traddr Transport address (e.g. 192.168.100.8)\n");
838 [ # # ]: 0 : printf(" trsvcid Transport service identifier (e.g. 4420)\n");
839 [ # # ]: 0 : printf(" subnqn Subsystem NQN (default: %s)\n", SPDK_NVMF_DISCOVERY_NQN);
840 [ # # ]: 0 : printf(" Example: -r 'trtype:RDMA adrfam:IPv4 traddr:192.168.100.8 trsvcid:4420'\n");
841 [ # # ]: 0 : printf(" -h show this usage\n");
842 : 0 : }
843 : :
844 : : static int
845 : 1 : parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
846 : : {
847 : : int op;
848 : :
849 : 1 : spdk_nvme_trid_populate_transport(&g_trid, SPDK_NVME_TRANSPORT_PCIE);
850 [ - + ]: 1 : snprintf(g_trid.subnqn, sizeof(g_trid.subnqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
851 : :
852 [ - + - + : 2 : while ((op = getopt(argc, argv, "r:h")) != -1) {
+ + ]
853 [ + - - ]: 1 : switch (op) {
854 : 1 : case 'r':
855 [ - + ]: 1 : if (spdk_nvme_transport_id_parse(&g_trid, optarg) != 0) {
856 [ # # # # ]: 0 : fprintf(stderr, "Error parsing transport address\n");
857 : 0 : return 1;
858 : : }
859 : :
860 : 1 : g_use_trid = true;
861 : 1 : break;
862 : 0 : case 'h':
863 : 0 : usage(argv[0]);
864 : 0 : exit(EXIT_SUCCESS);
865 : 0 : default:
866 : 0 : usage(argv[0]);
867 : 0 : return 1;
868 : : }
869 : : }
870 : :
871 : 1 : return 0;
872 : : }
873 : :
874 : : int
875 : 1 : main(int argc, char **argv)
876 : : {
877 : : int rc;
878 : 1 : struct spdk_env_opts opts;
879 : : struct ns_entry *ns_entry;
880 : :
881 : 1 : spdk_env_opts_init(&opts);
882 : 1 : rc = parse_args(argc, argv, &opts);
883 [ - + ]: 1 : if (rc != 0) {
884 : 0 : return rc;
885 : : }
886 : :
887 : 1 : opts.name = "fdp";
888 : 1 : opts.core_mask = "0x1";
889 : 1 : opts.shm_id = 0;
890 [ - + ]: 1 : if (spdk_env_init(&opts) < 0) {
891 [ # # # # ]: 0 : fprintf(stderr, "Unable to initialize SPDK env\n");
892 : 0 : return 1;
893 : : }
894 : :
895 [ - + ]: 1 : printf("Initializing NVMe Controllers\n");
896 : :
897 [ - + + - ]: 1 : rc = spdk_nvme_probe(g_use_trid ? &g_trid : NULL, NULL, probe_cb, attach_cb, NULL);
898 [ - + ]: 1 : if (rc != 0) {
899 [ # # # # ]: 0 : fprintf(stderr, "spdk_nvme_probe() failed\n");
900 : 0 : return 1;
901 : : }
902 : :
903 [ - + ]: 1 : if (g_namespaces == NULL) {
904 [ # # # # ]: 0 : fprintf(stderr, "no NVMe controllers found\n");
905 : 0 : return 1;
906 : : }
907 : :
908 [ - + ]: 1 : printf("Initialization complete.\n\n");
909 : :
910 : 1 : ns_entry = g_namespaces;
911 [ + + ]: 2 : while (ns_entry != NULL) {
912 : 1 : rc = fdp_tests(ns_entry->ns);
913 [ - + ]: 1 : if (rc) {
914 : 0 : break;
915 : : }
916 : 1 : ns_entry = ns_entry->next;
917 : : }
918 : :
919 [ - + - + ]: 1 : printf("FDP test %s\n", rc ? "failed" : "passed");
920 : 1 : cleanup();
921 : :
922 : 1 : return 0;
923 : : }
|