]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/lib/bdev/passthru/vbdev_passthru.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / lib / bdev / passthru / vbdev_passthru.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * This is a simple example of a virtual block device module that passes IO
36 * down to a bdev (or bdevs) that its configured to attach to.
37 */
38
39 #include "spdk/stdinc.h"
40
41 #include "vbdev_passthru.h"
42 #include "spdk/rpc.h"
43 #include "spdk/env.h"
44 #include "spdk/conf.h"
45 #include "spdk/endian.h"
46 #include "spdk/string.h"
47 #include "spdk/thread.h"
48 #include "spdk/util.h"
49
50 #include "spdk/bdev_module.h"
51 #include "spdk_internal/log.h"
52
53
54 static int vbdev_passthru_init(void);
55 static void vbdev_passthru_get_spdk_running_config(FILE *fp);
56 static int vbdev_passthru_get_ctx_size(void);
57 static void vbdev_passthru_examine(struct spdk_bdev *bdev);
58 static void vbdev_passthru_finish(void);
59 static int vbdev_passthru_config_json(struct spdk_json_write_ctx *w);
60
61 static struct spdk_bdev_module passthru_if = {
62 .name = "passthru",
63 .module_init = vbdev_passthru_init,
64 .config_text = vbdev_passthru_get_spdk_running_config,
65 .get_ctx_size = vbdev_passthru_get_ctx_size,
66 .examine_config = vbdev_passthru_examine,
67 .module_fini = vbdev_passthru_finish,
68 .config_json = vbdev_passthru_config_json
69 };
70
71 SPDK_BDEV_MODULE_REGISTER(passthru, &passthru_if)
72
73 /* List of pt_bdev names and their base bdevs via configuration file.
74 * Used so we can parse the conf once at init and use this list in examine().
75 */
76 struct bdev_names {
77 char *vbdev_name;
78 char *bdev_name;
79 TAILQ_ENTRY(bdev_names) link;
80 };
81 static TAILQ_HEAD(, bdev_names) g_bdev_names = TAILQ_HEAD_INITIALIZER(g_bdev_names);
82
83 /* List of virtual bdevs and associated info for each. */
84 struct vbdev_passthru {
85 struct spdk_bdev *base_bdev; /* the thing we're attaching to */
86 struct spdk_bdev_desc *base_desc; /* its descriptor we get from open */
87 struct spdk_bdev pt_bdev; /* the PT virtual bdev */
88 TAILQ_ENTRY(vbdev_passthru) link;
89 };
90 static TAILQ_HEAD(, vbdev_passthru) g_pt_nodes = TAILQ_HEAD_INITIALIZER(g_pt_nodes);
91
92 /* The pt vbdev channel struct. It is allocated and freed on my behalf by the io channel code.
93 * If this vbdev needed to implement a poller or a queue for IO, this is where those things
94 * would be defined. This passthru bdev doesn't actually need to allocate a channel, it could
95 * simply pass back the channel of the bdev underneath it but for example purposes we will
96 * present its own to the upper layers.
97 */
98 struct pt_io_channel {
99 struct spdk_io_channel *base_ch; /* IO channel of base device */
100 };
101
102 /* Just for fun, this pt_bdev module doesn't need it but this is essentially a per IO
103 * context that we get handed by the bdev layer.
104 */
105 struct passthru_bdev_io {
106 uint8_t test;
107
108 /* bdev related */
109 struct spdk_io_channel *ch;
110
111 /* for bdev_io_wait */
112 struct spdk_bdev_io_wait_entry bdev_io_wait;
113 };
114
115 static void
116 vbdev_passthru_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io);
117
118
119 /* Callback for unregistering the IO device. */
120 static void
121 _device_unregister_cb(void *io_device)
122 {
123 struct vbdev_passthru *pt_node = io_device;
124
125 /* Done with this pt_node. */
126 free(pt_node->pt_bdev.name);
127 free(pt_node);
128 }
129
130 /* Called after we've unregistered following a hot remove callback.
131 * Our finish entry point will be called next.
132 */
133 static int
134 vbdev_passthru_destruct(void *ctx)
135 {
136 struct vbdev_passthru *pt_node = (struct vbdev_passthru *)ctx;
137
138 /* It is important to follow this exact sequence of steps for destroying
139 * a vbdev...
140 */
141
142 TAILQ_REMOVE(&g_pt_nodes, pt_node, link);
143
144 /* Unclaim the underlying bdev. */
145 spdk_bdev_module_release_bdev(pt_node->base_bdev);
146
147 /* Close the underlying bdev. */
148 spdk_bdev_close(pt_node->base_desc);
149
150 /* Unregister the io_device. */
151 spdk_io_device_unregister(pt_node, _device_unregister_cb);
152
153 return 0;
154 }
155
156 /* Completion callback for IO that were issued from this bdev. The original bdev_io
157 * is passed in as an arg so we'll complete that one with the appropriate status
158 * and then free the one that this module issued.
159 */
160 static void
161 _pt_complete_io(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
162 {
163 struct spdk_bdev_io *orig_io = cb_arg;
164 int status = success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED;
165 struct passthru_bdev_io *io_ctx = (struct passthru_bdev_io *)orig_io->driver_ctx;
166
167 /* We setup this value in the submission routine, just showing here that it is
168 * passed back to us.
169 */
170 if (io_ctx->test != 0x5a) {
171 SPDK_ERRLOG("Error, original IO device_ctx is wrong! 0x%x\n",
172 io_ctx->test);
173 }
174
175 /* Complete the original IO and then free the one that we created here
176 * as a result of issuing an IO via submit_reqeust.
177 */
178 spdk_bdev_io_complete(orig_io, status);
179 spdk_bdev_free_io(bdev_io);
180 }
181
182 static void
183 vbdev_passthru_resubmit_io(void *arg)
184 {
185 struct spdk_bdev_io *bdev_io = (struct spdk_bdev_io *)arg;
186 struct passthru_bdev_io *io_ctx = (struct passthru_bdev_io *)bdev_io->driver_ctx;
187
188 vbdev_passthru_submit_request(io_ctx->ch, bdev_io);
189 }
190
191 static void
192 vbdev_passthru_queue_io(struct spdk_bdev_io *bdev_io)
193 {
194 struct passthru_bdev_io *io_ctx = (struct passthru_bdev_io *)bdev_io->driver_ctx;
195 int rc;
196
197 io_ctx->bdev_io_wait.bdev = bdev_io->bdev;
198 io_ctx->bdev_io_wait.cb_fn = vbdev_passthru_resubmit_io;
199 io_ctx->bdev_io_wait.cb_arg = bdev_io;
200
201 rc = spdk_bdev_queue_io_wait(bdev_io->bdev, io_ctx->ch, &io_ctx->bdev_io_wait);
202 if (rc != 0) {
203 SPDK_ERRLOG("Queue io failed in vbdev_passthru_queue_io, rc=%d.\n", rc);
204 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
205 }
206 }
207
208 /* Callback for getting a buf from the bdev pool in the event that the caller passed
209 * in NULL, we need to own the buffer so it doesn't get freed by another vbdev module
210 * beneath us before we're done with it. That won't happen in this example but it could
211 * if this example were used as a template for something more complex.
212 */
213 static void
214 pt_read_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io, bool success)
215 {
216 struct vbdev_passthru *pt_node = SPDK_CONTAINEROF(bdev_io->bdev, struct vbdev_passthru,
217 pt_bdev);
218 struct pt_io_channel *pt_ch = spdk_io_channel_get_ctx(ch);
219 struct passthru_bdev_io *io_ctx = (struct passthru_bdev_io *)bdev_io->driver_ctx;
220 int rc;
221
222 if (!success) {
223 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
224 return;
225 }
226
227 rc = spdk_bdev_readv_blocks(pt_node->base_desc, pt_ch->base_ch, bdev_io->u.bdev.iovs,
228 bdev_io->u.bdev.iovcnt, bdev_io->u.bdev.offset_blocks,
229 bdev_io->u.bdev.num_blocks, _pt_complete_io,
230 bdev_io);
231 if (rc != 0) {
232 if (rc == -ENOMEM) {
233 SPDK_ERRLOG("No memory, start to queue io for passthru.\n");
234 io_ctx->ch = ch;
235 vbdev_passthru_queue_io(bdev_io);
236 } else {
237 SPDK_ERRLOG("ERROR on bdev_io submission!\n");
238 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
239 }
240 }
241 }
242
243 /* Called when someone above submits IO to this pt vbdev. We're simply passing it on here
244 * via SPDK IO calls which in turn allocate another bdev IO and call our cpl callback provided
245 * below along with the original bdiv_io so that we can complete it once this IO completes.
246 */
247 static void
248 vbdev_passthru_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
249 {
250 struct vbdev_passthru *pt_node = SPDK_CONTAINEROF(bdev_io->bdev, struct vbdev_passthru, pt_bdev);
251 struct pt_io_channel *pt_ch = spdk_io_channel_get_ctx(ch);
252 struct passthru_bdev_io *io_ctx = (struct passthru_bdev_io *)bdev_io->driver_ctx;
253 int rc = 0;
254
255 /* Setup a per IO context value; we don't do anything with it in the vbdev other
256 * than confirm we get the same thing back in the completion callback just to
257 * demonstrate.
258 */
259 io_ctx->test = 0x5a;
260
261 switch (bdev_io->type) {
262 case SPDK_BDEV_IO_TYPE_READ:
263 spdk_bdev_io_get_buf(bdev_io, pt_read_get_buf_cb,
264 bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
265 break;
266 case SPDK_BDEV_IO_TYPE_WRITE:
267 rc = spdk_bdev_writev_blocks(pt_node->base_desc, pt_ch->base_ch, bdev_io->u.bdev.iovs,
268 bdev_io->u.bdev.iovcnt, bdev_io->u.bdev.offset_blocks,
269 bdev_io->u.bdev.num_blocks, _pt_complete_io,
270 bdev_io);
271 break;
272 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
273 rc = spdk_bdev_write_zeroes_blocks(pt_node->base_desc, pt_ch->base_ch,
274 bdev_io->u.bdev.offset_blocks,
275 bdev_io->u.bdev.num_blocks,
276 _pt_complete_io, bdev_io);
277 break;
278 case SPDK_BDEV_IO_TYPE_UNMAP:
279 rc = spdk_bdev_unmap_blocks(pt_node->base_desc, pt_ch->base_ch,
280 bdev_io->u.bdev.offset_blocks,
281 bdev_io->u.bdev.num_blocks,
282 _pt_complete_io, bdev_io);
283 break;
284 case SPDK_BDEV_IO_TYPE_FLUSH:
285 rc = spdk_bdev_flush_blocks(pt_node->base_desc, pt_ch->base_ch,
286 bdev_io->u.bdev.offset_blocks,
287 bdev_io->u.bdev.num_blocks,
288 _pt_complete_io, bdev_io);
289 break;
290 case SPDK_BDEV_IO_TYPE_RESET:
291 rc = spdk_bdev_reset(pt_node->base_desc, pt_ch->base_ch,
292 _pt_complete_io, bdev_io);
293 break;
294 default:
295 SPDK_ERRLOG("passthru: unknown I/O type %d\n", bdev_io->type);
296 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
297 return;
298 }
299 if (rc != 0) {
300 if (rc == -ENOMEM) {
301 SPDK_ERRLOG("No memory, start to queue io for passthru.\n");
302 io_ctx->ch = ch;
303 vbdev_passthru_queue_io(bdev_io);
304 } else {
305 SPDK_ERRLOG("ERROR on bdev_io submission!\n");
306 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
307 }
308 }
309 }
310
311 /* We'll just call the base bdev and let it answer however if we were more
312 * restrictive for some reason (or less) we could get the response back
313 * and modify according to our purposes.
314 */
315 static bool
316 vbdev_passthru_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
317 {
318 struct vbdev_passthru *pt_node = (struct vbdev_passthru *)ctx;
319
320 return spdk_bdev_io_type_supported(pt_node->base_bdev, io_type);
321 }
322
323 /* We supplied this as an entry point for upper layers who want to communicate to this
324 * bdev. This is how they get a channel. We are passed the same context we provided when
325 * we created our PT vbdev in examine() which, for this bdev, is the address of one of
326 * our context nodes. From here we'll ask the SPDK channel code to fill out our channel
327 * struct and we'll keep it in our PT node.
328 */
329 static struct spdk_io_channel *
330 vbdev_passthru_get_io_channel(void *ctx)
331 {
332 struct vbdev_passthru *pt_node = (struct vbdev_passthru *)ctx;
333 struct spdk_io_channel *pt_ch = NULL;
334
335 /* The IO channel code will allocate a channel for us which consists of
336 * the SPDK channel structure plus the size of our pt_io_channel struct
337 * that we passed in when we registered our IO device. It will then call
338 * our channel create callback to populate any elements that we need to
339 * update.
340 */
341 pt_ch = spdk_get_io_channel(pt_node);
342
343 return pt_ch;
344 }
345
346 /* This is the output for get_bdevs() for this vbdev */
347 static int
348 vbdev_passthru_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
349 {
350 struct vbdev_passthru *pt_node = (struct vbdev_passthru *)ctx;
351
352 spdk_json_write_name(w, "passthru");
353 spdk_json_write_object_begin(w);
354 spdk_json_write_named_string(w, "name", spdk_bdev_get_name(&pt_node->pt_bdev));
355 spdk_json_write_named_string(w, "base_bdev_name", spdk_bdev_get_name(pt_node->base_bdev));
356 spdk_json_write_object_end(w);
357
358 return 0;
359 }
360
361 /* This is used to generate JSON that can configure this module to its current state. */
362 static int
363 vbdev_passthru_config_json(struct spdk_json_write_ctx *w)
364 {
365 struct vbdev_passthru *pt_node;
366
367 TAILQ_FOREACH(pt_node, &g_pt_nodes, link) {
368 spdk_json_write_object_begin(w);
369 spdk_json_write_named_string(w, "method", "construct_passthru_bdev");
370 spdk_json_write_named_object_begin(w, "params");
371 spdk_json_write_named_string(w, "base_bdev_name", spdk_bdev_get_name(pt_node->base_bdev));
372 spdk_json_write_named_string(w, "name", spdk_bdev_get_name(&pt_node->pt_bdev));
373 spdk_json_write_object_end(w);
374 spdk_json_write_object_end(w);
375 }
376 return 0;
377 }
378
379 /* We provide this callback for the SPDK channel code to create a channel using
380 * the channel struct we provided in our module get_io_channel() entry point. Here
381 * we get and save off an underlying base channel of the device below us so that
382 * we can communicate with the base bdev on a per channel basis. If we needed
383 * our own poller for this vbdev, we'd register it here.
384 */
385 static int
386 pt_bdev_ch_create_cb(void *io_device, void *ctx_buf)
387 {
388 struct pt_io_channel *pt_ch = ctx_buf;
389 struct vbdev_passthru *pt_node = io_device;
390
391 pt_ch->base_ch = spdk_bdev_get_io_channel(pt_node->base_desc);
392
393 return 0;
394 }
395
396 /* We provide this callback for the SPDK channel code to destroy a channel
397 * created with our create callback. We just need to undo anything we did
398 * when we created. If this bdev used its own poller, we'd unregsiter it here.
399 */
400 static void
401 pt_bdev_ch_destroy_cb(void *io_device, void *ctx_buf)
402 {
403 struct pt_io_channel *pt_ch = ctx_buf;
404
405 spdk_put_io_channel(pt_ch->base_ch);
406 }
407
408 /* Create the passthru association from the bdev and vbdev name and insert
409 * on the global list. */
410 static int
411 vbdev_passthru_insert_name(const char *bdev_name, const char *vbdev_name)
412 {
413 struct bdev_names *name;
414
415 TAILQ_FOREACH(name, &g_bdev_names, link) {
416 if (strcmp(vbdev_name, name->vbdev_name) == 0) {
417 SPDK_ERRLOG("passthru bdev %s already exists\n", vbdev_name);
418 return -EEXIST;
419 }
420 }
421
422 name = calloc(1, sizeof(struct bdev_names));
423 if (!name) {
424 SPDK_ERRLOG("could not allocate bdev_names\n");
425 return -ENOMEM;
426 }
427
428 name->bdev_name = strdup(bdev_name);
429 if (!name->bdev_name) {
430 SPDK_ERRLOG("could not allocate name->bdev_name\n");
431 free(name);
432 return -ENOMEM;
433 }
434
435 name->vbdev_name = strdup(vbdev_name);
436 if (!name->vbdev_name) {
437 SPDK_ERRLOG("could not allocate name->vbdev_name\n");
438 free(name->bdev_name);
439 free(name);
440 return -ENOMEM;
441 }
442
443 TAILQ_INSERT_TAIL(&g_bdev_names, name, link);
444
445 return 0;
446 }
447
448 /* On init, just parse config file and build list of pt vbdevs and bdev name pairs. */
449 static int
450 vbdev_passthru_init(void)
451 {
452 struct spdk_conf_section *sp = NULL;
453 const char *conf_bdev_name = NULL;
454 const char *conf_vbdev_name = NULL;
455 struct bdev_names *name;
456 int i, rc;
457
458 sp = spdk_conf_find_section(NULL, "Passthru");
459 if (sp == NULL) {
460 return 0;
461 }
462
463 for (i = 0; ; i++) {
464 if (!spdk_conf_section_get_nval(sp, "PT", i)) {
465 break;
466 }
467
468 conf_bdev_name = spdk_conf_section_get_nmval(sp, "PT", i, 0);
469 if (!conf_bdev_name) {
470 SPDK_ERRLOG("Passthru configuration missing bdev name\n");
471 break;
472 }
473
474 conf_vbdev_name = spdk_conf_section_get_nmval(sp, "PT", i, 1);
475 if (!conf_vbdev_name) {
476 SPDK_ERRLOG("Passthru configuration missing pt_bdev name\n");
477 break;
478 }
479
480 rc = vbdev_passthru_insert_name(conf_bdev_name, conf_vbdev_name);
481 if (rc != 0) {
482 return rc;
483 }
484 }
485 TAILQ_FOREACH(name, &g_bdev_names, link) {
486 SPDK_NOTICELOG("conf parse matched: %s\n", name->bdev_name);
487 }
488 return 0;
489 }
490
491 /* Called when the entire module is being torn down. */
492 static void
493 vbdev_passthru_finish(void)
494 {
495 struct bdev_names *name;
496
497 while ((name = TAILQ_FIRST(&g_bdev_names))) {
498 TAILQ_REMOVE(&g_bdev_names, name, link);
499 free(name->bdev_name);
500 free(name->vbdev_name);
501 free(name);
502 }
503 }
504
505 /* During init we'll be asked how much memory we'd like passed to us
506 * in bev_io structures as context. Here's where we specify how
507 * much context we want per IO.
508 */
509 static int
510 vbdev_passthru_get_ctx_size(void)
511 {
512 return sizeof(struct passthru_bdev_io);
513 }
514
515 /* Called when SPDK wants to save the current config of this vbdev module to
516 * a file.
517 */
518 static void
519 vbdev_passthru_get_spdk_running_config(FILE *fp)
520 {
521 struct bdev_names *names = NULL;
522
523 fprintf(fp, "\n[Passthru]\n");
524 TAILQ_FOREACH(names, &g_bdev_names, link) {
525 fprintf(fp, " PT %s %s\n", names->bdev_name, names->vbdev_name);
526 }
527 fprintf(fp, "\n");
528 }
529
530 /* Where vbdev_passthru_config_json() is used to generate per module JSON config data, this
531 * function is called to output any per bdev specific methods. For the PT module, there are
532 * none.
533 */
534 static void
535 vbdev_passthru_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w)
536 {
537 /* No config per bdev needed */
538 }
539
540 /* When we register our bdev this is how we specify our entry points. */
541 static const struct spdk_bdev_fn_table vbdev_passthru_fn_table = {
542 .destruct = vbdev_passthru_destruct,
543 .submit_request = vbdev_passthru_submit_request,
544 .io_type_supported = vbdev_passthru_io_type_supported,
545 .get_io_channel = vbdev_passthru_get_io_channel,
546 .dump_info_json = vbdev_passthru_dump_info_json,
547 .write_config_json = vbdev_passthru_write_config_json,
548 };
549
550 /* Called when the underlying base bdev goes away. */
551 static void
552 vbdev_passthru_base_bdev_hotremove_cb(void *ctx)
553 {
554 struct vbdev_passthru *pt_node, *tmp;
555 struct spdk_bdev *bdev_find = ctx;
556
557 TAILQ_FOREACH_SAFE(pt_node, &g_pt_nodes, link, tmp) {
558 if (bdev_find == pt_node->base_bdev) {
559 spdk_bdev_unregister(&pt_node->pt_bdev, NULL, NULL);
560 }
561 }
562 }
563
564 /* Create and register the passthru vbdev if we find it in our list of bdev names.
565 * This can be called either by the examine path or RPC method.
566 */
567 static int
568 vbdev_passthru_register(struct spdk_bdev *bdev)
569 {
570 struct bdev_names *name;
571 struct vbdev_passthru *pt_node;
572 int rc = 0;
573
574 /* Check our list of names from config versus this bdev and if
575 * there's a match, create the pt_node & bdev accordingly.
576 */
577 TAILQ_FOREACH(name, &g_bdev_names, link) {
578 if (strcmp(name->bdev_name, bdev->name) != 0) {
579 continue;
580 }
581
582 SPDK_NOTICELOG("Match on %s\n", bdev->name);
583 pt_node = calloc(1, sizeof(struct vbdev_passthru));
584 if (!pt_node) {
585 rc = -ENOMEM;
586 SPDK_ERRLOG("could not allocate pt_node\n");
587 break;
588 }
589
590 /* The base bdev that we're attaching to. */
591 pt_node->base_bdev = bdev;
592 pt_node->pt_bdev.name = strdup(name->vbdev_name);
593 if (!pt_node->pt_bdev.name) {
594 rc = -ENOMEM;
595 SPDK_ERRLOG("could not allocate pt_bdev name\n");
596 free(pt_node);
597 break;
598 }
599 pt_node->pt_bdev.product_name = "passthru";
600
601 /* Copy some properties from the underlying base bdev. */
602 pt_node->pt_bdev.write_cache = bdev->write_cache;
603 pt_node->pt_bdev.required_alignment = bdev->required_alignment;
604 pt_node->pt_bdev.optimal_io_boundary = bdev->optimal_io_boundary;
605 pt_node->pt_bdev.blocklen = bdev->blocklen;
606 pt_node->pt_bdev.blockcnt = bdev->blockcnt;
607
608 /* This is the context that is passed to us when the bdev
609 * layer calls in so we'll save our pt_bdev node here.
610 */
611 pt_node->pt_bdev.ctxt = pt_node;
612 pt_node->pt_bdev.fn_table = &vbdev_passthru_fn_table;
613 pt_node->pt_bdev.module = &passthru_if;
614 TAILQ_INSERT_TAIL(&g_pt_nodes, pt_node, link);
615
616 spdk_io_device_register(pt_node, pt_bdev_ch_create_cb, pt_bdev_ch_destroy_cb,
617 sizeof(struct pt_io_channel),
618 name->vbdev_name);
619 SPDK_NOTICELOG("io_device created at: 0x%p\n", pt_node);
620
621 rc = spdk_bdev_open(bdev, true, vbdev_passthru_base_bdev_hotremove_cb,
622 bdev, &pt_node->base_desc);
623 if (rc) {
624 SPDK_ERRLOG("could not open bdev %s\n", spdk_bdev_get_name(bdev));
625 TAILQ_REMOVE(&g_pt_nodes, pt_node, link);
626 spdk_io_device_unregister(pt_node, NULL);
627 free(pt_node->pt_bdev.name);
628 free(pt_node);
629 break;
630 }
631 SPDK_NOTICELOG("bdev opened\n");
632
633 rc = spdk_bdev_module_claim_bdev(bdev, pt_node->base_desc, pt_node->pt_bdev.module);
634 if (rc) {
635 SPDK_ERRLOG("could not claim bdev %s\n", spdk_bdev_get_name(bdev));
636 spdk_bdev_close(pt_node->base_desc);
637 TAILQ_REMOVE(&g_pt_nodes, pt_node, link);
638 spdk_io_device_unregister(pt_node, NULL);
639 free(pt_node->pt_bdev.name);
640 free(pt_node);
641 break;
642 }
643 SPDK_NOTICELOG("bdev claimed\n");
644
645 rc = spdk_bdev_register(&pt_node->pt_bdev);
646 if (rc) {
647 SPDK_ERRLOG("could not register pt_bdev\n");
648 spdk_bdev_module_release_bdev(&pt_node->pt_bdev);
649 spdk_bdev_close(pt_node->base_desc);
650 TAILQ_REMOVE(&g_pt_nodes, pt_node, link);
651 spdk_io_device_unregister(pt_node, NULL);
652 free(pt_node->pt_bdev.name);
653 free(pt_node);
654 break;
655 }
656 SPDK_NOTICELOG("pt_bdev registered\n");
657 SPDK_NOTICELOG("created pt_bdev for: %s\n", name->vbdev_name);
658 }
659
660 return rc;
661 }
662
663 /* Create the passthru disk from the given bdev and vbdev name. */
664 int
665 create_passthru_disk(const char *bdev_name, const char *vbdev_name)
666 {
667 struct spdk_bdev *bdev = NULL;
668 int rc = 0;
669
670 /* Insert the bdev into our global name list even if it doesn't exist yet,
671 * it may show up soon...
672 */
673 rc = vbdev_passthru_insert_name(bdev_name, vbdev_name);
674 if (rc) {
675 return rc;
676 }
677
678 bdev = spdk_bdev_get_by_name(bdev_name);
679 if (!bdev) {
680 /* This is not an error, we tracked the name above and it still
681 * may show up later.
682 */
683 SPDK_NOTICELOG("vbdev creation deferred pending base bdev arrival\n");
684 return 0;
685 }
686
687 return vbdev_passthru_register(bdev);
688 }
689
690 void
691 delete_passthru_disk(struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn, void *cb_arg)
692 {
693 struct bdev_names *name;
694
695 if (!bdev || bdev->module != &passthru_if) {
696 cb_fn(cb_arg, -ENODEV);
697 return;
698 }
699
700 /* Remove the association (vbdev, bdev) from g_bdev_names. This is required so that the
701 * vbdev does not get re-created if the same bdev is constructed at some other time,
702 * unless the underlying bdev was hot-removed.
703 */
704 TAILQ_FOREACH(name, &g_bdev_names, link) {
705 if (strcmp(name->vbdev_name, bdev->name) == 0) {
706 TAILQ_REMOVE(&g_bdev_names, name, link);
707 free(name->bdev_name);
708 free(name->vbdev_name);
709 free(name);
710 break;
711 }
712 }
713
714 /* Additional cleanup happens in the destruct callback. */
715 spdk_bdev_unregister(bdev, cb_fn, cb_arg);
716 }
717
718 /* Because we specified this function in our pt bdev function table when we
719 * registered our pt bdev, we'll get this call anytime a new bdev shows up.
720 * Here we need to decide if we care about it and if so what to do. We
721 * parsed the config file at init so we check the new bdev against the list
722 * we built up at that time and if the user configured us to attach to this
723 * bdev, here's where we do it.
724 */
725 static void
726 vbdev_passthru_examine(struct spdk_bdev *bdev)
727 {
728 vbdev_passthru_register(bdev);
729
730 spdk_bdev_module_examine_done(&passthru_if);
731 }
732
733 SPDK_LOG_REGISTER_COMPONENT("vbdev_passthru", SPDK_LOG_VBDEV_PASSTHRU)