4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
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.
39 #include "spdk/stdinc.h"
41 #include "vbdev_passthru.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"
50 #include "spdk/bdev_module.h"
51 #include "spdk_internal/log.h"
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);
60 static struct spdk_bdev_module passthru_if
= {
62 .module_init
= vbdev_passthru_init
,
63 .config_text
= vbdev_passthru_get_spdk_running_config
,
64 .get_ctx_size
= vbdev_passthru_get_ctx_size
,
65 .examine_config
= vbdev_passthru_examine
,
66 .module_fini
= vbdev_passthru_finish
69 SPDK_BDEV_MODULE_REGISTER(&passthru_if
)
71 /* List of pt_bdev names and their base bdevs via configuration file.
72 * Used so we can parse the conf once at init and use this list in examine().
77 TAILQ_ENTRY(bdev_names
) link
;
79 static TAILQ_HEAD(, bdev_names
) g_bdev_names
= TAILQ_HEAD_INITIALIZER(g_bdev_names
);
81 /* List of virtual bdevs and associated info for each. */
82 struct vbdev_passthru
{
83 struct spdk_bdev
*base_bdev
; /* the thing we're attaching to */
84 struct spdk_bdev_desc
*base_desc
; /* its descriptor we get from open */
85 struct spdk_bdev pt_bdev
; /* the PT virtual bdev */
86 TAILQ_ENTRY(vbdev_passthru
) link
;
88 static TAILQ_HEAD(, vbdev_passthru
) g_pt_nodes
= TAILQ_HEAD_INITIALIZER(g_pt_nodes
);
90 /* The pt vbdev channel struct. It is allocated and freed on my behalf by the io channel code.
91 * If this vbdev needed to implement a poller or a queue for IO, this is where those things
92 * would be defined. This passthru bdev doesn't actually need to allocate a channel, it could
93 * simply pass back the channel of the bdev underneath it but for example purposes we will
94 * present its own to the upper layers.
96 struct pt_io_channel
{
97 struct spdk_io_channel
*base_ch
; /* IO channel of base device */
100 /* Just for fun, this pt_bdev module doesn't need it but this is essentially a per IO
101 * context that we get handed by the bdev layer.
103 struct passthru_bdev_io
{
107 struct spdk_io_channel
*ch
;
109 /* for bdev_io_wait */
110 struct spdk_bdev_io_wait_entry bdev_io_wait
;
114 vbdev_passthru_submit_request(struct spdk_io_channel
*ch
, struct spdk_bdev_io
*bdev_io
);
116 /* Called after we've unregistered following a hot remove callback.
117 * Our finish entry point will be called next.
120 vbdev_passthru_destruct(void *ctx
)
122 struct vbdev_passthru
*pt_node
= (struct vbdev_passthru
*)ctx
;
124 /* Unclaim the underlying bdev. */
125 spdk_bdev_module_release_bdev(pt_node
->base_bdev
);
127 /* Close the underlying bdev. */
128 spdk_bdev_close(pt_node
->base_desc
);
130 /* Done with this pt_node. */
131 TAILQ_REMOVE(&g_pt_nodes
, pt_node
, link
);
132 free(pt_node
->pt_bdev
.name
);
137 /* Completion callback for IO that were issued from this bdev. The original bdev_io
138 * is passed in as an arg so we'll complete that one with the appropriate status
139 * and then free the one that this module issued.
142 _pt_complete_io(struct spdk_bdev_io
*bdev_io
, bool success
, void *cb_arg
)
144 struct spdk_bdev_io
*orig_io
= cb_arg
;
145 int status
= success
? SPDK_BDEV_IO_STATUS_SUCCESS
: SPDK_BDEV_IO_STATUS_FAILED
;
146 struct passthru_bdev_io
*io_ctx
= (struct passthru_bdev_io
*)orig_io
->driver_ctx
;
148 /* We setup this value in the submission routine, just showing here that it is
151 if (io_ctx
->test
!= 0x5a) {
152 SPDK_ERRLOG("Error, original IO device_ctx is wrong! 0x%x\n",
156 /* Complete the original IO and then free the one that we created here
157 * as a result of issuing an IO via submit_reqeust.
159 spdk_bdev_io_complete(orig_io
, status
);
160 spdk_bdev_free_io(bdev_io
);
164 vbdev_passthru_resubmit_io(void *arg
)
166 struct spdk_bdev_io
*bdev_io
= (struct spdk_bdev_io
*)arg
;
167 struct passthru_bdev_io
*io_ctx
= (struct passthru_bdev_io
*)bdev_io
->driver_ctx
;
169 vbdev_passthru_submit_request(io_ctx
->ch
, bdev_io
);
173 vbdev_passthru_queue_io(struct spdk_bdev_io
*bdev_io
)
175 struct passthru_bdev_io
*io_ctx
= (struct passthru_bdev_io
*)bdev_io
->driver_ctx
;
178 io_ctx
->bdev_io_wait
.bdev
= bdev_io
->bdev
;
179 io_ctx
->bdev_io_wait
.cb_fn
= vbdev_passthru_resubmit_io
;
180 io_ctx
->bdev_io_wait
.cb_arg
= bdev_io
;
182 rc
= spdk_bdev_queue_io_wait(bdev_io
->bdev
, io_ctx
->ch
, &io_ctx
->bdev_io_wait
);
184 SPDK_ERRLOG("Queue io failed in vbdev_passthru_queue_io, rc=%d.\n", rc
);
185 spdk_bdev_io_complete(bdev_io
, SPDK_BDEV_IO_STATUS_FAILED
);
189 /* Callback for getting a buf from the bdev pool in the event that the caller passed
190 * in NULL, we need to own the buffer so it doesn't get freed by another vbdev module
191 * beneath us before we're done with it. That won't happen in this example but it could
192 * if this example were used as a template for something more complex.
195 pt_read_get_buf_cb(struct spdk_io_channel
*ch
, struct spdk_bdev_io
*bdev_io
)
197 struct vbdev_passthru
*pt_node
= SPDK_CONTAINEROF(bdev_io
->bdev
, struct vbdev_passthru
,
199 struct pt_io_channel
*pt_ch
= spdk_io_channel_get_ctx(ch
);
201 spdk_bdev_readv_blocks(pt_node
->base_desc
, pt_ch
->base_ch
, bdev_io
->u
.bdev
.iovs
,
202 bdev_io
->u
.bdev
.iovcnt
, bdev_io
->u
.bdev
.offset_blocks
,
203 bdev_io
->u
.bdev
.num_blocks
, _pt_complete_io
,
207 /* Called when someone above submits IO to this pt vbdev. We're simply passing it on here
208 * via SPDK IO calls which in turn allocate another bdev IO and call our cpl callback provided
209 * below along with the original bdiv_io so that we can complete it once this IO completes.
212 vbdev_passthru_submit_request(struct spdk_io_channel
*ch
, struct spdk_bdev_io
*bdev_io
)
214 struct vbdev_passthru
*pt_node
= SPDK_CONTAINEROF(bdev_io
->bdev
, struct vbdev_passthru
, pt_bdev
);
215 struct pt_io_channel
*pt_ch
= spdk_io_channel_get_ctx(ch
);
216 struct passthru_bdev_io
*io_ctx
= (struct passthru_bdev_io
*)bdev_io
->driver_ctx
;
219 /* Setup a per IO context value; we don't do anything with it in the vbdev other
220 * than confirm we get the same thing back in the completion callback just to
225 switch (bdev_io
->type
) {
226 case SPDK_BDEV_IO_TYPE_READ
:
227 spdk_bdev_io_get_buf(bdev_io
, pt_read_get_buf_cb
,
228 bdev_io
->u
.bdev
.num_blocks
* bdev_io
->bdev
->blocklen
);
230 case SPDK_BDEV_IO_TYPE_WRITE
:
231 rc
= spdk_bdev_writev_blocks(pt_node
->base_desc
, pt_ch
->base_ch
, bdev_io
->u
.bdev
.iovs
,
232 bdev_io
->u
.bdev
.iovcnt
, bdev_io
->u
.bdev
.offset_blocks
,
233 bdev_io
->u
.bdev
.num_blocks
, _pt_complete_io
,
236 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES
:
237 rc
= spdk_bdev_write_zeroes_blocks(pt_node
->base_desc
, pt_ch
->base_ch
,
238 bdev_io
->u
.bdev
.offset_blocks
,
239 bdev_io
->u
.bdev
.num_blocks
,
240 _pt_complete_io
, bdev_io
);
242 case SPDK_BDEV_IO_TYPE_UNMAP
:
243 rc
= spdk_bdev_unmap_blocks(pt_node
->base_desc
, pt_ch
->base_ch
,
244 bdev_io
->u
.bdev
.offset_blocks
,
245 bdev_io
->u
.bdev
.num_blocks
,
246 _pt_complete_io
, bdev_io
);
248 case SPDK_BDEV_IO_TYPE_FLUSH
:
249 rc
= spdk_bdev_flush_blocks(pt_node
->base_desc
, pt_ch
->base_ch
,
250 bdev_io
->u
.bdev
.offset_blocks
,
251 bdev_io
->u
.bdev
.num_blocks
,
252 _pt_complete_io
, bdev_io
);
254 case SPDK_BDEV_IO_TYPE_RESET
:
255 rc
= spdk_bdev_reset(pt_node
->base_desc
, pt_ch
->base_ch
,
256 _pt_complete_io
, bdev_io
);
259 SPDK_ERRLOG("passthru: unknown I/O type %d\n", bdev_io
->type
);
260 spdk_bdev_io_complete(bdev_io
, SPDK_BDEV_IO_STATUS_FAILED
);
265 SPDK_ERRLOG("No memory, start to queue io for passthru.\n");
267 vbdev_passthru_queue_io(bdev_io
);
269 SPDK_ERRLOG("ERROR on bdev_io submission!\n");
270 spdk_bdev_io_complete(bdev_io
, SPDK_BDEV_IO_STATUS_FAILED
);
275 /* We'll just call the base bdev and let it answer however if we were more
276 * restrictive for some reason (or less) we could get the response back
277 * and modify according to our purposes.
280 vbdev_passthru_io_type_supported(void *ctx
, enum spdk_bdev_io_type io_type
)
282 struct vbdev_passthru
*pt_node
= (struct vbdev_passthru
*)ctx
;
284 return spdk_bdev_io_type_supported(pt_node
->base_bdev
, io_type
);
287 /* We supplied this as an entry point for upper layers who want to communicate to this
288 * bdev. This is how they get a channel. We are passed the same context we provided when
289 * we created our PT vbdev in examine() which, for this bdev, is the address of one of
290 * our context nodes. From here we'll ask the SPDK channel code to fill out our channel
291 * struct and we'll keep it in our PT node.
293 static struct spdk_io_channel
*
294 vbdev_passthru_get_io_channel(void *ctx
)
296 struct vbdev_passthru
*pt_node
= (struct vbdev_passthru
*)ctx
;
297 struct spdk_io_channel
*pt_ch
= NULL
;
299 /* The IO channel code will allocate a channel for us which consists of
300 * the SPDK channel structure plus the size of our pt_io_channel struct
301 * that we passed in when we registered our IO device. It will then call
302 * our channel create callback to populate any elements that we need to
305 pt_ch
= spdk_get_io_channel(pt_node
);
311 vbdev_passthru_info_config_json(void *ctx
, struct spdk_json_write_ctx
*write_ctx
)
313 struct vbdev_passthru
*pt_node
= (struct vbdev_passthru
*)ctx
;
315 /* This is the output for get_bdevs() for this vbdev */
316 spdk_json_write_name(write_ctx
, "passthru");
317 spdk_json_write_object_begin(write_ctx
);
319 spdk_json_write_name(write_ctx
, "pt_bdev_name");
320 spdk_json_write_string(write_ctx
, spdk_bdev_get_name(&pt_node
->pt_bdev
));
322 spdk_json_write_name(write_ctx
, "base_bdev_name");
323 spdk_json_write_string(write_ctx
, spdk_bdev_get_name(pt_node
->base_bdev
));
325 spdk_json_write_object_end(write_ctx
);
330 /* We provide this callback for the SPDK channel code to create a channel using
331 * the channel struct we provided in our module get_io_channel() entry point. Here
332 * we get and save off an underlying base channel of the device below us so that
333 * we can communicate with the base bdev on a per channel basis. If we needed
334 * our own poller for this vbdev, we'd register it here.
337 pt_bdev_ch_create_cb(void *io_device
, void *ctx_buf
)
339 struct pt_io_channel
*pt_ch
= ctx_buf
;
340 struct vbdev_passthru
*pt_node
= io_device
;
342 pt_ch
->base_ch
= spdk_bdev_get_io_channel(pt_node
->base_desc
);
347 /* We provide this callback for the SPDK channel code to destroy a channel
348 * created with our create callback. We just need to undo anything we did
349 * when we created. If this bdev used its own poller, we'd unregsiter it here.
352 pt_bdev_ch_destroy_cb(void *io_device
, void *ctx_buf
)
354 struct pt_io_channel
*pt_ch
= ctx_buf
;
356 spdk_put_io_channel(pt_ch
->base_ch
);
359 /* Create the passthru association from the bdev and vbdev name and insert
360 * on the global list. */
362 vbdev_passthru_insert_name(const char *bdev_name
, const char *vbdev_name
)
364 struct bdev_names
*name
;
366 name
= calloc(1, sizeof(struct bdev_names
));
368 SPDK_ERRLOG("could not allocate bdev_names\n");
372 name
->bdev_name
= strdup(bdev_name
);
373 if (!name
->bdev_name
) {
374 SPDK_ERRLOG("could not allocate name->bdev_name\n");
379 name
->vbdev_name
= strdup(vbdev_name
);
380 if (!name
->vbdev_name
) {
381 SPDK_ERRLOG("could not allocate name->vbdev_name\n");
382 free(name
->bdev_name
);
387 TAILQ_INSERT_TAIL(&g_bdev_names
, name
, link
);
392 /* On init, just parse config file and build list of pt vbdevs and bdev name pairs. */
394 vbdev_passthru_init(void)
396 struct spdk_conf_section
*sp
= NULL
;
397 const char *conf_bdev_name
= NULL
;
398 const char *conf_vbdev_name
= NULL
;
399 struct bdev_names
*name
;
402 sp
= spdk_conf_find_section(NULL
, "Passthru");
408 if (!spdk_conf_section_get_nval(sp
, "PT", i
)) {
412 conf_bdev_name
= spdk_conf_section_get_nmval(sp
, "PT", i
, 0);
413 if (!conf_bdev_name
) {
414 SPDK_ERRLOG("Passthru configuration missing bdev name\n");
418 conf_vbdev_name
= spdk_conf_section_get_nmval(sp
, "PT", i
, 1);
419 if (!conf_vbdev_name
) {
420 SPDK_ERRLOG("Passthru configuration missing pt_bdev name\n");
424 rc
= vbdev_passthru_insert_name(conf_bdev_name
, conf_vbdev_name
);
429 TAILQ_FOREACH(name
, &g_bdev_names
, link
) {
430 SPDK_NOTICELOG("conf parse matched: %s\n", name
->bdev_name
);
435 /* Called when the entire module is being torn down. */
437 vbdev_passthru_finish(void)
439 struct bdev_names
*name
;
441 while ((name
= TAILQ_FIRST(&g_bdev_names
))) {
442 TAILQ_REMOVE(&g_bdev_names
, name
, link
);
443 free(name
->bdev_name
);
444 free(name
->vbdev_name
);
449 /* During init we'll be asked how much memory we'd like passed to us
450 * in bev_io structures as context. Here's where we specify how
451 * much context we want per IO.
454 vbdev_passthru_get_ctx_size(void)
456 return sizeof(struct passthru_bdev_io
);
459 /* Called when SPDK wants to save the current config of this vbdev module to
463 vbdev_passthru_get_spdk_running_config(FILE *fp
)
465 struct bdev_names
*names
= NULL
;
467 fprintf(fp
, "\n[Passthru]\n");
468 TAILQ_FOREACH(names
, &g_bdev_names
, link
) {
469 fprintf(fp
, " PT %s %s\n", names
->bdev_name
, names
->vbdev_name
);
474 /* Called when SPDK wants to output the bdev specific methods. */
476 vbdev_passthru_write_json_config(struct spdk_bdev
*bdev
, struct spdk_json_write_ctx
*w
)
478 struct vbdev_passthru
*pt_node
= SPDK_CONTAINEROF(bdev
, struct vbdev_passthru
, pt_bdev
);
480 spdk_json_write_object_begin(w
);
482 spdk_json_write_named_string(w
, "method", "construct_passthru_bdev");
484 spdk_json_write_named_object_begin(w
, "params");
485 spdk_json_write_named_string(w
, "base_bdev_name", spdk_bdev_get_name(pt_node
->base_bdev
));
486 spdk_json_write_named_string(w
, "passthru_bdev_name", spdk_bdev_get_name(bdev
));
487 spdk_json_write_object_end(w
);
489 spdk_json_write_object_end(w
);
492 /* When we register our bdev this is how we specify our entry points. */
493 static const struct spdk_bdev_fn_table vbdev_passthru_fn_table
= {
494 .destruct
= vbdev_passthru_destruct
,
495 .submit_request
= vbdev_passthru_submit_request
,
496 .io_type_supported
= vbdev_passthru_io_type_supported
,
497 .get_io_channel
= vbdev_passthru_get_io_channel
,
498 .dump_info_json
= vbdev_passthru_info_config_json
,
499 .write_config_json
= vbdev_passthru_write_json_config
,
502 /* Called when the underlying base bdev goes away. */
504 vbdev_passthru_base_bdev_hotremove_cb(void *ctx
)
506 struct vbdev_passthru
*pt_node
, *tmp
;
507 struct spdk_bdev
*bdev_find
= ctx
;
509 TAILQ_FOREACH_SAFE(pt_node
, &g_pt_nodes
, link
, tmp
) {
510 if (bdev_find
== pt_node
->base_bdev
) {
511 spdk_bdev_unregister(&pt_node
->pt_bdev
, NULL
, NULL
);
516 /* Create and register the passthru vbdev if we find it in our list of bdev names.
517 * This can be called either by the examine path or RPC method.
520 vbdev_passthru_register(struct spdk_bdev
*bdev
)
522 struct bdev_names
*name
;
523 struct vbdev_passthru
*pt_node
;
526 /* Check our list of names from config versus this bdev and if
527 * there's a match, create the pt_node & bdev accordingly.
529 TAILQ_FOREACH(name
, &g_bdev_names
, link
) {
530 if (strcmp(name
->bdev_name
, bdev
->name
) != 0) {
534 SPDK_NOTICELOG("Match on %s\n", bdev
->name
);
535 pt_node
= calloc(1, sizeof(struct vbdev_passthru
));
537 SPDK_ERRLOG("could not allocate pt_node\n");
541 /* The base bdev that we're attaching to. */
542 pt_node
->base_bdev
= bdev
;
543 pt_node
->pt_bdev
.name
= strdup(name
->vbdev_name
);
544 if (!pt_node
->pt_bdev
.name
) {
545 SPDK_ERRLOG("could not allocate pt_bdev name\n");
549 pt_node
->pt_bdev
.product_name
= "passthru";
551 /* Copy some properties from the underlying base bdev. */
552 pt_node
->pt_bdev
.write_cache
= bdev
->write_cache
;
553 pt_node
->pt_bdev
.need_aligned_buffer
= bdev
->need_aligned_buffer
;
554 pt_node
->pt_bdev
.optimal_io_boundary
= bdev
->optimal_io_boundary
;
555 pt_node
->pt_bdev
.blocklen
= bdev
->blocklen
;
556 pt_node
->pt_bdev
.blockcnt
= bdev
->blockcnt
;
558 /* This is the context that is passed to us when the bdev
559 * layer calls in so we'll save our pt_bdev node here.
561 pt_node
->pt_bdev
.ctxt
= pt_node
;
562 pt_node
->pt_bdev
.fn_table
= &vbdev_passthru_fn_table
;
563 pt_node
->pt_bdev
.module
= &passthru_if
;
564 TAILQ_INSERT_TAIL(&g_pt_nodes
, pt_node
, link
);
566 spdk_io_device_register(pt_node
, pt_bdev_ch_create_cb
, pt_bdev_ch_destroy_cb
,
567 sizeof(struct pt_io_channel
),
569 SPDK_NOTICELOG("io_device created at: 0x%p\n", pt_node
);
571 rc
= spdk_bdev_open(bdev
, true, vbdev_passthru_base_bdev_hotremove_cb
,
572 bdev
, &pt_node
->base_desc
);
574 SPDK_ERRLOG("could not open bdev %s\n", spdk_bdev_get_name(bdev
));
575 TAILQ_REMOVE(&g_pt_nodes
, pt_node
, link
);
576 free(pt_node
->pt_bdev
.name
);
580 SPDK_NOTICELOG("bdev opened\n");
582 rc
= spdk_bdev_module_claim_bdev(bdev
, pt_node
->base_desc
, pt_node
->pt_bdev
.module
);
584 SPDK_ERRLOG("could not claim bdev %s\n", spdk_bdev_get_name(bdev
));
585 spdk_bdev_close(pt_node
->base_desc
);
586 TAILQ_REMOVE(&g_pt_nodes
, pt_node
, link
);
587 free(pt_node
->pt_bdev
.name
);
591 SPDK_NOTICELOG("bdev claimed\n");
593 rc
= spdk_vbdev_register(&pt_node
->pt_bdev
, &bdev
, 1);
595 SPDK_ERRLOG("could not register pt_bdev\n");
596 spdk_bdev_close(pt_node
->base_desc
);
597 TAILQ_REMOVE(&g_pt_nodes
, pt_node
, link
);
598 free(pt_node
->pt_bdev
.name
);
602 SPDK_NOTICELOG("pt_bdev registered\n");
603 SPDK_NOTICELOG("created pt_bdev for: %s\n", name
->vbdev_name
);
607 /* Create the passthru disk from the given bdev and vbdev name. */
609 create_passthru_disk(const char *bdev_name
, const char *vbdev_name
)
611 struct spdk_bdev
*bdev
= NULL
;
614 bdev
= spdk_bdev_get_by_name(bdev_name
);
619 rc
= vbdev_passthru_insert_name(bdev_name
, vbdev_name
);
624 vbdev_passthru_register(bdev
);
630 delete_passthru_disk(struct spdk_bdev
*bdev
, spdk_delete_passthru_complete cb_fn
, void *cb_arg
)
632 struct bdev_names
*name
;
634 if (!bdev
|| bdev
->module
!= &passthru_if
) {
635 cb_fn(cb_arg
, -ENODEV
);
639 /* Remove the association (vbdev, bdev) from g_bdev_names. This is required so that the
640 * vbdev does not get re-created if the same bdev is constructed at some other time,
641 * unless the underlying bdev was hot-removed.
643 TAILQ_FOREACH(name
, &g_bdev_names
, link
) {
644 if (strcmp(name
->vbdev_name
, bdev
->name
) == 0) {
645 TAILQ_REMOVE(&g_bdev_names
, name
, link
);
646 free(name
->bdev_name
);
647 free(name
->vbdev_name
);
653 spdk_bdev_unregister(bdev
, cb_fn
, cb_arg
);
656 /* Because we specified this function in our pt bdev function table when we
657 * registered our pt bdev, we'll get this call anytime a new bdev shows up.
658 * Here we need to decide if we care about it and if so what to do. We
659 * parsed the config file at init so we check the new bdev against the list
660 * we built up at that time and if the user configured us to attach to this
661 * bdev, here's where we do it.
664 vbdev_passthru_examine(struct spdk_bdev
*bdev
)
666 vbdev_passthru_register(bdev
);
668 spdk_bdev_module_examine_done(&passthru_if
);
671 SPDK_LOG_REGISTER_COMPONENT("vbdev_passthru", SPDK_LOG_VBDEV_PASSTHRU
)