Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2022 Intel Corporation.
3 : : * Copyright (c) Samsung Electronics Co., Ltd.
4 : : * All rights reserved.
5 : : */
6 : :
7 : : #include "libxnvme.h"
8 : :
9 : : #include "bdev_xnvme.h"
10 : :
11 : : #include "spdk/stdinc.h"
12 : :
13 : : #include "spdk/barrier.h"
14 : : #include "spdk/bdev.h"
15 : : #include "spdk/env.h"
16 : : #include "spdk/fd.h"
17 : : #include "spdk/likely.h"
18 : : #include "spdk/thread.h"
19 : : #include "spdk/json.h"
20 : : #include "spdk/util.h"
21 : : #include "spdk/string.h"
22 : :
23 : : #include "spdk/log.h"
24 : :
25 : : struct bdev_xnvme_io_channel {
26 : : struct xnvme_queue *queue;
27 : : struct spdk_poller *poller;
28 : : };
29 : :
30 : : struct bdev_xnvme_task {
31 : : struct bdev_xnvme_io_channel *ch;
32 : : TAILQ_ENTRY(bdev_xnvme_task) link;
33 : : };
34 : :
35 : : struct bdev_xnvme {
36 : : struct spdk_bdev bdev;
37 : : char *filename;
38 : : char *io_mechanism;
39 : : struct xnvme_dev *dev;
40 : : uint32_t nsid;
41 : : bool conserve_cpu;
42 : :
43 : : TAILQ_ENTRY(bdev_xnvme) link;
44 : : };
45 : :
46 : : static int bdev_xnvme_init(void);
47 : : static void bdev_xnvme_fini(void);
48 : : static void bdev_xnvme_free(struct bdev_xnvme *xnvme);
49 : : static TAILQ_HEAD(, bdev_xnvme) g_xnvme_bdev_head = TAILQ_HEAD_INITIALIZER(g_xnvme_bdev_head);
50 : :
51 : : static int
52 : 94 : bdev_xnvme_get_ctx_size(void)
53 : : {
54 : 94 : return sizeof(struct bdev_xnvme_task);
55 : : }
56 : :
57 : : static int
58 : 12 : bdev_xnvme_config_json(struct spdk_json_write_ctx *w)
59 : : {
60 : : struct bdev_xnvme *xnvme;
61 : :
62 [ + + ]: 18 : TAILQ_FOREACH(xnvme, &g_xnvme_bdev_head, link) {
63 : 6 : spdk_json_write_object_begin(w);
64 : :
65 : 6 : spdk_json_write_named_string(w, "method", "bdev_xnvme_create");
66 : :
67 : 6 : spdk_json_write_named_object_begin(w, "params");
68 : 6 : spdk_json_write_named_string(w, "name", xnvme->bdev.name);
69 : 6 : spdk_json_write_named_string(w, "filename", xnvme->filename);
70 : 6 : spdk_json_write_named_string(w, "io_mechanism", xnvme->io_mechanism);
71 [ - + ]: 6 : spdk_json_write_named_bool(w, "conserve_cpu", xnvme->conserve_cpu);
72 : 6 : spdk_json_write_object_end(w);
73 : :
74 : 6 : spdk_json_write_object_end(w);
75 : : }
76 : :
77 : 12 : return 0;
78 : : }
79 : :
80 : : static struct spdk_bdev_module xnvme_if = {
81 : : .name = "xnvme",
82 : : .module_init = bdev_xnvme_init,
83 : : .module_fini = bdev_xnvme_fini,
84 : : .get_ctx_size = bdev_xnvme_get_ctx_size,
85 : : .config_json = bdev_xnvme_config_json,
86 : : };
87 : :
88 : 104 : SPDK_BDEV_MODULE_REGISTER(xnvme, &xnvme_if)
89 : :
90 : : static struct spdk_io_channel *
91 : 115 : bdev_xnvme_get_io_channel(void *ctx)
92 : : {
93 : 115 : struct bdev_xnvme *xnvme = ctx;
94 : :
95 : 115 : return spdk_get_io_channel(xnvme);
96 : : }
97 : :
98 : : static bool
99 : 166704 : bdev_xnvme_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
100 : : {
101 : 166704 : struct bdev_xnvme *xnvme = ctx;
102 : :
103 [ + + + ]: 166704 : switch (io_type) {
104 : 55500 : case SPDK_BDEV_IO_TYPE_READ:
105 : : case SPDK_BDEV_IO_TYPE_WRITE:
106 : 55500 : return true;
107 : 110934 : case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
108 : : case SPDK_BDEV_IO_TYPE_UNMAP:
109 : : /* libaio and io_uring only supports read and write */
110 [ - + - + : 110934 : return !strcmp(xnvme->io_mechanism, "io_uring_cmd") &&
- - ]
111 : 0 : xnvme_dev_get_csi(xnvme->dev) == XNVME_SPEC_CSI_NVM;
112 : 270 : default:
113 : 270 : return false;
114 : : }
115 : : }
116 : :
117 : : static void
118 : 54 : bdev_xnvme_destruct_cb(void *io_device)
119 : : {
120 : 54 : struct bdev_xnvme *xnvme = io_device;
121 : :
122 [ - + ]: 54 : TAILQ_REMOVE(&g_xnvme_bdev_head, xnvme, link);
123 : 54 : bdev_xnvme_free(xnvme);
124 : 54 : }
125 : :
126 : : static int
127 : 54 : bdev_xnvme_destruct(void *ctx)
128 : : {
129 : 54 : struct bdev_xnvme *xnvme = ctx;
130 : :
131 : 54 : spdk_io_device_unregister(xnvme, bdev_xnvme_destruct_cb);
132 : :
133 : 54 : return 0;
134 : : }
135 : :
136 : : static int
137 : 0 : bdev_xnvme_unmap(struct spdk_bdev_io *bdev_io, struct xnvme_cmd_ctx *ctx, struct bdev_xnvme *xnvme)
138 : : {
139 : : struct spdk_nvme_dsm_range *range;
140 : : uint64_t offset, remaining;
141 : : uint64_t num_ranges_u64, num_blocks, offset_blocks;
142 : : uint16_t num_ranges;
143 : :
144 : 0 : num_blocks = bdev_io->u.bdev.num_blocks;
145 : 0 : offset_blocks = bdev_io->u.bdev.offset_blocks;
146 : :
147 : 0 : num_ranges_u64 = spdk_divide_round_up(num_blocks, xnvme->bdev.max_unmap);
148 [ # # ]: 0 : if (num_ranges_u64 > xnvme->bdev.max_unmap_segments) {
149 : 0 : SPDK_ERRLOG("Unmap request for %" PRIu64 " blocks is too large\n", num_blocks);
150 : 0 : return -EINVAL;
151 : : }
152 : 0 : num_ranges = (uint16_t)num_ranges_u64;
153 : :
154 : 0 : offset = offset_blocks;
155 : 0 : remaining = num_blocks;
156 : :
157 [ # # ]: 0 : assert(bdev_io->u.bdev.iovcnt == 1);
158 : 0 : range = (struct spdk_nvme_dsm_range *) bdev_io->u.bdev.iovs->iov_base;
159 : :
160 : : /* Fill max-size ranges until the remaining blocks fit into one range */
161 [ # # ]: 0 : while (remaining > xnvme->bdev.max_unmap) {
162 : 0 : range->attributes.raw = 0;
163 : 0 : range->length = xnvme->bdev.max_unmap;
164 : 0 : range->starting_lba = offset;
165 : :
166 : 0 : offset += xnvme->bdev.max_unmap;
167 : 0 : remaining -= xnvme->bdev.max_unmap;
168 : 0 : range++;
169 : : }
170 : :
171 : : /* Final range describes the remaining blocks */
172 : 0 : range->attributes.raw = 0;
173 : 0 : range->length = remaining;
174 : 0 : range->starting_lba = offset;
175 : :
176 : 0 : ctx->cmd.common.opcode = XNVME_SPEC_NVM_OPC_DATASET_MANAGEMENT;
177 : 0 : ctx->cmd.common.nsid = xnvme->nsid;
178 : 0 : ctx->cmd.nvm.nlb = num_blocks - 1;
179 : 0 : ctx->cmd.nvm.slba = offset_blocks;
180 : 0 : ctx->cmd.dsm.nr = num_ranges - 1;
181 : 0 : ctx->cmd.dsm.ad = true;
182 : :
183 : 0 : return 0;
184 : : }
185 : :
186 : : static void
187 : 3695707 : _xnvme_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
188 : : {
189 : 3695707 : struct bdev_xnvme_task *xnvme_task = (struct bdev_xnvme_task *)bdev_io->driver_ctx;
190 : 3695707 : struct bdev_xnvme *xnvme = (struct bdev_xnvme *)bdev_io->bdev->ctxt;
191 : 3695707 : struct bdev_xnvme_io_channel *xnvme_ch = spdk_io_channel_get_ctx(ch);
192 : 3695707 : struct xnvme_cmd_ctx *ctx = xnvme_queue_get_cmd_ctx(xnvme_ch->queue);
193 : : int err;
194 : :
195 [ - + - + ]: 3695707 : SPDK_DEBUGLOG(xnvme, "bdev_io : %p, iov_cnt : %d, bdev_xnvme_task : %p\n",
196 : : bdev_io, bdev_io->u.bdev.iovcnt, (struct bdev_xnvme_task *)bdev_io->driver_ctx);
197 : :
198 [ + + - - : 3695707 : switch (bdev_io->type) {
- ]
199 : 2640910 : case SPDK_BDEV_IO_TYPE_READ:
200 : 2640910 : ctx->cmd.common.opcode = XNVME_SPEC_NVM_OPC_READ;
201 : 2640910 : ctx->cmd.common.nsid = xnvme->nsid;
202 : 2640910 : ctx->cmd.nvm.nlb = bdev_io->u.bdev.num_blocks - 1;
203 : 2640910 : ctx->cmd.nvm.slba = bdev_io->u.bdev.offset_blocks;
204 : 2640910 : break;
205 : 1054797 : case SPDK_BDEV_IO_TYPE_WRITE:
206 : 1054797 : ctx->cmd.common.opcode = XNVME_SPEC_NVM_OPC_WRITE;
207 : 1054797 : ctx->cmd.common.nsid = xnvme->nsid;
208 : 1054797 : ctx->cmd.nvm.nlb = bdev_io->u.bdev.num_blocks - 1;
209 : 1054797 : ctx->cmd.nvm.slba = bdev_io->u.bdev.offset_blocks;
210 : 1054797 : break;
211 : 0 : case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
212 : 0 : ctx->cmd.common.opcode = XNVME_SPEC_NVM_OPC_WRITE_ZEROES;
213 : 0 : ctx->cmd.common.nsid = xnvme->nsid;
214 : 0 : ctx->cmd.nvm.nlb = bdev_io->u.bdev.num_blocks - 1;
215 : 0 : ctx->cmd.nvm.slba = bdev_io->u.bdev.offset_blocks;
216 : 0 : break;
217 : 0 : case SPDK_BDEV_IO_TYPE_UNMAP:
218 [ # # ]: 0 : if (bdev_xnvme_unmap(bdev_io, ctx, xnvme)) {
219 : 0 : xnvme_queue_put_cmd_ctx(xnvme_ch->queue, ctx);
220 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
221 : 0 : return;
222 : : }
223 : 0 : break;
224 : 0 : default:
225 : 0 : SPDK_ERRLOG("Wrong io type\n");
226 : :
227 : 0 : xnvme_queue_put_cmd_ctx(xnvme_ch->queue, ctx);
228 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
229 : 0 : return;
230 : : }
231 : :
232 : 3695707 : xnvme_task->ch = xnvme_ch;
233 : 3695707 : ctx->async.cb_arg = xnvme_task;
234 : :
235 : 3695707 : err = xnvme_cmd_passv(ctx, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
236 : 3695707 : bdev_io->u.bdev.num_blocks * xnvme->bdev.blocklen, NULL, 0, 0);
237 : :
238 [ + - - ]: 3695707 : switch (err) {
239 : : /* Submission success! */
240 : 3695707 : case 0:
241 [ - + - + ]: 3695707 : SPDK_DEBUGLOG(xnvme, "io_channel : %p, iovcnt:%d, nblks: %lu off: %#lx\n",
242 : : xnvme_ch, bdev_io->u.bdev.iovcnt,
243 : : bdev_io->u.bdev.num_blocks, bdev_io->u.bdev.offset_blocks);
244 : 3695707 : return;
245 : :
246 : : /* Submission failed: queue is full or no memory => Queue the I/O in bdev layer */
247 : 0 : case -EBUSY:
248 : : case -EAGAIN:
249 : : case -ENOMEM:
250 : 0 : SPDK_WARNLOG("Start to queue I/O for xnvme bdev\n");
251 : :
252 : 0 : xnvme_queue_put_cmd_ctx(xnvme_ch->queue, ctx);
253 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM);
254 : 0 : return;
255 : :
256 : : /* Submission failed: unexpected error, put the command-context back in the queue */
257 : 0 : default:
258 : 0 : SPDK_ERRLOG("bdev_xnvme_cmd_passv : Submission failed: unexpected error\n");
259 : :
260 : 0 : xnvme_queue_put_cmd_ctx(xnvme_ch->queue, ctx);
261 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
262 : 0 : return;
263 : : }
264 : : }
265 : :
266 : : static void
267 : 3695707 : bdev_xnvme_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io, bool success)
268 : : {
269 : 3695707 : struct bdev_xnvme_io_channel *xnvme_ch = spdk_io_channel_get_ctx(ch);
270 : :
271 [ - + ]: 3695707 : if (!success) {
272 : 0 : xnvme_queue_put_cmd_ctx(xnvme_ch->queue, xnvme_queue_get_cmd_ctx(xnvme_ch->queue));
273 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
274 : 0 : return;
275 : : }
276 : :
277 : 3695707 : _xnvme_submit_request(ch, bdev_io);
278 : : }
279 : :
280 : : static void
281 : 3695713 : bdev_xnvme_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
282 : : {
283 [ + - - + ]: 3695713 : switch (bdev_io->type) {
284 : : /* Read and write operations must be performed on buffers aligned to
285 : : * bdev->required_alignment. If user specified unaligned buffers,
286 : : * get the aligned buffer from the pool by calling spdk_bdev_io_get_buf. */
287 : 3695707 : case SPDK_BDEV_IO_TYPE_READ:
288 : : case SPDK_BDEV_IO_TYPE_WRITE:
289 : 3695707 : spdk_bdev_io_get_buf(bdev_io, bdev_xnvme_get_buf_cb,
290 : 3695707 : bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
291 : 3695707 : break;
292 : 0 : case SPDK_BDEV_IO_TYPE_UNMAP:
293 : : /* The max number of segments defined by spec is 256 and an
294 : : * spdk_nvme_dsm_range structure is 16 bytes */
295 : 0 : spdk_bdev_io_get_buf(bdev_io, bdev_xnvme_get_buf_cb, 256 * 16);
296 : 0 : break;
297 : 0 : case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
298 : 0 : _xnvme_submit_request(ch, bdev_io);
299 : 0 : break;
300 : :
301 : 6 : default:
302 : 6 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
303 : 6 : break;
304 : : }
305 : 3695713 : }
306 : :
307 : : static const struct spdk_bdev_fn_table xnvme_fn_table = {
308 : : .destruct = bdev_xnvme_destruct,
309 : : .submit_request = bdev_xnvme_submit_request,
310 : : .io_type_supported = bdev_xnvme_io_type_supported,
311 : : .get_io_channel = bdev_xnvme_get_io_channel,
312 : : };
313 : :
314 : : static void
315 : 54 : bdev_xnvme_free(struct bdev_xnvme *xnvme)
316 : : {
317 [ - + ]: 54 : assert(xnvme != NULL);
318 : :
319 : 54 : xnvme_dev_close(xnvme->dev);
320 : 54 : free(xnvme->io_mechanism);
321 : 54 : free(xnvme->filename);
322 : 54 : free(xnvme->bdev.name);
323 : 54 : free(xnvme);
324 : 54 : }
325 : :
326 : : static void
327 : 3695707 : bdev_xnvme_cmd_cb(struct xnvme_cmd_ctx *ctx, void *cb_arg)
328 : : {
329 : 3695707 : struct bdev_xnvme_task *xnvme_task = ctx->async.cb_arg;
330 : 3695707 : enum spdk_bdev_io_status status = SPDK_BDEV_IO_STATUS_SUCCESS;
331 : :
332 [ - + - + ]: 3695707 : SPDK_DEBUGLOG(xnvme, "xnvme_task : %p\n", xnvme_task);
333 : :
334 [ - + ]: 3695707 : if (xnvme_cmd_ctx_cpl_status(ctx)) {
335 : 0 : SPDK_ERRLOG("xNVMe I/O Failed\n");
336 : 0 : xnvme_cmd_ctx_pr(ctx, XNVME_PR_DEF);
337 : 0 : status = SPDK_BDEV_IO_STATUS_FAILED;
338 : : }
339 : :
340 : 3695707 : spdk_bdev_io_complete(spdk_bdev_io_from_ctx(xnvme_task), status);
341 : :
342 : : /* Completed: Put the command- context back in the queue */
343 : 3695707 : xnvme_queue_put_cmd_ctx(ctx->async.queue, ctx);
344 : 3695707 : }
345 : :
346 : : static int
347 : 5259375 : bdev_xnvme_poll(void *arg)
348 : : {
349 : 5259375 : struct bdev_xnvme_io_channel *ch = arg;
350 : : int rc;
351 : :
352 : 5259375 : rc = xnvme_queue_poke(ch->queue, 0);
353 [ - + ]: 5259375 : if (rc < 0) {
354 : 0 : SPDK_ERRLOG("xnvme_queue_poke failure rc : %d\n", rc);
355 : 0 : return SPDK_POLLER_BUSY;
356 : : }
357 : :
358 : 5259375 : return xnvme_queue_get_outstanding(ch->queue) ? SPDK_POLLER_BUSY : SPDK_POLLER_IDLE;
359 : : }
360 : :
361 : : static int
362 : 115 : bdev_xnvme_queue_create_cb(void *io_device, void *ctx_buf)
363 : : {
364 : 115 : struct bdev_xnvme *xnvme = io_device;
365 : 115 : struct bdev_xnvme_io_channel *ch = ctx_buf;
366 : : int rc;
367 : 115 : int qd = 512;
368 : :
369 : 115 : rc = xnvme_queue_init(xnvme->dev, qd, 0, &ch->queue);
370 [ - + ]: 115 : if (rc) {
371 : 0 : SPDK_ERRLOG("xnvme_queue_init failure: %d\n", rc);
372 : 0 : return 1;
373 : : }
374 : :
375 : 115 : xnvme_queue_set_cb(ch->queue, bdev_xnvme_cmd_cb, ch);
376 : :
377 : 115 : ch->poller = SPDK_POLLER_REGISTER(bdev_xnvme_poll, ch, 0);
378 : :
379 : 115 : return 0;
380 : : }
381 : :
382 : : static void
383 : 115 : bdev_xnvme_queue_destroy_cb(void *io_device, void *ctx_buf)
384 : : {
385 : 115 : struct bdev_xnvme_io_channel *ch = ctx_buf;
386 : :
387 : 115 : spdk_poller_unregister(&ch->poller);
388 : :
389 : 115 : xnvme_queue_term(ch->queue);
390 : 115 : }
391 : :
392 : : struct spdk_bdev *
393 : 54 : create_xnvme_bdev(const char *name, const char *filename, const char *io_mechanism,
394 : : bool conserve_cpu)
395 : : {
396 : : struct bdev_xnvme *xnvme;
397 : : const struct xnvme_spec_nvm_idfy_ctrlr *ctrlr;
398 : : uint32_t block_size;
399 : : uint64_t bdev_size;
400 : : int rc;
401 : 54 : struct xnvme_opts opts = xnvme_opts_default();
402 : :
403 : 54 : xnvme = calloc(1, sizeof(*xnvme));
404 [ - + ]: 54 : if (!xnvme) {
405 : 0 : SPDK_ERRLOG("Unable to allocate enough memory for xNVMe backend\n");
406 : 0 : return NULL;
407 : : }
408 : :
409 : 54 : opts.direct = 1;
410 : 54 : opts.async = io_mechanism;
411 [ - + ]: 54 : if (!opts.async) {
412 : 0 : goto error_return;
413 : : }
414 [ - + ]: 54 : xnvme->io_mechanism = strdup(io_mechanism);
415 [ - + ]: 54 : if (!xnvme->io_mechanism) {
416 : 0 : goto error_return;
417 : : }
418 : :
419 [ + - ]: 54 : if (!conserve_cpu) {
420 [ - + + + ]: 54 : if (!strcmp(xnvme->io_mechanism, "libaio")) {
421 : 3 : opts.poll_io = 1;
422 [ - + + - ]: 51 : } else if (!strcmp(xnvme->io_mechanism, "io_uring")) {
423 : 51 : opts.poll_io = 1;
424 [ # # # # ]: 0 : } else if (!strcmp(xnvme->io_mechanism, "io_uring_cmd")) {
425 : 0 : opts.poll_io = 1;
426 : : }
427 : : }
428 : :
429 [ - + ]: 54 : xnvme->filename = strdup(filename);
430 [ - + ]: 54 : if (!xnvme->filename) {
431 : 0 : goto error_return;
432 : : }
433 : :
434 : 54 : xnvme->dev = xnvme_dev_open(xnvme->filename, &opts);
435 [ - + ]: 54 : if (!xnvme->dev) {
436 : 0 : SPDK_ERRLOG("Unable to open xNVMe device %s\n", filename);
437 : 0 : goto error_return;
438 : : }
439 : :
440 : 54 : xnvme->nsid = xnvme_dev_get_nsid(xnvme->dev);
441 : :
442 : 54 : bdev_size = xnvme_dev_get_geo(xnvme->dev)->tbytes;
443 : 54 : block_size = xnvme_dev_get_geo(xnvme->dev)->nbytes;
444 : :
445 [ - + ]: 54 : xnvme->bdev.name = strdup(name);
446 [ - + ]: 54 : if (!xnvme->bdev.name) {
447 : 0 : goto error_return;
448 : : }
449 : :
450 : 54 : xnvme->bdev.product_name = "xNVMe bdev";
451 : 54 : xnvme->bdev.module = &xnvme_if;
452 : :
453 : 54 : xnvme->bdev.write_cache = 0;
454 : 54 : xnvme->bdev.max_write_zeroes = UINT16_MAX + 1;
455 : :
456 [ + + ]: 54 : if (xnvme_dev_get_csi(xnvme->dev) == XNVME_SPEC_CSI_NVM) {
457 : 48 : ctrlr = (struct xnvme_spec_nvm_idfy_ctrlr *) xnvme_dev_get_ctrlr_css(xnvme->dev);
458 [ + - ]: 48 : xnvme->bdev.max_unmap = ctrlr->dmrsl ? ctrlr->dmrsl : SPDK_NVME_DATASET_MANAGEMENT_RANGE_MAX_BLOCKS;
459 [ - + ]: 48 : xnvme->bdev.max_unmap_segments = ctrlr->dmrl ? ctrlr->dmrl :
460 : : SPDK_NVME_DATASET_MANAGEMENT_MAX_RANGES;
461 : : }
462 : :
463 [ - + ]: 54 : if (block_size == 0) {
464 : 0 : SPDK_ERRLOG("Block size could not be auto-detected\n");
465 : 0 : goto error_return;
466 : : }
467 : :
468 [ - + ]: 54 : if (block_size < 512) {
469 : 0 : SPDK_ERRLOG("Invalid block size %" PRIu32 " (must be at least 512).\n", block_size);
470 : 0 : goto error_return;
471 : : }
472 : :
473 [ - + ]: 54 : if (!spdk_u32_is_pow2(block_size)) {
474 : 0 : SPDK_ERRLOG("Invalid block size %" PRIu32 " (must be a power of 2.)\n", block_size);
475 : 0 : goto error_return;
476 : : }
477 : :
478 [ - + - + ]: 54 : SPDK_DEBUGLOG(xnvme, "bdev_name : %s, bdev_size : %lu, block_size : %d\n",
479 : : xnvme->bdev.name, bdev_size, block_size);
480 : :
481 : 54 : xnvme->bdev.blocklen = block_size;
482 : 54 : xnvme->bdev.required_alignment = spdk_u32log2(block_size);
483 : :
484 [ - + - + ]: 54 : if (bdev_size % xnvme->bdev.blocklen != 0) {
485 : 0 : SPDK_ERRLOG("Disk size %" PRIu64 " is not a multiple of block size %" PRIu32 "\n",
486 : : bdev_size, xnvme->bdev.blocklen);
487 : 0 : goto error_return;
488 : : }
489 : :
490 [ - + ]: 54 : xnvme->bdev.blockcnt = bdev_size / xnvme->bdev.blocklen;
491 : 54 : xnvme->bdev.ctxt = xnvme;
492 : :
493 : 54 : xnvme->bdev.fn_table = &xnvme_fn_table;
494 : :
495 : 54 : spdk_io_device_register(xnvme, bdev_xnvme_queue_create_cb, bdev_xnvme_queue_destroy_cb,
496 : : sizeof(struct bdev_xnvme_io_channel),
497 : 54 : xnvme->bdev.name);
498 : 54 : rc = spdk_bdev_register(&xnvme->bdev);
499 [ - + ]: 54 : if (rc) {
500 : 0 : spdk_io_device_unregister(xnvme, NULL);
501 : 0 : goto error_return;
502 : : }
503 : :
504 : 54 : TAILQ_INSERT_TAIL(&g_xnvme_bdev_head, xnvme, link);
505 : :
506 : 54 : return &xnvme->bdev;
507 : :
508 : 0 : error_return:
509 : 0 : bdev_xnvme_free(xnvme);
510 : 0 : return NULL;
511 : : }
512 : :
513 : : void
514 : 0 : delete_xnvme_bdev(const char *name, spdk_bdev_unregister_cb cb_fn, void *cb_arg)
515 : : {
516 : : int rc;
517 : :
518 : 0 : rc = spdk_bdev_unregister_by_name(name, &xnvme_if, cb_fn, cb_arg);
519 [ # # ]: 0 : if (rc != 0) {
520 : 0 : cb_fn(cb_arg, rc);
521 : : }
522 : 0 : }
523 : :
524 : : static int
525 : 0 : bdev_xnvme_module_create_cb(void *io_device, void *ctx_buf)
526 : : {
527 : 0 : return 0;
528 : : }
529 : :
530 : : static void
531 : 0 : bdev_xnvme_module_destroy_cb(void *io_device, void *ctx_buf)
532 : : {
533 : 0 : }
534 : :
535 : : static int
536 : 94 : bdev_xnvme_init(void)
537 : : {
538 : 94 : spdk_io_device_register(&xnvme_if, bdev_xnvme_module_create_cb, bdev_xnvme_module_destroy_cb,
539 : : 0, "xnvme_module");
540 : :
541 : 94 : return 0;
542 : : }
543 : :
544 : : static void
545 : 94 : bdev_xnvme_fini(void)
546 : : {
547 : 94 : spdk_io_device_unregister(&xnvme_if, NULL);
548 : 94 : }
549 : :
550 : 104 : SPDK_LOG_REGISTER_COMPONENT(xnvme)
|