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);
59 static int vbdev_passthru_config_json(struct spdk_json_write_ctx
*w
);
61 static struct spdk_bdev_module passthru_if
= {
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
71 SPDK_BDEV_MODULE_REGISTER(passthru
, &passthru_if
)
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().
79 TAILQ_ENTRY(bdev_names
) link
;
81 static TAILQ_HEAD(, bdev_names
) g_bdev_names
= TAILQ_HEAD_INITIALIZER(g_bdev_names
);
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
;
90 static TAILQ_HEAD(, vbdev_passthru
) g_pt_nodes
= TAILQ_HEAD_INITIALIZER(g_pt_nodes
);
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.
98 struct pt_io_channel
{
99 struct spdk_io_channel
*base_ch
; /* IO channel of base device */
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.
105 struct passthru_bdev_io
{
109 struct spdk_io_channel
*ch
;
111 /* for bdev_io_wait */
112 struct spdk_bdev_io_wait_entry bdev_io_wait
;
116 vbdev_passthru_submit_request(struct spdk_io_channel
*ch
, struct spdk_bdev_io
*bdev_io
);
119 /* Callback for unregistering the IO device. */
121 _device_unregister_cb(void *io_device
)
123 struct vbdev_passthru
*pt_node
= io_device
;
125 /* Done with this pt_node. */
126 free(pt_node
->pt_bdev
.name
);
130 /* Called after we've unregistered following a hot remove callback.
131 * Our finish entry point will be called next.
134 vbdev_passthru_destruct(void *ctx
)
136 struct vbdev_passthru
*pt_node
= (struct vbdev_passthru
*)ctx
;
138 /* It is important to follow this exact sequence of steps for destroying
142 TAILQ_REMOVE(&g_pt_nodes
, pt_node
, link
);
144 /* Unclaim the underlying bdev. */
145 spdk_bdev_module_release_bdev(pt_node
->base_bdev
);
147 /* Close the underlying bdev. */
148 spdk_bdev_close(pt_node
->base_desc
);
150 /* Unregister the io_device. */
151 spdk_io_device_unregister(pt_node
, _device_unregister_cb
);
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.
161 _pt_complete_io(struct spdk_bdev_io
*bdev_io
, bool success
, void *cb_arg
)
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
;
167 /* We setup this value in the submission routine, just showing here that it is
170 if (io_ctx
->test
!= 0x5a) {
171 SPDK_ERRLOG("Error, original IO device_ctx is wrong! 0x%x\n",
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.
178 spdk_bdev_io_complete(orig_io
, status
);
179 spdk_bdev_free_io(bdev_io
);
183 vbdev_passthru_resubmit_io(void *arg
)
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
;
188 vbdev_passthru_submit_request(io_ctx
->ch
, bdev_io
);
192 vbdev_passthru_queue_io(struct spdk_bdev_io
*bdev_io
)
194 struct passthru_bdev_io
*io_ctx
= (struct passthru_bdev_io
*)bdev_io
->driver_ctx
;
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
;
201 rc
= spdk_bdev_queue_io_wait(bdev_io
->bdev
, io_ctx
->ch
, &io_ctx
->bdev_io_wait
);
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
);
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.
214 pt_read_get_buf_cb(struct spdk_io_channel
*ch
, struct spdk_bdev_io
*bdev_io
, bool success
)
216 struct vbdev_passthru
*pt_node
= SPDK_CONTAINEROF(bdev_io
->bdev
, struct vbdev_passthru
,
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
;
223 spdk_bdev_io_complete(bdev_io
, SPDK_BDEV_IO_STATUS_FAILED
);
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
,
233 SPDK_ERRLOG("No memory, start to queue io for passthru.\n");
235 vbdev_passthru_queue_io(bdev_io
);
237 SPDK_ERRLOG("ERROR on bdev_io submission!\n");
238 spdk_bdev_io_complete(bdev_io
, SPDK_BDEV_IO_STATUS_FAILED
);
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.
248 vbdev_passthru_submit_request(struct spdk_io_channel
*ch
, struct spdk_bdev_io
*bdev_io
)
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
;
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
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
);
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
,
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
);
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
);
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
);
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
);
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
);
301 SPDK_ERRLOG("No memory, start to queue io for passthru.\n");
303 vbdev_passthru_queue_io(bdev_io
);
305 SPDK_ERRLOG("ERROR on bdev_io submission!\n");
306 spdk_bdev_io_complete(bdev_io
, SPDK_BDEV_IO_STATUS_FAILED
);
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.
316 vbdev_passthru_io_type_supported(void *ctx
, enum spdk_bdev_io_type io_type
)
318 struct vbdev_passthru
*pt_node
= (struct vbdev_passthru
*)ctx
;
320 return spdk_bdev_io_type_supported(pt_node
->base_bdev
, io_type
);
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.
329 static struct spdk_io_channel
*
330 vbdev_passthru_get_io_channel(void *ctx
)
332 struct vbdev_passthru
*pt_node
= (struct vbdev_passthru
*)ctx
;
333 struct spdk_io_channel
*pt_ch
= NULL
;
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
341 pt_ch
= spdk_get_io_channel(pt_node
);
346 /* This is the output for get_bdevs() for this vbdev */
348 vbdev_passthru_dump_info_json(void *ctx
, struct spdk_json_write_ctx
*w
)
350 struct vbdev_passthru
*pt_node
= (struct vbdev_passthru
*)ctx
;
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
);
361 /* This is used to generate JSON that can configure this module to its current state. */
363 vbdev_passthru_config_json(struct spdk_json_write_ctx
*w
)
365 struct vbdev_passthru
*pt_node
;
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
);
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.
386 pt_bdev_ch_create_cb(void *io_device
, void *ctx_buf
)
388 struct pt_io_channel
*pt_ch
= ctx_buf
;
389 struct vbdev_passthru
*pt_node
= io_device
;
391 pt_ch
->base_ch
= spdk_bdev_get_io_channel(pt_node
->base_desc
);
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.
401 pt_bdev_ch_destroy_cb(void *io_device
, void *ctx_buf
)
403 struct pt_io_channel
*pt_ch
= ctx_buf
;
405 spdk_put_io_channel(pt_ch
->base_ch
);
408 /* Create the passthru association from the bdev and vbdev name and insert
409 * on the global list. */
411 vbdev_passthru_insert_name(const char *bdev_name
, const char *vbdev_name
)
413 struct bdev_names
*name
;
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
);
422 name
= calloc(1, sizeof(struct bdev_names
));
424 SPDK_ERRLOG("could not allocate bdev_names\n");
428 name
->bdev_name
= strdup(bdev_name
);
429 if (!name
->bdev_name
) {
430 SPDK_ERRLOG("could not allocate name->bdev_name\n");
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
);
443 TAILQ_INSERT_TAIL(&g_bdev_names
, name
, link
);
448 /* On init, just parse config file and build list of pt vbdevs and bdev name pairs. */
450 vbdev_passthru_init(void)
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
;
458 sp
= spdk_conf_find_section(NULL
, "Passthru");
464 if (!spdk_conf_section_get_nval(sp
, "PT", i
)) {
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");
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");
480 rc
= vbdev_passthru_insert_name(conf_bdev_name
, conf_vbdev_name
);
485 TAILQ_FOREACH(name
, &g_bdev_names
, link
) {
486 SPDK_NOTICELOG("conf parse matched: %s\n", name
->bdev_name
);
491 /* Called when the entire module is being torn down. */
493 vbdev_passthru_finish(void)
495 struct bdev_names
*name
;
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
);
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.
510 vbdev_passthru_get_ctx_size(void)
512 return sizeof(struct passthru_bdev_io
);
515 /* Called when SPDK wants to save the current config of this vbdev module to
519 vbdev_passthru_get_spdk_running_config(FILE *fp
)
521 struct bdev_names
*names
= NULL
;
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
);
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
535 vbdev_passthru_write_config_json(struct spdk_bdev
*bdev
, struct spdk_json_write_ctx
*w
)
537 /* No config per bdev needed */
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
,
550 /* Called when the underlying base bdev goes away. */
552 vbdev_passthru_base_bdev_hotremove_cb(void *ctx
)
554 struct vbdev_passthru
*pt_node
, *tmp
;
555 struct spdk_bdev
*bdev_find
= ctx
;
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
);
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.
568 vbdev_passthru_register(struct spdk_bdev
*bdev
)
570 struct bdev_names
*name
;
571 struct vbdev_passthru
*pt_node
;
574 /* Check our list of names from config versus this bdev and if
575 * there's a match, create the pt_node & bdev accordingly.
577 TAILQ_FOREACH(name
, &g_bdev_names
, link
) {
578 if (strcmp(name
->bdev_name
, bdev
->name
) != 0) {
582 SPDK_NOTICELOG("Match on %s\n", bdev
->name
);
583 pt_node
= calloc(1, sizeof(struct vbdev_passthru
));
586 SPDK_ERRLOG("could not allocate pt_node\n");
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
) {
595 SPDK_ERRLOG("could not allocate pt_bdev name\n");
599 pt_node
->pt_bdev
.product_name
= "passthru";
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
;
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.
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
);
616 spdk_io_device_register(pt_node
, pt_bdev_ch_create_cb
, pt_bdev_ch_destroy_cb
,
617 sizeof(struct pt_io_channel
),
619 SPDK_NOTICELOG("io_device created at: 0x%p\n", pt_node
);
621 rc
= spdk_bdev_open(bdev
, true, vbdev_passthru_base_bdev_hotremove_cb
,
622 bdev
, &pt_node
->base_desc
);
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
);
631 SPDK_NOTICELOG("bdev opened\n");
633 rc
= spdk_bdev_module_claim_bdev(bdev
, pt_node
->base_desc
, pt_node
->pt_bdev
.module
);
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
);
643 SPDK_NOTICELOG("bdev claimed\n");
645 rc
= spdk_bdev_register(&pt_node
->pt_bdev
);
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
);
656 SPDK_NOTICELOG("pt_bdev registered\n");
657 SPDK_NOTICELOG("created pt_bdev for: %s\n", name
->vbdev_name
);
663 /* Create the passthru disk from the given bdev and vbdev name. */
665 create_passthru_disk(const char *bdev_name
, const char *vbdev_name
)
667 struct spdk_bdev
*bdev
= NULL
;
670 /* Insert the bdev into our global name list even if it doesn't exist yet,
671 * it may show up soon...
673 rc
= vbdev_passthru_insert_name(bdev_name
, vbdev_name
);
678 bdev
= spdk_bdev_get_by_name(bdev_name
);
680 /* This is not an error, we tracked the name above and it still
683 SPDK_NOTICELOG("vbdev creation deferred pending base bdev arrival\n");
687 return vbdev_passthru_register(bdev
);
691 delete_passthru_disk(struct spdk_bdev
*bdev
, spdk_bdev_unregister_cb cb_fn
, void *cb_arg
)
693 struct bdev_names
*name
;
695 if (!bdev
|| bdev
->module
!= &passthru_if
) {
696 cb_fn(cb_arg
, -ENODEV
);
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.
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
);
714 /* Additional cleanup happens in the destruct callback. */
715 spdk_bdev_unregister(bdev
, cb_fn
, cb_arg
);
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.
726 vbdev_passthru_examine(struct spdk_bdev
*bdev
)
728 vbdev_passthru_register(bdev
);
730 spdk_bdev_module_examine_done(&passthru_if
);
733 SPDK_LOG_REGISTER_COMPONENT("vbdev_passthru", SPDK_LOG_VBDEV_PASSTHRU
)