From 7f6c737a25fc4921d22d00788a7814c227031257 Mon Sep 17 00:00:00 2001 From: Jim Harris Date: Thu, 29 Jun 2017 13:16:26 -0700 Subject: [PATCH] bdev: add virtual to base bdev relationships Each virtual bdev now has a pointer to its base bdev, and a base bdev has a pointers to any virtual bdevs built on top of it. Also add a new set of leaf iterators, to get only bdevs that have no virtual bdevs built on top of them. These iterators are now used by the bdevio and bdevperf utilities, in advance of the claim/unclaim semantics getting removed in a future patch. Signed-off-by: Jim Harris Change-Id: I669783764407cdd4920b5ee121959e2a58c8d436 Reviewed-on: https://review.gerrithub.io/367610 Reviewed-by: Daniel Verkamp Tested-by: SPDK Automated Test System Reviewed-by: Ben Walker --- include/spdk/bdev.h | 10 ++++ include/spdk_internal/bdev.h | 14 ++++++ lib/bdev/bdev.c | 80 ++++++++++++++++++++++++++++++- lib/bdev/error/vbdev_error.c | 2 +- lib/bdev/split/vbdev_split.c | 2 +- test/lib/bdev/bdevio/bdevio.c | 6 +-- test/lib/bdev/bdevperf/bdevperf.c | 8 ++-- 7 files changed, 111 insertions(+), 11 deletions(-) diff --git a/include/spdk/bdev.h b/include/spdk/bdev.h index 1b7d2be74..c7c5d7e89 100644 --- a/include/spdk/bdev.h +++ b/include/spdk/bdev.h @@ -126,9 +126,19 @@ void spdk_bdev_config_text(FILE *fp); struct spdk_bdev *spdk_bdev_get_by_name(const char *bdev_name); +/** + * These two functions iterate the full list of bdevs, including bdevs + * that have virtual bdevs on top of them. + */ struct spdk_bdev *spdk_bdev_first(void); struct spdk_bdev *spdk_bdev_next(struct spdk_bdev *prev); +/** + * These two functions only iterate over bdevs which have no virtual + * bdevs on top of them. + */ +struct spdk_bdev *spdk_bdev_first_leaf(void); +struct spdk_bdev *spdk_bdev_next_leaf(struct spdk_bdev *prev); /** * Claim ownership of a block device. * diff --git a/include/spdk_internal/bdev.h b/include/spdk_internal/bdev.h index f013c23cc..94d176477 100644 --- a/include/spdk_internal/bdev.h +++ b/include/spdk_internal/bdev.h @@ -201,6 +201,16 @@ struct spdk_bdev { /** The bdev status */ enum spdk_bdev_status status; + /** The list of block devices that this block device is built on top of (if any). */ + TAILQ_HEAD(, spdk_bdev) base_bdevs; + + TAILQ_ENTRY(spdk_bdev) base_bdev_link; + + /** The list of virtual block devices built on top of this block device. */ + TAILQ_HEAD(, spdk_bdev) vbdevs; + + TAILQ_ENTRY(spdk_bdev) vbdev_link; + /** Remove callback function pointer to upper level stack */ spdk_bdev_remove_cb_t remove_cb; @@ -354,6 +364,10 @@ struct spdk_bdev_io { void spdk_bdev_register(struct spdk_bdev *bdev); void spdk_bdev_unregister(struct spdk_bdev *bdev); +void spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs, + int base_bdev_count); +void spdk_vbdev_unregister(struct spdk_bdev *vbdev); + void spdk_bdev_poller_start(struct spdk_bdev_poller **ppoller, spdk_bdev_poller_fn fn, void *arg, diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index f1ae4748f..fba6c19b8 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -147,6 +147,48 @@ spdk_bdev_next(struct spdk_bdev *prev) return bdev; } +static struct spdk_bdev * +_bdev_next_leaf(struct spdk_bdev *bdev) +{ + while (bdev != NULL) { + if (TAILQ_EMPTY(&bdev->vbdevs)) { + return bdev; + } else { + bdev = TAILQ_NEXT(bdev, link); + } + } + + return bdev; +} + +struct spdk_bdev * +spdk_bdev_first_leaf(void) +{ + struct spdk_bdev *bdev; + + bdev = _bdev_next_leaf(TAILQ_FIRST(&g_bdev_mgr.bdevs)); + + if (bdev) { + SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Starting bdev iteration at %s\n", bdev->name); + } + + return bdev; +} + +struct spdk_bdev * +spdk_bdev_next_leaf(struct spdk_bdev *prev) +{ + struct spdk_bdev *bdev; + + bdev = _bdev_next_leaf(TAILQ_NEXT(prev, link)); + + if (bdev) { + SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Continuing bdev iteration at %s\n", bdev->name); + } + + return bdev; +} + struct spdk_bdev * spdk_bdev_get_by_name(const char *bdev_name) { @@ -1313,14 +1355,17 @@ spdk_bdev_io_get_nvme_status(const struct spdk_bdev_io *bdev_io, int *sct, int * } } -void -spdk_bdev_register(struct spdk_bdev *bdev) +static void +_spdk_bdev_register(struct spdk_bdev *bdev) { struct spdk_bdev_module_if *vbdev_module; /* initialize the reset generation value to zero */ bdev->gencnt = 0; + TAILQ_INIT(&bdev->vbdevs); + TAILQ_INIT(&bdev->base_bdevs); + bdev->reset_in_progress = false; TAILQ_INIT(&bdev->queued_resets); @@ -1339,6 +1384,25 @@ spdk_bdev_register(struct spdk_bdev *bdev) } } +void +spdk_bdev_register(struct spdk_bdev *bdev) +{ + _spdk_bdev_register(bdev); +} + +void +spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs, int base_bdev_count) +{ + int i; + + _spdk_bdev_register(vbdev); + for (i = 0; i < base_bdev_count; i++) { + assert(base_bdevs[i] != NULL); + TAILQ_INSERT_TAIL(&vbdev->base_bdevs, base_bdevs[i], base_bdev_link); + TAILQ_INSERT_TAIL(&base_bdevs[i]->vbdevs, vbdev, vbdev_link); + } +} + void spdk_bdev_unregister(struct spdk_bdev *bdev) { @@ -1372,6 +1436,18 @@ spdk_bdev_unregister(struct spdk_bdev *bdev) } } +void +spdk_vbdev_unregister(struct spdk_bdev *vbdev) +{ + struct spdk_bdev *base_bdev; + + assert(!TAILQ_EMPTY(&vbdev->base_bdevs)); + TAILQ_FOREACH(base_bdev, &vbdev->base_bdevs, base_bdev_link) { + TAILQ_REMOVE(&base_bdev->vbdevs, vbdev, vbdev_link); + } + spdk_bdev_unregister(vbdev); +} + bool spdk_bdev_claim(struct spdk_bdev *bdev, spdk_bdev_remove_cb_t remove_cb, void *remove_ctx) diff --git a/lib/bdev/error/vbdev_error.c b/lib/bdev/error/vbdev_error.c index a359ef13a..5bfecf3aa 100644 --- a/lib/bdev/error/vbdev_error.c +++ b/lib/bdev/error/vbdev_error.c @@ -240,7 +240,7 @@ spdk_vbdev_error_create(struct spdk_bdev *base_bdev) disk->disk.ctxt = disk; disk->disk.fn_table = &vbdev_error_fn_table; - spdk_bdev_register(&disk->disk); + spdk_vbdev_register(&disk->disk, &base_bdev, 1); TAILQ_INSERT_TAIL(&g_vbdev_error_disks, disk, tailq); diff --git a/lib/bdev/split/vbdev_split.c b/lib/bdev/split/vbdev_split.c index 9e91d0077..69f466877 100644 --- a/lib/bdev/split/vbdev_split.c +++ b/lib/bdev/split/vbdev_split.c @@ -319,7 +319,7 @@ vbdev_split_create(struct spdk_bdev *base_bdev, uint64_t split_count, uint64_t s vbdev_split_base_get_ref(split_base, d); - spdk_bdev_register(&d->disk); + spdk_vbdev_register(&d->disk, &base_bdev, 1); TAILQ_INSERT_TAIL(&g_split_disks, d, tailq); diff --git a/test/lib/bdev/bdevio/bdevio.c b/test/lib/bdev/bdevio/bdevio.c index 9546055ec..676a64fdb 100644 --- a/test/lib/bdev/bdevio/bdevio.c +++ b/test/lib/bdev/bdevio/bdevio.c @@ -106,13 +106,13 @@ bdevio_construct_targets(void) printf("I/O targets:\n"); - bdev = spdk_bdev_first(); + bdev = spdk_bdev_first_leaf(); while (bdev != NULL) { uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev); uint32_t block_size = spdk_bdev_get_block_size(bdev); if (!spdk_bdev_claim(bdev, NULL, NULL)) { - bdev = spdk_bdev_next(bdev); + bdev = spdk_bdev_next_leaf(bdev); continue; } @@ -130,7 +130,7 @@ bdevio_construct_targets(void) execute_spdk_function(__get_io_channel, target, NULL); g_io_targets = target; - bdev = spdk_bdev_next(bdev); + bdev = spdk_bdev_next_leaf(bdev); } return 0; diff --git a/test/lib/bdev/bdevperf/bdevperf.c b/test/lib/bdev/bdevperf/bdevperf.c index 53d75b7ed..e7173f009 100644 --- a/test/lib/bdev/bdevperf/bdevperf.c +++ b/test/lib/bdev/bdevperf/bdevperf.c @@ -117,17 +117,17 @@ bdevperf_construct_targets(void) struct io_target *target; size_t align; - bdev = spdk_bdev_first(); + bdev = spdk_bdev_first_leaf(); while (bdev != NULL) { if (!spdk_bdev_claim(bdev, NULL, NULL)) { - bdev = spdk_bdev_next(bdev); + bdev = spdk_bdev_next_leaf(bdev); continue; } if (g_unmap && !spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) { printf("Skipping %s because it does not support unmap\n", spdk_bdev_get_name(bdev)); - bdev = spdk_bdev_next(bdev); + bdev = spdk_bdev_next_leaf(bdev); continue; } @@ -161,7 +161,7 @@ bdevperf_construct_targets(void) head[index] = target; g_target_count++; - bdev = spdk_bdev_next(bdev); + bdev = spdk_bdev_next_leaf(bdev); } }