xref: /spdk/test/nvme/fdp/fdp.c (revision 57fd99b91e71a4baa5543e19ff83958dc99d4dac)
1c976353bSAnkit Kumar /*   SPDX-License-Identifier: BSD-3-Clause
2c976353bSAnkit Kumar  *   Copyright (c) 2023 Samsung Electronics Co., Ltd.
3c976353bSAnkit Kumar  *   All rights reserved.
4c976353bSAnkit Kumar  */
5c976353bSAnkit Kumar 
6c976353bSAnkit Kumar #include "spdk/stdinc.h"
7c976353bSAnkit Kumar #include "spdk/nvme.h"
8c976353bSAnkit Kumar #include "spdk/env.h"
91d77eec8SKonrad Sztyber #include "spdk/util.h"
10c976353bSAnkit Kumar 
11c976353bSAnkit Kumar #define MAX_FDP_EVENTS			0xFF
12c976353bSAnkit Kumar 
13c976353bSAnkit Kumar #define SET_EVENT_TYPES	((uint8_t[]){0x0, 0x1, 0x2, 0x3, 0x80, 0x81})
14c976353bSAnkit Kumar 
15c976353bSAnkit Kumar struct ns_entry {
16c976353bSAnkit Kumar 	struct spdk_nvme_ctrlr	*ctrlr;
17c976353bSAnkit Kumar 	struct spdk_nvme_ns	*ns;
18c976353bSAnkit Kumar 	struct ns_entry		*next;
19c976353bSAnkit Kumar };
20c976353bSAnkit Kumar 
21c976353bSAnkit Kumar static struct ns_entry *g_namespaces = NULL;
22c976353bSAnkit Kumar static struct spdk_nvme_transport_id g_trid;
23c976353bSAnkit Kumar static bool g_use_trid = false;
24c976353bSAnkit Kumar 
25c976353bSAnkit Kumar static int g_outstanding_commands;
26c976353bSAnkit Kumar static int g_fdp_command_result;
27c976353bSAnkit Kumar static uint32_t g_feat_result;
28c976353bSAnkit Kumar static uint16_t ph_for_fdp_event;
29c976353bSAnkit Kumar static uint8_t rgif;
30c976353bSAnkit Kumar static uint8_t fdpci;
31c976353bSAnkit Kumar static uint16_t pid_for_ruhu;
32c976353bSAnkit Kumar static uint32_t g_spdk_sge_size = 4096;
33c976353bSAnkit Kumar 
34c976353bSAnkit Kumar static union spdk_nvme_feat_fdp_cdw12 fdp_res;
35c976353bSAnkit Kumar 
36c976353bSAnkit Kumar struct io_request {
37c976353bSAnkit Kumar 	void *contig;
38c976353bSAnkit Kumar 	uint32_t sgl_offset;
39c976353bSAnkit Kumar 	uint32_t buf_size;
40c976353bSAnkit Kumar };
41c976353bSAnkit Kumar 
42c976353bSAnkit Kumar static void
43c976353bSAnkit Kumar nvme_req_reset_sgl(void *cb_arg, uint32_t sgl_offset)
44c976353bSAnkit Kumar {
45c976353bSAnkit Kumar 	struct io_request *req = (struct io_request *)cb_arg;
46c976353bSAnkit Kumar 
47c976353bSAnkit Kumar 	req->sgl_offset = sgl_offset;
48c976353bSAnkit Kumar }
49c976353bSAnkit Kumar 
50c976353bSAnkit Kumar static int
51c976353bSAnkit Kumar nvme_req_next_sge(void *cb_arg, void **address, uint32_t *length)
52c976353bSAnkit Kumar {
53c976353bSAnkit Kumar 	struct io_request *req = (struct io_request *)cb_arg;
54c976353bSAnkit Kumar 	uint32_t iov_len;
55c976353bSAnkit Kumar 
56c976353bSAnkit Kumar 	*address = req->contig;
57c976353bSAnkit Kumar 
58c976353bSAnkit Kumar 	if (req->sgl_offset) {
59c976353bSAnkit Kumar 		*address += req->sgl_offset;
60c976353bSAnkit Kumar 	}
61c976353bSAnkit Kumar 
62c976353bSAnkit Kumar 	iov_len = req->buf_size - req->sgl_offset;
63c976353bSAnkit Kumar 	if (iov_len > g_spdk_sge_size) {
64c976353bSAnkit Kumar 		iov_len = g_spdk_sge_size;
65c976353bSAnkit Kumar 	}
66c976353bSAnkit Kumar 
67c976353bSAnkit Kumar 	req->sgl_offset += iov_len;
68c976353bSAnkit Kumar 	*length = iov_len;
69c976353bSAnkit Kumar 
70c976353bSAnkit Kumar 	return 0;
71c976353bSAnkit Kumar }
72c976353bSAnkit Kumar 
73c976353bSAnkit Kumar static void
74c976353bSAnkit Kumar get_feat_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
75c976353bSAnkit Kumar {
76c976353bSAnkit Kumar 	if (spdk_nvme_cpl_is_error(cpl)) {
77c976353bSAnkit Kumar 		g_fdp_command_result = -1;
78c976353bSAnkit Kumar 	} else {
79c976353bSAnkit Kumar 		g_fdp_command_result = 0;
80c976353bSAnkit Kumar 		g_feat_result = cpl->cdw0;
81c976353bSAnkit Kumar 	}
82c976353bSAnkit Kumar 
83c976353bSAnkit Kumar 	g_outstanding_commands--;
84c976353bSAnkit Kumar }
85c976353bSAnkit Kumar 
86c976353bSAnkit Kumar static void
87c976353bSAnkit Kumar cmd_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
88c976353bSAnkit Kumar {
89c976353bSAnkit Kumar 	if (spdk_nvme_cpl_is_error(cpl)) {
90c976353bSAnkit Kumar 		g_fdp_command_result = -1;
91c976353bSAnkit Kumar 	} else {
92c976353bSAnkit Kumar 		g_fdp_command_result = 0;
93c976353bSAnkit Kumar 	}
94c976353bSAnkit Kumar 
95c976353bSAnkit Kumar 	g_outstanding_commands--;
96c976353bSAnkit Kumar }
97c976353bSAnkit Kumar 
98c976353bSAnkit Kumar static void
99c976353bSAnkit Kumar print_uint128_hex(uint64_t *v)
100c976353bSAnkit Kumar {
101c976353bSAnkit Kumar 	unsigned long long lo = v[0], hi = v[1];
102c976353bSAnkit Kumar 	if (hi) {
103c976353bSAnkit Kumar 		printf("0x%llX%016llX", hi, lo);
104c976353bSAnkit Kumar 	} else {
105c976353bSAnkit Kumar 		printf("0x%llX", lo);
106c976353bSAnkit Kumar 	}
107c976353bSAnkit Kumar }
108c976353bSAnkit Kumar 
109c976353bSAnkit Kumar static void
110c976353bSAnkit Kumar print_uint128_dec(uint64_t *v)
111c976353bSAnkit Kumar {
112c976353bSAnkit Kumar 	unsigned long long lo = v[0], hi = v[1];
113c976353bSAnkit Kumar 	if (hi) {
114c976353bSAnkit Kumar 		/* can't handle large (>64-bit) decimal values for now, so fall back to hex */
115c976353bSAnkit Kumar 		print_uint128_hex(v);
116c976353bSAnkit Kumar 	} else {
117c976353bSAnkit Kumar 		printf("%llu", (unsigned long long)lo);
118c976353bSAnkit Kumar 	}
119c976353bSAnkit Kumar }
120c976353bSAnkit Kumar 
121c976353bSAnkit Kumar static int
122c976353bSAnkit Kumar set_fdp_events(struct spdk_nvme_ns *ns)
123c976353bSAnkit Kumar {
124c976353bSAnkit Kumar 	int ret;
125c976353bSAnkit Kumar 	uint8_t fdp_event_type_list[6] = {};
126c976353bSAnkit Kumar 	uint32_t nfdp_events = 6;
127c976353bSAnkit Kumar 	uint32_t cdw11, cdw12;
128c976353bSAnkit Kumar 	struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
129c976353bSAnkit Kumar 	int nsid = spdk_nvme_ns_get_id(ns);
130c976353bSAnkit Kumar 
131c976353bSAnkit Kumar 	memcpy(fdp_event_type_list, SET_EVENT_TYPES, nfdp_events);
132c976353bSAnkit Kumar 	g_outstanding_commands = 0;
133c976353bSAnkit Kumar 	g_fdp_command_result = -1;
134c976353bSAnkit Kumar 
135c976353bSAnkit Kumar 	cdw11 = (nfdp_events << 16) | ph_for_fdp_event;
136c976353bSAnkit Kumar 	/* Enable FDP event */
137c976353bSAnkit Kumar 	cdw12 = 1;
138c976353bSAnkit Kumar 
139c976353bSAnkit Kumar 	ret = spdk_nvme_ctrlr_cmd_set_feature_ns(ctrlr, SPDK_NVME_FEAT_FDP_EVENTS, cdw11, cdw12,
140c976353bSAnkit Kumar 			fdp_event_type_list, nfdp_events,
141c976353bSAnkit Kumar 			get_feat_completion, NULL, nsid);
142c976353bSAnkit Kumar 	if (ret) {
143c976353bSAnkit Kumar 		fprintf(stderr, "Set Feature (fdp events) failed\n\n");
144c976353bSAnkit Kumar 		return -1;
145c976353bSAnkit Kumar 	}
146c976353bSAnkit Kumar 
147c976353bSAnkit Kumar 	g_outstanding_commands++;
148c976353bSAnkit Kumar 	while (g_outstanding_commands) {
149c976353bSAnkit Kumar 		spdk_nvme_ctrlr_process_admin_completions(ctrlr);
150c976353bSAnkit Kumar 	}
151c976353bSAnkit Kumar 
152c976353bSAnkit Kumar 	if (g_fdp_command_result) {
153c976353bSAnkit Kumar 		fprintf(stderr, "Set Feature (fdp events) failed\n\n");
154c976353bSAnkit Kumar 		return -1;
155c976353bSAnkit Kumar 	}
156c976353bSAnkit Kumar 
157c976353bSAnkit Kumar 	fprintf(stdout, "Set Feature: Enabling FDP events on Placement handle: #%u Success\n\n",
158c976353bSAnkit Kumar 		ph_for_fdp_event);
159c976353bSAnkit Kumar 	return 0;
160c976353bSAnkit Kumar }
161c976353bSAnkit Kumar 
162c976353bSAnkit Kumar static int
163c976353bSAnkit Kumar get_fdp_events(struct spdk_nvme_ns *ns)
164c976353bSAnkit Kumar {
165c976353bSAnkit Kumar 	int ret;
166c976353bSAnkit Kumar 	uint32_t i, cdw11;
167c976353bSAnkit Kumar 	struct spdk_nvme_fdp_event_desc events[MAX_FDP_EVENTS];
168c976353bSAnkit Kumar 	struct spdk_nvme_fdp_event_desc *event_desc;
169c976353bSAnkit Kumar 	struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
170c976353bSAnkit Kumar 	int nsid = spdk_nvme_ns_get_id(ns);
171c976353bSAnkit Kumar 
172c976353bSAnkit Kumar 	g_outstanding_commands = 0;
173c976353bSAnkit Kumar 	g_fdp_command_result = -1;
174c976353bSAnkit Kumar 	g_feat_result = 0;
175c976353bSAnkit Kumar 
176c976353bSAnkit Kumar 	cdw11 = (MAX_FDP_EVENTS << 16) | ph_for_fdp_event;
177c976353bSAnkit Kumar 
178c976353bSAnkit Kumar 	ret = spdk_nvme_ctrlr_cmd_get_feature_ns(ctrlr, SPDK_NVME_FEAT_FDP_EVENTS, cdw11,
179c976353bSAnkit Kumar 			events, MAX_FDP_EVENTS * sizeof(struct spdk_nvme_fdp_event_desc),
180c976353bSAnkit Kumar 			get_feat_completion, NULL, nsid);
181c976353bSAnkit Kumar 	if (ret) {
182c976353bSAnkit Kumar 		fprintf(stderr, "Get Feature (fdp events) failed\n\n");
183c976353bSAnkit Kumar 		return -1;
184c976353bSAnkit Kumar 	}
185c976353bSAnkit Kumar 
186c976353bSAnkit Kumar 	g_outstanding_commands++;
187c976353bSAnkit Kumar 	while (g_outstanding_commands) {
188c976353bSAnkit Kumar 		spdk_nvme_ctrlr_process_admin_completions(ctrlr);
189c976353bSAnkit Kumar 	}
190c976353bSAnkit Kumar 
191c976353bSAnkit Kumar 	if (g_fdp_command_result) {
192c976353bSAnkit Kumar 		fprintf(stderr, "Get Feature (fdp events) failed\n\n");
193c976353bSAnkit Kumar 		return -1;
194c976353bSAnkit Kumar 	}
195c976353bSAnkit Kumar 
196c976353bSAnkit Kumar 	fprintf(stdout, "Get Feature: FDP Events for Placement handle: #%u\n", ph_for_fdp_event);
197c976353bSAnkit Kumar 	fprintf(stdout, "========================\n");
198c976353bSAnkit Kumar 	fprintf(stdout, "Number of FDP Events: %u\n", g_feat_result);
199c976353bSAnkit Kumar 
200c976353bSAnkit Kumar 	event_desc = events;
201c976353bSAnkit Kumar 	for (i = 0; i < g_feat_result; i++) {
202c976353bSAnkit Kumar 		fprintf(stdout, "FDP Event: #%u  Type: %s", i,
203c976353bSAnkit Kumar 			event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_RU_NOT_WRITTEN_CAPACITY ?
204c976353bSAnkit Kumar 			"RU Not Written to Capacity   " :
205c976353bSAnkit Kumar 			event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_RU_TIME_LIMIT_EXCEEDED ?
206c976353bSAnkit Kumar 			"RU Time Limit Exceeded       " :
207c976353bSAnkit Kumar 			event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_CTRLR_RESET_MODIFY_RUH ?
208c976353bSAnkit Kumar 			"Ctrlr Reset Modified RUH's   " :
209c976353bSAnkit Kumar 			event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_INVALID_PLACEMENT_ID ?
210c976353bSAnkit Kumar 			"Invalid Placement Identifier " :
211c976353bSAnkit Kumar 			event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_MEDIA_REALLOCATED ? "Media Reallocated            " :
212c976353bSAnkit Kumar 			event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_IMPLICIT_MODIFIED_RUH ?
213c976353bSAnkit Kumar 			"Implicitly modified RUH      " :
214c976353bSAnkit Kumar 			"Reserved");
215c976353bSAnkit Kumar 		fprintf(stdout, "  Enabled: %s\n",
216c976353bSAnkit Kumar 			event_desc->fdpeta.bits.fdp_ee ? "Yes" : "No");
217c976353bSAnkit Kumar 		event_desc++;
218c976353bSAnkit Kumar 	}
219c976353bSAnkit Kumar 
220c976353bSAnkit Kumar 	fprintf(stdout, "\n");
221c976353bSAnkit Kumar 	return 0;
222c976353bSAnkit Kumar }
223c976353bSAnkit Kumar 
224c976353bSAnkit Kumar static int
225c976353bSAnkit Kumar get_fdp(struct spdk_nvme_ns *ns)
226c976353bSAnkit Kumar {
227c976353bSAnkit Kumar 	int ret;
228c976353bSAnkit Kumar 	uint32_t cdw11;
229c976353bSAnkit Kumar 	struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
230c976353bSAnkit Kumar 	const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
231c976353bSAnkit Kumar 
232c976353bSAnkit Kumar 	g_outstanding_commands = 0;
233c976353bSAnkit Kumar 	g_fdp_command_result = -1;
234c976353bSAnkit Kumar 	g_feat_result = 0;
235c976353bSAnkit Kumar 
236c976353bSAnkit Kumar 	cdw11 = nsdata->endgid;
237c976353bSAnkit Kumar 
238c976353bSAnkit Kumar 	ret = spdk_nvme_ctrlr_cmd_get_feature(ctrlr, SPDK_NVME_FEAT_FDP, cdw11, NULL, 0,
239c976353bSAnkit Kumar 					      get_feat_completion, NULL);
240c976353bSAnkit Kumar 	if (ret) {
241c976353bSAnkit Kumar 		fprintf(stderr, "Get Feature (fdp) failed\n\n");
242c976353bSAnkit Kumar 		return -1;
243c976353bSAnkit Kumar 	}
244c976353bSAnkit Kumar 
245c976353bSAnkit Kumar 	g_outstanding_commands++;
246c976353bSAnkit Kumar 	while (g_outstanding_commands) {
247c976353bSAnkit Kumar 		spdk_nvme_ctrlr_process_admin_completions(ctrlr);
248c976353bSAnkit Kumar 	}
249c976353bSAnkit Kumar 
250c976353bSAnkit Kumar 	if (g_fdp_command_result) {
251c976353bSAnkit Kumar 		fprintf(stderr, "Get Feature (fdp) failed\n\n");
252c976353bSAnkit Kumar 		return -1;
253c976353bSAnkit Kumar 	}
254c976353bSAnkit Kumar 
255c976353bSAnkit Kumar 	fdp_res.raw = g_feat_result;
256c976353bSAnkit Kumar 
257c976353bSAnkit Kumar 	fprintf(stdout, "Get Feature: FDP:\n");
258c976353bSAnkit Kumar 	fprintf(stdout, "=================\n");
259c976353bSAnkit Kumar 	fprintf(stdout, "  Enabled:                 %s\n",
260c976353bSAnkit Kumar 		fdp_res.bits.fdpe ? "Yes" : "No");
261c976353bSAnkit Kumar 	fprintf(stdout, "  FDP configuration Index: %u\n\n", fdp_res.bits.fdpci);
262c976353bSAnkit Kumar 
263c976353bSAnkit Kumar 	return 0;
264c976353bSAnkit Kumar }
265c976353bSAnkit Kumar 
266c976353bSAnkit Kumar static int
267c976353bSAnkit Kumar check_fdp_write(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair)
268c976353bSAnkit Kumar {
269c976353bSAnkit Kumar 	int ret;
270c976353bSAnkit Kumar 	uint32_t sector_size, lba_count;
271c976353bSAnkit Kumar 	uint64_t lba;
272c976353bSAnkit Kumar 	struct io_request *req;
273c976353bSAnkit Kumar 	struct spdk_nvme_ns_cmd_ext_io_opts ext_opts;
274c976353bSAnkit Kumar 
275c976353bSAnkit Kumar 	g_outstanding_commands = 0;
276c976353bSAnkit Kumar 	g_fdp_command_result = -1;
277c976353bSAnkit Kumar 
2781d77eec8SKonrad Sztyber 	ext_opts.size = SPDK_SIZEOF(&ext_opts, cdw13);
279c976353bSAnkit Kumar 	ext_opts.io_flags = SPDK_NVME_IO_FLAGS_DATA_PLACEMENT_DIRECTIVE;
280c976353bSAnkit Kumar 	ext_opts.metadata = NULL;
281c976353bSAnkit Kumar 	ext_opts.cdw13 = (pid_for_ruhu << 16);
282c976353bSAnkit Kumar 
283c976353bSAnkit Kumar 	sector_size = spdk_nvme_ns_get_sector_size(ns);
284c976353bSAnkit Kumar 
285c976353bSAnkit Kumar 	req = spdk_zmalloc(sizeof(*req), 0, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
286c976353bSAnkit Kumar 	assert(req);
287c976353bSAnkit Kumar 
288c976353bSAnkit Kumar 	lba = 0;
289c976353bSAnkit Kumar 	lba_count = 8;
290c976353bSAnkit Kumar 	req->buf_size = sector_size * lba_count;
291c976353bSAnkit Kumar 	req->contig = spdk_zmalloc(req->buf_size, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
292c976353bSAnkit Kumar 				   SPDK_MALLOC_DMA);
293c976353bSAnkit Kumar 	assert(req->contig);
294c976353bSAnkit Kumar 
295c976353bSAnkit Kumar 	ret = spdk_nvme_ns_cmd_writev_ext(ns, qpair, lba, lba_count, cmd_completion, req,
296c976353bSAnkit Kumar 					  nvme_req_reset_sgl, nvme_req_next_sge, &ext_opts);
297c976353bSAnkit Kumar 
298c976353bSAnkit Kumar 	if (ret) {
299c976353bSAnkit Kumar 		fprintf(stderr, "spdk_nvme_ns_cmd_writev_ext failed\n\n");
3004ab55a0cSAnkit Kumar 		spdk_free(req->contig);
3014ab55a0cSAnkit Kumar 		spdk_free(req);
302c976353bSAnkit Kumar 		return -1;
303c976353bSAnkit Kumar 	}
304c976353bSAnkit Kumar 
305c976353bSAnkit Kumar 	g_outstanding_commands++;
306c976353bSAnkit Kumar 	while (g_outstanding_commands) {
307c976353bSAnkit Kumar 		spdk_nvme_qpair_process_completions(qpair, 100);
308c976353bSAnkit Kumar 	}
309c976353bSAnkit Kumar 
310c976353bSAnkit Kumar 	if (g_fdp_command_result) {
311c976353bSAnkit Kumar 		fprintf(stderr, "FDP write on placement id: %u failed\n\n", pid_for_ruhu);
312c976353bSAnkit Kumar 	} else {
313c976353bSAnkit Kumar 		fprintf(stdout, "FDP write on placement id: %u success\n\n", pid_for_ruhu);
314c976353bSAnkit Kumar 	}
315c976353bSAnkit Kumar 
316c976353bSAnkit Kumar 	spdk_free(req->contig);
317c976353bSAnkit Kumar 	spdk_free(req);
318c976353bSAnkit Kumar 	return g_fdp_command_result;
319c976353bSAnkit Kumar }
320c976353bSAnkit Kumar 
321c976353bSAnkit Kumar static int
322c976353bSAnkit Kumar reclaim_unit_handle_update(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair)
323c976353bSAnkit Kumar {
324c976353bSAnkit Kumar 	int ret;
325c976353bSAnkit Kumar 	uint32_t npids = 1;
326c976353bSAnkit Kumar 	uint16_t pid_list[1] = {};
327c976353bSAnkit Kumar 
328c976353bSAnkit Kumar 	memcpy(pid_list, &pid_for_ruhu, sizeof(pid_list));
329c976353bSAnkit Kumar 	g_outstanding_commands = 0;
330c976353bSAnkit Kumar 	g_fdp_command_result = -1;
331c976353bSAnkit Kumar 
332c976353bSAnkit Kumar 	ret = spdk_nvme_ns_cmd_io_mgmt_send(ns, qpair, pid_list, npids * sizeof(uint16_t),
333c976353bSAnkit Kumar 					    SPDK_NVME_FDP_IO_MGMT_SEND_RUHU, npids - 1, cmd_completion, NULL);
334c976353bSAnkit Kumar 	if (ret) {
335c976353bSAnkit Kumar 		fprintf(stderr, "IO management send: RUH update failed\n\n");
336c976353bSAnkit Kumar 		return -1;
337c976353bSAnkit Kumar 	}
338c976353bSAnkit Kumar 
339c976353bSAnkit Kumar 	g_outstanding_commands++;
340c976353bSAnkit Kumar 	while (g_outstanding_commands) {
341c976353bSAnkit Kumar 		spdk_nvme_qpair_process_completions(qpair, 100);
342c976353bSAnkit Kumar 	}
343c976353bSAnkit Kumar 
344c976353bSAnkit Kumar 	if (g_fdp_command_result) {
345c976353bSAnkit Kumar 		fprintf(stderr, "IO management send: RUH update failed\n\n");
346c976353bSAnkit Kumar 		return -1;
347c976353bSAnkit Kumar 	}
348c976353bSAnkit Kumar 
349c976353bSAnkit Kumar 	fprintf(stdout, "IO mgmt send: RUH update for Placement ID: #%u Success\n\n",
350c976353bSAnkit Kumar 		pid_for_ruhu);
351c976353bSAnkit Kumar 	return 0;
352c976353bSAnkit Kumar }
353c976353bSAnkit Kumar 
354c976353bSAnkit Kumar static int
355c976353bSAnkit Kumar reclaim_unit_handle_status(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair)
356c976353bSAnkit Kumar {
357c976353bSAnkit Kumar 	int ret;
358c976353bSAnkit Kumar 	uint32_t i;
359c976353bSAnkit Kumar 	size_t fdp_ruhs_size;
360c976353bSAnkit Kumar 	struct spdk_nvme_fdp_ruhs *fdp_ruhs;
361c976353bSAnkit Kumar 	struct spdk_nvme_fdp_ruhs_desc *ruhs_desc;
362c976353bSAnkit Kumar 
363c976353bSAnkit Kumar 	g_outstanding_commands = 0;
364c976353bSAnkit Kumar 	g_fdp_command_result = -1;
365c976353bSAnkit Kumar 
3664ab55a0cSAnkit Kumar 	fdp_ruhs_size = sizeof(struct spdk_nvme_fdp_ruhs);
367c976353bSAnkit Kumar 	fdp_ruhs = calloc(1, fdp_ruhs_size);
3684ab55a0cSAnkit Kumar 	if (!fdp_ruhs) {
369c976353bSAnkit Kumar 		fprintf(stderr, "FDP reclaim unit handle status allocation failed!\n\n");
370c976353bSAnkit Kumar 		return -1;
371c976353bSAnkit Kumar 	}
372c976353bSAnkit Kumar 
3734ab55a0cSAnkit Kumar 	/* Fetch the reclaim unit handle status header */
3744ab55a0cSAnkit Kumar 	ret = spdk_nvme_ns_cmd_io_mgmt_recv(ns, qpair, fdp_ruhs, fdp_ruhs_size,
3754ab55a0cSAnkit Kumar 					    SPDK_NVME_FDP_IO_MGMT_RECV_RUHS, 0, cmd_completion, NULL);
3764ab55a0cSAnkit Kumar 	if (ret) {
3774ab55a0cSAnkit Kumar 		fprintf(stderr, "IO management receive: RUH status failed\n\n");
3784ab55a0cSAnkit Kumar 		free(fdp_ruhs);
3794ab55a0cSAnkit Kumar 		return -1;
3804ab55a0cSAnkit Kumar 	}
3814ab55a0cSAnkit Kumar 
3824ab55a0cSAnkit Kumar 	g_outstanding_commands++;
3834ab55a0cSAnkit Kumar 	while (g_outstanding_commands) {
3844ab55a0cSAnkit Kumar 		spdk_nvme_qpair_process_completions(qpair, 100);
3854ab55a0cSAnkit Kumar 	}
3864ab55a0cSAnkit Kumar 
3874ab55a0cSAnkit Kumar 	if (g_fdp_command_result) {
3884ab55a0cSAnkit Kumar 		fprintf(stderr, "IO management receive: RUH status failed\n\n");
3894ab55a0cSAnkit Kumar 		free(fdp_ruhs);
3904ab55a0cSAnkit Kumar 		return -1;
3914ab55a0cSAnkit Kumar 	}
3924ab55a0cSAnkit Kumar 
3934ab55a0cSAnkit Kumar 	fdp_ruhs_size += fdp_ruhs->nruhsd * sizeof(struct spdk_nvme_fdp_ruhs_desc);
3944ab55a0cSAnkit Kumar 	fdp_ruhs = realloc(fdp_ruhs, fdp_ruhs_size);
3954ab55a0cSAnkit Kumar 	if (!fdp_ruhs) {
3964ab55a0cSAnkit Kumar 		fprintf(stderr, "FDP reclaim unit handle status buffer reallocation failed!\n\n");
3974ab55a0cSAnkit Kumar 		return -1;
3984ab55a0cSAnkit Kumar 	}
3994ab55a0cSAnkit Kumar 
400c976353bSAnkit Kumar 	ret = spdk_nvme_ns_cmd_io_mgmt_recv(ns, qpair, fdp_ruhs, fdp_ruhs_size,
401c976353bSAnkit Kumar 					    SPDK_NVME_FDP_IO_MGMT_RECV_RUHS, 0, cmd_completion, NULL);
402c976353bSAnkit Kumar 	if (ret) {
403c976353bSAnkit Kumar 		fprintf(stderr, "IO management receive: RUH status failed\n\n");
404c976353bSAnkit Kumar 		free(fdp_ruhs);
405c976353bSAnkit Kumar 		return -1;
406c976353bSAnkit Kumar 	}
407c976353bSAnkit Kumar 
408c976353bSAnkit Kumar 	g_outstanding_commands++;
409c976353bSAnkit Kumar 	while (g_outstanding_commands) {
410c976353bSAnkit Kumar 		spdk_nvme_qpair_process_completions(qpair, 100);
411c976353bSAnkit Kumar 	}
412c976353bSAnkit Kumar 
413c976353bSAnkit Kumar 	if (g_fdp_command_result) {
414c976353bSAnkit Kumar 		fprintf(stderr, "IO management receive: RUH status failed\n\n");
415c976353bSAnkit Kumar 		free(fdp_ruhs);
416c976353bSAnkit Kumar 		return -1;
417c976353bSAnkit Kumar 	}
418c976353bSAnkit Kumar 
419c976353bSAnkit Kumar 	fprintf(stdout, "FDP Reclaim unit handle status\n");
420c976353bSAnkit Kumar 	fprintf(stdout, "==============================\n");
421c976353bSAnkit Kumar 
422c976353bSAnkit Kumar 	fprintf(stdout, "Number of RUHS descriptors:   %u\n", fdp_ruhs->nruhsd);
423c976353bSAnkit Kumar 	for (i = 0; i < fdp_ruhs->nruhsd; i++) {
424c976353bSAnkit Kumar 		ruhs_desc = &fdp_ruhs->ruhs_desc[i];
425c976353bSAnkit Kumar 
426c976353bSAnkit Kumar 		fprintf(stdout,
427c976353bSAnkit Kumar 			"RUHS Desc: #%04u  PID: 0x%04x  RUHID: 0x%04x  ERUT: 0x%08x  RUAMW: 0x%016"PRIx64"\n",
428c976353bSAnkit Kumar 			i, ruhs_desc->pid, ruhs_desc->ruhid, ruhs_desc->earutr, ruhs_desc->ruamw);
429c976353bSAnkit Kumar 	}
430c976353bSAnkit Kumar 	fprintf(stdout, "\n");
431c976353bSAnkit Kumar 
432c976353bSAnkit Kumar 	/* Use this Placement Identifier for Reclaim unit handle Update */
433c976353bSAnkit Kumar 	pid_for_ruhu = (&fdp_ruhs->ruhs_desc[0])->pid;
434c976353bSAnkit Kumar 
435c976353bSAnkit Kumar 	/* Use this Placement Handle to enable FDP events */
436c976353bSAnkit Kumar 	ph_for_fdp_event = pid_for_ruhu & ((1 << (16 - rgif)) - 1);
437c976353bSAnkit Kumar 
438c976353bSAnkit Kumar 	free(fdp_ruhs);
439c976353bSAnkit Kumar 	return 0;
440c976353bSAnkit Kumar }
441c976353bSAnkit Kumar 
442c976353bSAnkit Kumar static int
443c976353bSAnkit Kumar get_fdp_cfg_log_page(struct spdk_nvme_ns *ns)
444c976353bSAnkit Kumar {
445c976353bSAnkit Kumar 	uint32_t i, j;
4464ab55a0cSAnkit Kumar 	size_t fdp_cfg_size;
4474ab55a0cSAnkit Kumar 	struct spdk_nvme_fdp_cfg_log_page *fdp_cfg_log_page;
448c976353bSAnkit Kumar 	struct spdk_nvme_fdp_cfg_descriptor *cfg_desc;
449c976353bSAnkit Kumar 	struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
450c976353bSAnkit Kumar 	const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
451c976353bSAnkit Kumar 	void *log;
452c976353bSAnkit Kumar 
453c976353bSAnkit Kumar 	g_outstanding_commands = 0;
454c976353bSAnkit Kumar 	g_fdp_command_result = -1;
455c976353bSAnkit Kumar 
4564ab55a0cSAnkit Kumar 	fdp_cfg_size = sizeof(struct spdk_nvme_fdp_cfg_log_page);
4574ab55a0cSAnkit Kumar 	fdp_cfg_log_page = calloc(1, fdp_cfg_size);
4584ab55a0cSAnkit Kumar 	if (!fdp_cfg_log_page) {
4594ab55a0cSAnkit Kumar 		fprintf(stderr, "FDP config log page allocation failed!\n\n");
4604ab55a0cSAnkit Kumar 		return -1;
4614ab55a0cSAnkit Kumar 	}
4624ab55a0cSAnkit Kumar 
4634ab55a0cSAnkit Kumar 	/* Fetch the FDP configurations log page header */
464c976353bSAnkit Kumar 	if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_CONFIGURATIONS, 0,
4654ab55a0cSAnkit Kumar 			fdp_cfg_log_page, fdp_cfg_size, 0, 0, (nsdata->endgid << 16),
466c976353bSAnkit Kumar 			0, cmd_completion, NULL) == 0) {
467c976353bSAnkit Kumar 		g_outstanding_commands++;
468c976353bSAnkit Kumar 	} else {
469c976353bSAnkit Kumar 		fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP config) failed\n\n");
4704ab55a0cSAnkit Kumar 		free(fdp_cfg_log_page);
471c976353bSAnkit Kumar 		return -1;
472c976353bSAnkit Kumar 	}
473c976353bSAnkit Kumar 
474c976353bSAnkit Kumar 	while (g_outstanding_commands) {
475c976353bSAnkit Kumar 		spdk_nvme_ctrlr_process_admin_completions(ctrlr);
476c976353bSAnkit Kumar 	}
477c976353bSAnkit Kumar 
478c976353bSAnkit Kumar 	if (g_fdp_command_result) {
479c976353bSAnkit Kumar 		fprintf(stderr, "Failed to get FDP configuration log page\n\n");
4804ab55a0cSAnkit Kumar 		free(fdp_cfg_log_page);
4814ab55a0cSAnkit Kumar 		return -1;
4824ab55a0cSAnkit Kumar 	}
4834ab55a0cSAnkit Kumar 
4844ab55a0cSAnkit Kumar 	fdp_cfg_size = fdp_cfg_log_page->size;
4854ab55a0cSAnkit Kumar 	fdp_cfg_log_page = realloc(fdp_cfg_log_page, fdp_cfg_size);
4864ab55a0cSAnkit Kumar 	if (!fdp_cfg_log_page) {
4874ab55a0cSAnkit Kumar 		fprintf(stderr, "FDP config log page reallocation failed!\n\n");
4884ab55a0cSAnkit Kumar 		return -1;
4894ab55a0cSAnkit Kumar 	}
4904ab55a0cSAnkit Kumar 
4914ab55a0cSAnkit Kumar 	if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_CONFIGURATIONS, 0,
4924ab55a0cSAnkit Kumar 			fdp_cfg_log_page, fdp_cfg_size, 0, 0, (nsdata->endgid << 16),
4934ab55a0cSAnkit Kumar 			0, cmd_completion, NULL) == 0) {
4944ab55a0cSAnkit Kumar 		g_outstanding_commands++;
4954ab55a0cSAnkit Kumar 	} else {
4964ab55a0cSAnkit Kumar 		fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP config) failed\n\n");
4974ab55a0cSAnkit Kumar 		free(fdp_cfg_log_page);
4984ab55a0cSAnkit Kumar 		return -1;
4994ab55a0cSAnkit Kumar 	}
5004ab55a0cSAnkit Kumar 
5014ab55a0cSAnkit Kumar 	while (g_outstanding_commands) {
5024ab55a0cSAnkit Kumar 		spdk_nvme_ctrlr_process_admin_completions(ctrlr);
5034ab55a0cSAnkit Kumar 	}
5044ab55a0cSAnkit Kumar 
5054ab55a0cSAnkit Kumar 	if (g_fdp_command_result) {
5064ab55a0cSAnkit Kumar 		fprintf(stderr, "Failed to get FDP configuration log page\n\n");
5074ab55a0cSAnkit Kumar 		free(fdp_cfg_log_page);
508c976353bSAnkit Kumar 		return -1;
509c976353bSAnkit Kumar 	}
510c976353bSAnkit Kumar 
511c976353bSAnkit Kumar 	fprintf(stdout, "FDP configurations log page\n");
512c976353bSAnkit Kumar 	fprintf(stdout, "===========================\n");
513c976353bSAnkit Kumar 
5144ab55a0cSAnkit Kumar 	fprintf(stdout, "Number of FDP configurations:         %u\n", fdp_cfg_log_page->ncfg + 1);
5154ab55a0cSAnkit Kumar 	fprintf(stdout, "Version:                              %u\n", fdp_cfg_log_page->version);
5164ab55a0cSAnkit Kumar 	fprintf(stdout, "Size:                                 %u\n", fdp_cfg_log_page->size);
517c976353bSAnkit Kumar 
5184ab55a0cSAnkit Kumar 	log = fdp_cfg_log_page->cfg_desc;
5194ab55a0cSAnkit Kumar 	for (i = 0; i <= fdp_cfg_log_page->ncfg; i++) {
520c976353bSAnkit Kumar 		cfg_desc = log;
521c976353bSAnkit Kumar 		fprintf(stdout, "FDP Configuration Descriptor:         %u\n", i);
522c976353bSAnkit Kumar 		fprintf(stdout, "  Descriptor Size:                    %u\n", cfg_desc->ds);
523c976353bSAnkit Kumar 		fprintf(stdout, "  Reclaim Group Identifier format:    %u\n",
524c976353bSAnkit Kumar 			cfg_desc->fdpa.bits.rgif);
525c976353bSAnkit Kumar 		fprintf(stdout, "  FDP Volatile Write Cache:           %s\n",
526c976353bSAnkit Kumar 			cfg_desc->fdpa.bits.fdpvwc ? "Present" : "Not Present");
527c976353bSAnkit Kumar 		fprintf(stdout, "  FDP Configuration:                  %s\n",
528c976353bSAnkit Kumar 			cfg_desc->fdpa.bits.fdpcv ? "Valid" : "Invalid");
529c976353bSAnkit Kumar 		fprintf(stdout, "  Vendor Specific Size:               %u\n", cfg_desc->vss);
530c976353bSAnkit Kumar 		fprintf(stdout, "  Number of Reclaim Groups:           %u\n", cfg_desc->nrg);
531c976353bSAnkit Kumar 		fprintf(stdout, "  Number of Recalim Unit Handles:     %u\n", cfg_desc->nruh);
532c976353bSAnkit Kumar 		fprintf(stdout, "  Max Placement Identifiers:          %u\n", cfg_desc->maxpids + 1);
533c976353bSAnkit Kumar 		fprintf(stdout, "  Number of Namespaces Suppprted:     %u\n", cfg_desc->nns);
534c976353bSAnkit Kumar 		fprintf(stdout, "  Reclaim unit Nominal Size:          %" PRIx64 " bytes\n", cfg_desc->runs);
535c976353bSAnkit Kumar 		fprintf(stdout, "  Estimated Reclaim Unit Time Limit:  ");
536c976353bSAnkit Kumar 		if (cfg_desc->erutl) {
537c976353bSAnkit Kumar 			fprintf(stdout, "%u seconds\n", cfg_desc->erutl);
538c976353bSAnkit Kumar 		} else {
539c976353bSAnkit Kumar 			fprintf(stdout, "Not Reported\n");
540c976353bSAnkit Kumar 		}
541c976353bSAnkit Kumar 		for (j = 0; j < cfg_desc->nruh; j++) {
542c976353bSAnkit Kumar 			fprintf(stdout, "    RUH Desc #%03d:          RUH Type: %s\n", j,
543c976353bSAnkit Kumar 				cfg_desc->ruh_desc[j].ruht == SPDK_NVME_FDP_RUHT_INITIALLY_ISOLATED ? "Initially Isolated" :
544c976353bSAnkit Kumar 				cfg_desc->ruh_desc[j].ruht == SPDK_NVME_FDP_RUHT_PERSISTENTLY_ISOLATED ? "Persistently Isolated" :
545c976353bSAnkit Kumar 				"Reserved");
546c976353bSAnkit Kumar 		}
547c976353bSAnkit Kumar 		if (i == fdpci) {
548c976353bSAnkit Kumar 			rgif = cfg_desc->fdpa.bits.rgif;
549c976353bSAnkit Kumar 		}
550c976353bSAnkit Kumar 		log += cfg_desc->ds;
551c976353bSAnkit Kumar 	}
552c976353bSAnkit Kumar 
553c976353bSAnkit Kumar 	fprintf(stdout, "\n");
5544ab55a0cSAnkit Kumar 	free(fdp_cfg_log_page);
5554ab55a0cSAnkit Kumar 
556c976353bSAnkit Kumar 	return 0;
557c976353bSAnkit Kumar }
558c976353bSAnkit Kumar 
559c976353bSAnkit Kumar static int
560c976353bSAnkit Kumar get_fdp_ruhu_log_page(struct spdk_nvme_ns *ns)
561c976353bSAnkit Kumar {
562c976353bSAnkit Kumar 	uint32_t i;
5634ab55a0cSAnkit Kumar 	size_t fdp_ruhu_size;
5644ab55a0cSAnkit Kumar 	struct spdk_nvme_fdp_ruhu_log_page *fdp_ruhu_log_page;
565c976353bSAnkit Kumar 	struct spdk_nvme_fdp_ruhu_descriptor *ruhu_desc;
566c976353bSAnkit Kumar 	struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
567c976353bSAnkit Kumar 	const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
568c976353bSAnkit Kumar 
569c976353bSAnkit Kumar 	g_outstanding_commands = 0;
570c976353bSAnkit Kumar 	g_fdp_command_result = -1;
571c976353bSAnkit Kumar 
5724ab55a0cSAnkit Kumar 	fdp_ruhu_size = sizeof(struct spdk_nvme_fdp_ruhu_log_page);
5734ab55a0cSAnkit Kumar 	fdp_ruhu_log_page = calloc(1, fdp_ruhu_size);
5744ab55a0cSAnkit Kumar 	if (!fdp_ruhu_log_page) {
5754ab55a0cSAnkit Kumar 		fprintf(stderr, "FDP Reclaim Unit Handle usage log page allocation failed!\n\n");
5764ab55a0cSAnkit Kumar 		return -1;
5774ab55a0cSAnkit Kumar 	}
5784ab55a0cSAnkit Kumar 
5794ab55a0cSAnkit Kumar 	/* Fetch the FDP RUH usage log page header */
580c976353bSAnkit Kumar 	if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_RECLAIM_UNIT_HANDLE_USAGE, 0,
5814ab55a0cSAnkit Kumar 			fdp_ruhu_log_page, fdp_ruhu_size, 0, 0, (nsdata->endgid << 16),
582c976353bSAnkit Kumar 			0, cmd_completion, NULL) == 0) {
583c976353bSAnkit Kumar 		g_outstanding_commands++;
584c976353bSAnkit Kumar 	} else {
585c976353bSAnkit Kumar 		fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(RUH usage) failed\n\n");
5864ab55a0cSAnkit Kumar 		free(fdp_ruhu_log_page);
587c976353bSAnkit Kumar 		return -1;
588c976353bSAnkit Kumar 	}
589c976353bSAnkit Kumar 
590c976353bSAnkit Kumar 	while (g_outstanding_commands) {
591c976353bSAnkit Kumar 		spdk_nvme_ctrlr_process_admin_completions(ctrlr);
592c976353bSAnkit Kumar 	}
593c976353bSAnkit Kumar 
594c976353bSAnkit Kumar 	if (g_fdp_command_result) {
595c976353bSAnkit Kumar 		fprintf(stderr, "Failed to get Reclaim Unit Handle usage log page\n\n");
5964ab55a0cSAnkit Kumar 		free(fdp_ruhu_log_page);
5974ab55a0cSAnkit Kumar 		return -1;
5984ab55a0cSAnkit Kumar 	}
5994ab55a0cSAnkit Kumar 
6004ab55a0cSAnkit Kumar 	fdp_ruhu_size += fdp_ruhu_log_page->nruh * sizeof(struct spdk_nvme_fdp_ruhu_descriptor);
6014ab55a0cSAnkit Kumar 	fdp_ruhu_log_page = realloc(fdp_ruhu_log_page, fdp_ruhu_size);
6024ab55a0cSAnkit Kumar 	if (!fdp_ruhu_log_page) {
6034ab55a0cSAnkit Kumar 		fprintf(stderr, "FDP Reclaim Unit Handle usage log page reallocation failed!\n\n");
6044ab55a0cSAnkit Kumar 		return -1;
6054ab55a0cSAnkit Kumar 	}
6064ab55a0cSAnkit Kumar 
6074ab55a0cSAnkit Kumar 	if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_RECLAIM_UNIT_HANDLE_USAGE, 0,
6084ab55a0cSAnkit Kumar 			fdp_ruhu_log_page, fdp_ruhu_size, 0, 0, (nsdata->endgid << 16),
6094ab55a0cSAnkit Kumar 			0, cmd_completion, NULL) == 0) {
6104ab55a0cSAnkit Kumar 		g_outstanding_commands++;
6114ab55a0cSAnkit Kumar 	} else {
6124ab55a0cSAnkit Kumar 		fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(RUH usage) failed\n\n");
6134ab55a0cSAnkit Kumar 		free(fdp_ruhu_log_page);
6144ab55a0cSAnkit Kumar 		return -1;
6154ab55a0cSAnkit Kumar 	}
6164ab55a0cSAnkit Kumar 
6174ab55a0cSAnkit Kumar 	while (g_outstanding_commands) {
6184ab55a0cSAnkit Kumar 		spdk_nvme_ctrlr_process_admin_completions(ctrlr);
6194ab55a0cSAnkit Kumar 	}
6204ab55a0cSAnkit Kumar 
6214ab55a0cSAnkit Kumar 	if (g_fdp_command_result) {
6224ab55a0cSAnkit Kumar 		fprintf(stderr, "Failed to get Reclaim Unit Handle usage log page\n\n");
6234ab55a0cSAnkit Kumar 		free(fdp_ruhu_log_page);
624c976353bSAnkit Kumar 		return -1;
625c976353bSAnkit Kumar 	}
626c976353bSAnkit Kumar 
627c976353bSAnkit Kumar 	fprintf(stdout, "FDP reclaim unit handle usage log page\n");
628c976353bSAnkit Kumar 	fprintf(stdout, "======================================\n");
629c976353bSAnkit Kumar 
6304ab55a0cSAnkit Kumar 	fprintf(stdout, "Number of Reclaim Unit Handles:       %u\n", fdp_ruhu_log_page->nruh);
631c976353bSAnkit Kumar 
6324ab55a0cSAnkit Kumar 	for (i = 0; i < fdp_ruhu_log_page->nruh; i++) {
6334ab55a0cSAnkit Kumar 		ruhu_desc = &fdp_ruhu_log_page->ruhu_desc[i];
634c976353bSAnkit Kumar 
635c976353bSAnkit Kumar 		fprintf(stdout, "  RUH Usage Desc #%03d:   RUH Attributes: %s\n", i,
636c976353bSAnkit Kumar 			ruhu_desc->ruha == SPDK_NVME_FDP_RUHA_UNUSED ? "Unused" :
637c976353bSAnkit Kumar 			ruhu_desc->ruha == SPDK_NVME_FDP_RUHA_HOST_SPECIFIED ? "Host Specified" :
638c976353bSAnkit Kumar 			ruhu_desc->ruha == SPDK_NVME_FDP_RUHA_CTRLR_SPECIFIED ? "Controller Specified" :
639c976353bSAnkit Kumar 			"Reserved");
640c976353bSAnkit Kumar 	}
641c976353bSAnkit Kumar 
642c976353bSAnkit Kumar 	fprintf(stdout, "\n");
6434ab55a0cSAnkit Kumar 	free(fdp_ruhu_log_page);
6444ab55a0cSAnkit Kumar 
645c976353bSAnkit Kumar 	return 0;
646c976353bSAnkit Kumar }
647c976353bSAnkit Kumar 
648c976353bSAnkit Kumar static int
649c976353bSAnkit Kumar get_fdp_stats_log_page(struct spdk_nvme_ns *ns)
650c976353bSAnkit Kumar {
6514ab55a0cSAnkit Kumar 	struct spdk_nvme_fdp_stats_log_page fdp_stats_log_page;
652c976353bSAnkit Kumar 	struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
653c976353bSAnkit Kumar 	const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
654c976353bSAnkit Kumar 
655c976353bSAnkit Kumar 	g_outstanding_commands = 0;
656c976353bSAnkit Kumar 	g_fdp_command_result = -1;
657c976353bSAnkit Kumar 
658c976353bSAnkit Kumar 	if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_STATISTICS, 0,
6594ab55a0cSAnkit Kumar 			&fdp_stats_log_page, 64, 0, 0, (nsdata->endgid << 16), 0,
660c976353bSAnkit Kumar 			cmd_completion, NULL) == 0) {
661c976353bSAnkit Kumar 		g_outstanding_commands++;
662c976353bSAnkit Kumar 	} else {
663c976353bSAnkit Kumar 		fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP stats) failed\n\n");
664c976353bSAnkit Kumar 		return -1;
665c976353bSAnkit Kumar 	}
666c976353bSAnkit Kumar 
667c976353bSAnkit Kumar 	while (g_outstanding_commands) {
668c976353bSAnkit Kumar 		spdk_nvme_ctrlr_process_admin_completions(ctrlr);
669c976353bSAnkit Kumar 	}
670c976353bSAnkit Kumar 
671c976353bSAnkit Kumar 	if (g_fdp_command_result) {
672c976353bSAnkit Kumar 		fprintf(stderr, "Failed to get FDP statistics log page\n\n");
673c976353bSAnkit Kumar 		return -1;
674c976353bSAnkit Kumar 	}
675c976353bSAnkit Kumar 
676c976353bSAnkit Kumar 	fprintf(stdout, "FDP statistics log page\n");
677c976353bSAnkit Kumar 	fprintf(stdout, "=======================\n");
678c976353bSAnkit Kumar 
679c976353bSAnkit Kumar 	fprintf(stdout, "Host bytes with metadata written:  ");
6804ab55a0cSAnkit Kumar 	print_uint128_dec(fdp_stats_log_page.hbmw);
681c976353bSAnkit Kumar 	fprintf(stdout, "\n");
682c976353bSAnkit Kumar 	fprintf(stdout, "Media bytes with metadata written: ");
6834ab55a0cSAnkit Kumar 	print_uint128_dec(fdp_stats_log_page.mbmw);
684c976353bSAnkit Kumar 	fprintf(stdout, "\n");
685c976353bSAnkit Kumar 	fprintf(stdout, "Media bytes erased:                ");
6864ab55a0cSAnkit Kumar 	print_uint128_dec(fdp_stats_log_page.mbe);
687c976353bSAnkit Kumar 	fprintf(stdout, "\n\n");
688c976353bSAnkit Kumar 
689c976353bSAnkit Kumar 	return 0;
690c976353bSAnkit Kumar }
691c976353bSAnkit Kumar 
692c976353bSAnkit Kumar static int
693c976353bSAnkit Kumar get_fdp_events_log_page(struct spdk_nvme_ns *ns)
694c976353bSAnkit Kumar {
695c976353bSAnkit Kumar 	uint32_t i;
6964ab55a0cSAnkit Kumar 	size_t fdp_event_size;
6974ab55a0cSAnkit Kumar 	struct spdk_nvme_fdp_events_log_page *fdp_events_log_page;
698c976353bSAnkit Kumar 	struct spdk_nvme_fdp_event *event;
699c976353bSAnkit Kumar 	struct spdk_nvme_fdp_event_media_reallocated *media_reallocated;
700c976353bSAnkit Kumar 	struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
701c976353bSAnkit Kumar 	const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
702c976353bSAnkit Kumar 
703c976353bSAnkit Kumar 	g_outstanding_commands = 0;
704c976353bSAnkit Kumar 	g_fdp_command_result = -1;
705c976353bSAnkit Kumar 
7064ab55a0cSAnkit Kumar 	fdp_event_size = sizeof(struct spdk_nvme_fdp_events_log_page);
7074ab55a0cSAnkit Kumar 	fdp_events_log_page = calloc(1, fdp_event_size);
7084ab55a0cSAnkit Kumar 	if (!fdp_events_log_page) {
7094ab55a0cSAnkit Kumar 		fprintf(stderr, "FDP events log page allocation failed!\n\n");
7104ab55a0cSAnkit Kumar 		return -1;
7114ab55a0cSAnkit Kumar 	}
7124ab55a0cSAnkit Kumar 
7134ab55a0cSAnkit Kumar 	/* Fetch the FDP events log page header */
714c976353bSAnkit Kumar 	if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_EVENTS, 0,
7154ab55a0cSAnkit Kumar 			fdp_events_log_page, fdp_event_size, 0,
716c976353bSAnkit Kumar 			(SPDK_NVME_FDP_REPORT_HOST_EVENTS << 8), (nsdata->endgid << 16),
717c976353bSAnkit Kumar 			0, cmd_completion, NULL) == 0) {
718c976353bSAnkit Kumar 		g_outstanding_commands++;
719c976353bSAnkit Kumar 	} else {
720c976353bSAnkit Kumar 		fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP events) failed\n\n");
7214ab55a0cSAnkit Kumar 		free(fdp_events_log_page);
722c976353bSAnkit Kumar 		return -1;
723c976353bSAnkit Kumar 	}
724c976353bSAnkit Kumar 
725c976353bSAnkit Kumar 	while (g_outstanding_commands) {
726c976353bSAnkit Kumar 		spdk_nvme_ctrlr_process_admin_completions(ctrlr);
727c976353bSAnkit Kumar 	}
728c976353bSAnkit Kumar 
729c976353bSAnkit Kumar 	if (g_fdp_command_result) {
730c976353bSAnkit Kumar 		fprintf(stderr, "Failed to get eventss log page\n\n");
7314ab55a0cSAnkit Kumar 		free(fdp_events_log_page);
7324ab55a0cSAnkit Kumar 		return -1;
7334ab55a0cSAnkit Kumar 	}
7344ab55a0cSAnkit Kumar 
7354ab55a0cSAnkit Kumar 	fdp_event_size += fdp_events_log_page->nevents * sizeof(struct spdk_nvme_fdp_event);
7364ab55a0cSAnkit Kumar 	fdp_events_log_page = realloc(fdp_events_log_page, fdp_event_size);
7374ab55a0cSAnkit Kumar 	if (!fdp_events_log_page) {
7384ab55a0cSAnkit Kumar 		fprintf(stderr, "FDP events log page reallocation failed!\n\n");
7394ab55a0cSAnkit Kumar 		return -1;
7404ab55a0cSAnkit Kumar 	}
7414ab55a0cSAnkit Kumar 
7424ab55a0cSAnkit Kumar 	/* Only fetch FDP host events here */
7434ab55a0cSAnkit Kumar 	if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_EVENTS, 0,
7444ab55a0cSAnkit Kumar 			fdp_events_log_page, fdp_event_size, 0,
7454ab55a0cSAnkit Kumar 			(SPDK_NVME_FDP_REPORT_HOST_EVENTS << 8), (nsdata->endgid << 16),
7464ab55a0cSAnkit Kumar 			0, cmd_completion, NULL) == 0) {
7474ab55a0cSAnkit Kumar 		g_outstanding_commands++;
7484ab55a0cSAnkit Kumar 	} else {
7494ab55a0cSAnkit Kumar 		fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP events) failed\n\n");
7504ab55a0cSAnkit Kumar 		free(fdp_events_log_page);
7514ab55a0cSAnkit Kumar 		return -1;
7524ab55a0cSAnkit Kumar 	}
7534ab55a0cSAnkit Kumar 
7544ab55a0cSAnkit Kumar 	while (g_outstanding_commands) {
7554ab55a0cSAnkit Kumar 		spdk_nvme_ctrlr_process_admin_completions(ctrlr);
7564ab55a0cSAnkit Kumar 	}
7574ab55a0cSAnkit Kumar 
7584ab55a0cSAnkit Kumar 	if (g_fdp_command_result) {
7594ab55a0cSAnkit Kumar 		fprintf(stderr, "Failed to get eventss log page\n\n");
7604ab55a0cSAnkit Kumar 		free(fdp_events_log_page);
761c976353bSAnkit Kumar 		return -1;
762c976353bSAnkit Kumar 	}
763c976353bSAnkit Kumar 
764c976353bSAnkit Kumar 	fprintf(stdout, "FDP events log page\n");
765c976353bSAnkit Kumar 	fprintf(stdout, "===================\n");
7664ab55a0cSAnkit Kumar 	fprintf(stdout, "Number of FDP events: %u\n", fdp_events_log_page->nevents);
767c976353bSAnkit Kumar 
7684ab55a0cSAnkit Kumar 	for (i = 0; i < fdp_events_log_page->nevents; i++) {
7694ab55a0cSAnkit Kumar 		event = &fdp_events_log_page->event[i];
770c976353bSAnkit Kumar 
771c976353bSAnkit Kumar 		fprintf(stdout, "FDP Event #%u:\n", i);
772c976353bSAnkit Kumar 		fprintf(stdout, "  Event Type:                      %s\n",
773c976353bSAnkit Kumar 			event->etype == SPDK_NVME_FDP_EVENT_RU_NOT_WRITTEN_CAPACITY ? "RU Not Written to Capacity" :
774c976353bSAnkit Kumar 			event->etype == SPDK_NVME_FDP_EVENT_RU_TIME_LIMIT_EXCEEDED ? "RU Time Limit Exceeded" :
775c976353bSAnkit Kumar 			event->etype == SPDK_NVME_FDP_EVENT_CTRLR_RESET_MODIFY_RUH ? "Ctrlr Reset Modified RUH's" :
776c976353bSAnkit Kumar 			event->etype == SPDK_NVME_FDP_EVENT_INVALID_PLACEMENT_ID ? "Invalid Placement Identifier" :
777c976353bSAnkit Kumar 			event->etype == SPDK_NVME_FDP_EVENT_MEDIA_REALLOCATED ? "Media Reallocated" :
778c976353bSAnkit Kumar 			event->etype == SPDK_NVME_FDP_EVENT_IMPLICIT_MODIFIED_RUH ? "Implicitly modified RUH" :
779c976353bSAnkit Kumar 			"Reserved");
780c976353bSAnkit Kumar 		fprintf(stdout, "  Placement Identifier:            %s\n",
781c976353bSAnkit Kumar 			event->fdpef.bits.piv ? "Valid" : "Invalid");
782c976353bSAnkit Kumar 		fprintf(stdout, "  NSID:                            %s\n",
783c976353bSAnkit Kumar 			event->fdpef.bits.nsidv ? "Valid" : "Invalid");
784c976353bSAnkit Kumar 		fprintf(stdout, "  Location:                        %s\n",
785c976353bSAnkit Kumar 			event->fdpef.bits.lv ? "Valid" : "Invalid");
786c976353bSAnkit Kumar 		if (event->fdpef.bits.piv) {
787c976353bSAnkit Kumar 			fprintf(stdout, "  Placement Identifier:            %u\n", event->pid);
788c976353bSAnkit Kumar 		} else {
789c976353bSAnkit Kumar 			fprintf(stdout, "  Placement Identifier:            Reserved\n");
790c976353bSAnkit Kumar 		}
791c976353bSAnkit Kumar 		fprintf(stdout, "  Event Timestamp:                 %" PRIx64 "\n", event->timestamp);
792c976353bSAnkit Kumar 		if (event->fdpef.bits.nsidv) {
793c976353bSAnkit Kumar 			fprintf(stdout, "  Namespace Identifier:            %u\n", event->nsid);
794c976353bSAnkit Kumar 		} else {
795c976353bSAnkit Kumar 			fprintf(stdout, "  Namespace Identifier:            Ignore\n");
796c976353bSAnkit Kumar 		}
797c976353bSAnkit Kumar 
798c976353bSAnkit Kumar 		if (event->etype == SPDK_NVME_FDP_EVENT_MEDIA_REALLOCATED) {
799c976353bSAnkit Kumar 			media_reallocated = (struct spdk_nvme_fdp_event_media_reallocated *)&event->event_type_specific;
800c976353bSAnkit Kumar 
801c976353bSAnkit Kumar 			fprintf(stdout, "  LBA:                             %s\n",
802c976353bSAnkit Kumar 				media_reallocated->sef.bits.lbav ? "Valid" : "Invalid");
803c976353bSAnkit Kumar 			fprintf(stdout, "  Number of LBA's Moved:           %u\n", media_reallocated->nlbam);
804c976353bSAnkit Kumar 			if (media_reallocated->sef.bits.lbav) {
805c976353bSAnkit Kumar 				fprintf(stdout, "  Logical Block Address:           %u\n", event->nsid);
806c976353bSAnkit Kumar 			} else {
807c976353bSAnkit Kumar 				fprintf(stdout, "  Logical Block Address:           Ignore\n");
808c976353bSAnkit Kumar 			}
809c976353bSAnkit Kumar 		}
810c976353bSAnkit Kumar 
811c976353bSAnkit Kumar 		if (event->fdpef.bits.lv) {
812c976353bSAnkit Kumar 			fprintf(stdout, "  Reclaim Group Identifier:        %u\n", event->rgid);
813c976353bSAnkit Kumar 		} else {
814c976353bSAnkit Kumar 			fprintf(stdout, "  Reclaim Group Identifier:        Ignore\n");
815c976353bSAnkit Kumar 		}
816c976353bSAnkit Kumar 		if (event->fdpef.bits.lv) {
817c976353bSAnkit Kumar 			fprintf(stdout, "  Reclaim Unit Handle Identifier:  %u\n", event->ruhid);
818c976353bSAnkit Kumar 		} else {
819c976353bSAnkit Kumar 			fprintf(stdout, "  Reclaim Unit Handle Identifier:  Ignore\n");
820c976353bSAnkit Kumar 		}
821c976353bSAnkit Kumar 	}
822c976353bSAnkit Kumar 
823c976353bSAnkit Kumar 	fprintf(stdout, "\n");
8244ab55a0cSAnkit Kumar 	free(fdp_events_log_page);
8254ab55a0cSAnkit Kumar 
826c976353bSAnkit Kumar 	return 0;
827c976353bSAnkit Kumar }
828c976353bSAnkit Kumar 
829c976353bSAnkit Kumar static int
830c976353bSAnkit Kumar fdp_tests(struct spdk_nvme_ns *ns)
831c976353bSAnkit Kumar {
832c976353bSAnkit Kumar 	struct spdk_nvme_qpair *qpair;
833c976353bSAnkit Kumar 	struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
834c976353bSAnkit Kumar 	int ret, err;
835c976353bSAnkit Kumar 
836c976353bSAnkit Kumar 	qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, NULL, 0);
837c976353bSAnkit Kumar 	if (!qpair) {
838c976353bSAnkit Kumar 		fprintf(stderr, "spdk_nvme_ctrlr_alloc_io_qpair() failed\n");
839c976353bSAnkit Kumar 		return -EIO;
840c976353bSAnkit Kumar 	}
841c976353bSAnkit Kumar 
842c976353bSAnkit Kumar 	ret = 0;
843c976353bSAnkit Kumar 
844c976353bSAnkit Kumar 	fprintf(stdout, "==================================\n");
845c976353bSAnkit Kumar 	fprintf(stdout, "== FDP tests for Namespace: #%02u ==\n", spdk_nvme_ns_get_id(ns));
846c976353bSAnkit Kumar 	fprintf(stdout, "==================================\n\n");
847c976353bSAnkit Kumar 	err = get_fdp(ns);
848c976353bSAnkit Kumar 	if (err) {
849c976353bSAnkit Kumar 		spdk_nvme_ctrlr_free_io_qpair(qpair);
850c976353bSAnkit Kumar 		return err;
851c976353bSAnkit Kumar 	}
852c976353bSAnkit Kumar 
853c976353bSAnkit Kumar 	if (!fdp_res.bits.fdpe) {
854c976353bSAnkit Kumar 		fprintf(stdout, "FDP support disabled\n");
855c976353bSAnkit Kumar 		spdk_nvme_ctrlr_free_io_qpair(qpair);
856c976353bSAnkit Kumar 		return 0;
857c976353bSAnkit Kumar 	}
858c976353bSAnkit Kumar 
859c976353bSAnkit Kumar 	fdpci = fdp_res.bits.fdpci;
860c976353bSAnkit Kumar 	err = get_fdp_cfg_log_page(ns);
861c976353bSAnkit Kumar 	if (err) {
862c976353bSAnkit Kumar 		spdk_nvme_ctrlr_free_io_qpair(qpair);
863c976353bSAnkit Kumar 		return err;
864c976353bSAnkit Kumar 	}
865c976353bSAnkit Kumar 
866c976353bSAnkit Kumar 	ret += get_fdp_ruhu_log_page(ns);
867c976353bSAnkit Kumar 	ret += get_fdp_stats_log_page(ns);
868c976353bSAnkit Kumar 
869c976353bSAnkit Kumar 	err = reclaim_unit_handle_status(ns, qpair);
870c976353bSAnkit Kumar 	if (err) {
871c976353bSAnkit Kumar 		spdk_nvme_ctrlr_free_io_qpair(qpair);
872c976353bSAnkit Kumar 		return err;
873c976353bSAnkit Kumar 	}
874c976353bSAnkit Kumar 
875c976353bSAnkit Kumar 	err = check_fdp_write(ns, qpair);
876c976353bSAnkit Kumar 	if (err) {
877c976353bSAnkit Kumar 		spdk_nvme_ctrlr_free_io_qpair(qpair);
878c976353bSAnkit Kumar 		return err;
879c976353bSAnkit Kumar 	}
880c976353bSAnkit Kumar 
881c976353bSAnkit Kumar 	ret += set_fdp_events(ns);
882c976353bSAnkit Kumar 	ret += reclaim_unit_handle_update(ns, qpair);
883c976353bSAnkit Kumar 
884c976353bSAnkit Kumar 	ret += get_fdp_events(ns);
885c976353bSAnkit Kumar 	ret += get_fdp_events_log_page(ns);
886c976353bSAnkit Kumar 
887c976353bSAnkit Kumar 	return ret;
888c976353bSAnkit Kumar }
889c976353bSAnkit Kumar 
890c976353bSAnkit Kumar static void
891c976353bSAnkit Kumar register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
892c976353bSAnkit Kumar {
893c976353bSAnkit Kumar 	struct ns_entry *entry;
894c976353bSAnkit Kumar 	const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
895c976353bSAnkit Kumar 
896c976353bSAnkit Kumar 	entry = malloc(sizeof(struct ns_entry));
897c976353bSAnkit Kumar 	if (entry == NULL) {
898c976353bSAnkit Kumar 		perror("ns_entry malloc");
899c976353bSAnkit Kumar 		exit(1);
900c976353bSAnkit Kumar 	}
901c976353bSAnkit Kumar 
902c976353bSAnkit Kumar 	entry->ctrlr = ctrlr;
903c976353bSAnkit Kumar 	entry->ns = ns;
904c976353bSAnkit Kumar 	entry->next = g_namespaces;
905c976353bSAnkit Kumar 	g_namespaces = entry;
906c976353bSAnkit Kumar 
907c976353bSAnkit Kumar 	printf("Namespace ID: %d Endurance Group ID: %d\n", spdk_nvme_ns_get_id(ns),
908c976353bSAnkit Kumar 	       nsdata->endgid);
909c976353bSAnkit Kumar }
910c976353bSAnkit Kumar 
911c976353bSAnkit Kumar static bool
912c976353bSAnkit Kumar probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
913c976353bSAnkit Kumar 	 struct spdk_nvme_ctrlr_opts *opts)
914c976353bSAnkit Kumar {
915c976353bSAnkit Kumar 	fprintf(stdout, "Attaching to %s\n", trid->traddr);
916c976353bSAnkit Kumar 
917c976353bSAnkit Kumar 	return true;
918c976353bSAnkit Kumar }
919c976353bSAnkit Kumar 
920c976353bSAnkit Kumar static void
921c976353bSAnkit Kumar attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
922c976353bSAnkit Kumar 	  struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
923c976353bSAnkit Kumar {
924c976353bSAnkit Kumar 	int num_ns, nsid;
925c976353bSAnkit Kumar 	struct spdk_nvme_ns *ns;
926c976353bSAnkit Kumar 	const struct spdk_nvme_ctrlr_data *cdata;
927c976353bSAnkit Kumar 
928c976353bSAnkit Kumar 	cdata = spdk_nvme_ctrlr_get_data(ctrlr);
929c976353bSAnkit Kumar 
930b4d406b7SAnkit Kumar 	if (cdata->ctratt.bits.fdps) {
931c976353bSAnkit Kumar 		fprintf(stdout, "Controller supports FDP Attached to %s\n", trid->traddr);
932c976353bSAnkit Kumar 		num_ns = spdk_nvme_ctrlr_get_num_ns(ctrlr);
933c976353bSAnkit Kumar 		if (num_ns < 1) {
934c976353bSAnkit Kumar 			printf("No valid namespaces in controller\n");
935c976353bSAnkit Kumar 		} else {
936c976353bSAnkit Kumar 			for (nsid = spdk_nvme_ctrlr_get_first_active_ns(ctrlr); nsid != 0;
937c976353bSAnkit Kumar 			     nsid = spdk_nvme_ctrlr_get_next_active_ns(ctrlr, nsid)) {
938c976353bSAnkit Kumar 				ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid);
939c976353bSAnkit Kumar 				register_ns(ctrlr, ns);
940c976353bSAnkit Kumar 			}
941c976353bSAnkit Kumar 		}
942c976353bSAnkit Kumar 	} else {
943c976353bSAnkit Kumar 		fprintf(stdout, "Controller attached to: %s doesn't support FDP\n", trid->traddr);
944c976353bSAnkit Kumar 	}
945c976353bSAnkit Kumar }
946c976353bSAnkit Kumar 
947c976353bSAnkit Kumar static void
948c976353bSAnkit Kumar cleanup(void)
949c976353bSAnkit Kumar {
950c976353bSAnkit Kumar 	struct ns_entry	*ns_entry = g_namespaces;
951c976353bSAnkit Kumar 	struct spdk_nvme_detach_ctx *detach_ctx = NULL;
952c976353bSAnkit Kumar 
953c976353bSAnkit Kumar 	while (ns_entry) {
954c976353bSAnkit Kumar 		struct ns_entry *next = ns_entry->next;
955c976353bSAnkit Kumar 
956c976353bSAnkit Kumar 		spdk_nvme_detach_async(ns_entry->ctrlr, &detach_ctx);
957c976353bSAnkit Kumar 
958c976353bSAnkit Kumar 		free(ns_entry);
959c976353bSAnkit Kumar 		ns_entry = next;
960c976353bSAnkit Kumar 	}
961c976353bSAnkit Kumar 
962c976353bSAnkit Kumar 	if (detach_ctx) {
963c976353bSAnkit Kumar 		spdk_nvme_detach_poll(detach_ctx);
964c976353bSAnkit Kumar 	}
965c976353bSAnkit Kumar }
966c976353bSAnkit Kumar 
967c976353bSAnkit Kumar static void
968c976353bSAnkit Kumar usage(const char *program_name)
969c976353bSAnkit Kumar {
970c976353bSAnkit Kumar 	printf("%s [options]", program_name);
971c976353bSAnkit Kumar 	printf("\n");
972c976353bSAnkit Kumar 	printf("options:\n");
973c976353bSAnkit Kumar 	printf(" -r trid    remote NVMe over Fabrics target address\n");
974c976353bSAnkit Kumar 	printf("    Format: 'key:value [key:value] ...'\n");
975c976353bSAnkit Kumar 	printf("    Keys:\n");
976c976353bSAnkit Kumar 	printf("     trtype      Transport type (e.g. RDMA)\n");
977c976353bSAnkit Kumar 	printf("     adrfam      Address family (e.g. IPv4, IPv6)\n");
978c976353bSAnkit Kumar 	printf("     traddr      Transport address (e.g. 192.168.100.8)\n");
979c976353bSAnkit Kumar 	printf("     trsvcid     Transport service identifier (e.g. 4420)\n");
980c976353bSAnkit Kumar 	printf("     subnqn      Subsystem NQN (default: %s)\n", SPDK_NVMF_DISCOVERY_NQN);
981c976353bSAnkit Kumar 	printf("    Example: -r 'trtype:RDMA adrfam:IPv4 traddr:192.168.100.8 trsvcid:4420'\n");
982c976353bSAnkit Kumar 	printf(" -h         show this usage\n");
983c976353bSAnkit Kumar }
984c976353bSAnkit Kumar 
985c976353bSAnkit Kumar static int
986c976353bSAnkit Kumar parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
987c976353bSAnkit Kumar {
988c976353bSAnkit Kumar 	int op;
989c976353bSAnkit Kumar 
990c976353bSAnkit Kumar 	spdk_nvme_trid_populate_transport(&g_trid, SPDK_NVME_TRANSPORT_PCIE);
991c976353bSAnkit Kumar 	snprintf(g_trid.subnqn, sizeof(g_trid.subnqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
992c976353bSAnkit Kumar 
993c976353bSAnkit Kumar 	while ((op = getopt(argc, argv, "r:h")) != -1) {
994c976353bSAnkit Kumar 		switch (op) {
995c976353bSAnkit Kumar 		case 'r':
996c976353bSAnkit Kumar 			if (spdk_nvme_transport_id_parse(&g_trid, optarg) != 0) {
997c976353bSAnkit Kumar 				fprintf(stderr, "Error parsing transport address\n");
998c976353bSAnkit Kumar 				return 1;
999c976353bSAnkit Kumar 			}
1000c976353bSAnkit Kumar 
1001c976353bSAnkit Kumar 			g_use_trid = true;
1002c976353bSAnkit Kumar 			break;
1003c976353bSAnkit Kumar 		case 'h':
1004c976353bSAnkit Kumar 			usage(argv[0]);
1005c976353bSAnkit Kumar 			exit(EXIT_SUCCESS);
1006c976353bSAnkit Kumar 		default:
1007c976353bSAnkit Kumar 			usage(argv[0]);
1008c976353bSAnkit Kumar 			return 1;
1009c976353bSAnkit Kumar 		}
1010c976353bSAnkit Kumar 	}
1011c976353bSAnkit Kumar 
1012c976353bSAnkit Kumar 	return 0;
1013c976353bSAnkit Kumar }
1014c976353bSAnkit Kumar 
1015c976353bSAnkit Kumar int
1016c976353bSAnkit Kumar main(int argc, char **argv)
1017c976353bSAnkit Kumar {
1018c976353bSAnkit Kumar 	int			rc;
1019c976353bSAnkit Kumar 	struct spdk_env_opts	opts;
1020c976353bSAnkit Kumar 	struct ns_entry	*ns_entry;
1021c976353bSAnkit Kumar 
1022*57fd99b9SJim Harris 	opts.opts_size = sizeof(opts);
1023c976353bSAnkit Kumar 	spdk_env_opts_init(&opts);
1024c976353bSAnkit Kumar 	rc = parse_args(argc, argv, &opts);
1025c976353bSAnkit Kumar 	if (rc != 0) {
1026c976353bSAnkit Kumar 		return rc;
1027c976353bSAnkit Kumar 	}
1028c976353bSAnkit Kumar 
1029c976353bSAnkit Kumar 	opts.name = "fdp";
1030c976353bSAnkit Kumar 	opts.core_mask = "0x1";
1031c976353bSAnkit Kumar 	opts.shm_id = 0;
1032c976353bSAnkit Kumar 	if (spdk_env_init(&opts) < 0) {
1033c976353bSAnkit Kumar 		fprintf(stderr, "Unable to initialize SPDK env\n");
1034c976353bSAnkit Kumar 		return 1;
1035c976353bSAnkit Kumar 	}
1036c976353bSAnkit Kumar 
1037c976353bSAnkit Kumar 	printf("Initializing NVMe Controllers\n");
1038c976353bSAnkit Kumar 
1039c976353bSAnkit Kumar 	rc = spdk_nvme_probe(g_use_trid ? &g_trid : NULL, NULL, probe_cb, attach_cb, NULL);
1040c976353bSAnkit Kumar 	if (rc != 0) {
1041c976353bSAnkit Kumar 		fprintf(stderr, "spdk_nvme_probe() failed\n");
1042c976353bSAnkit Kumar 		return 1;
1043c976353bSAnkit Kumar 	}
1044c976353bSAnkit Kumar 
1045c976353bSAnkit Kumar 	if (g_namespaces == NULL) {
1046c976353bSAnkit Kumar 		fprintf(stderr, "no NVMe controllers found\n");
1047c976353bSAnkit Kumar 		return 1;
1048c976353bSAnkit Kumar 	}
1049c976353bSAnkit Kumar 
1050c976353bSAnkit Kumar 	printf("Initialization complete.\n\n");
1051c976353bSAnkit Kumar 
1052c976353bSAnkit Kumar 	ns_entry = g_namespaces;
1053c976353bSAnkit Kumar 	while (ns_entry != NULL) {
1054c976353bSAnkit Kumar 		rc = fdp_tests(ns_entry->ns);
1055c976353bSAnkit Kumar 		if (rc) {
1056c976353bSAnkit Kumar 			break;
1057c976353bSAnkit Kumar 		}
1058c976353bSAnkit Kumar 		ns_entry = ns_entry->next;
1059c976353bSAnkit Kumar 	}
1060c976353bSAnkit Kumar 
1061c976353bSAnkit Kumar 	printf("FDP test %s\n", rc ? "failed" : "passed");
1062c976353bSAnkit Kumar 	cleanup();
1063c976353bSAnkit Kumar 
1064c976353bSAnkit Kumar 	return 0;
1065c976353bSAnkit Kumar }
1066