From 6b7609b6395eb3d26b80b606b6dc811eb55e83c5 Mon Sep 17 00:00:00 2001 From: Seth Howell Date: Thu, 28 Jun 2018 10:37:00 -0700 Subject: [PATCH] bdev.c: encapsulate members of spdk_bdev_part. Change-Id: Ia3d04905d319c075a12726ca85c3aa1d3135db44 Signed-off-by: Seth Howell Reviewed-on: https://review.gerrithub.io/417176 Tested-by: SPDK Automated Test System Reviewed-by: Jim Harris Reviewed-by: Ben Walker Reviewed-by: Shuhei Matsumoto --- CHANGELOG.md | 5 +++ include/spdk/bdev_module.h | 61 +++++++++++++++++++++++-- lib/bdev/error/vbdev_error.c | 6 +-- lib/bdev/gpt/vbdev_gpt.c | 8 ++-- lib/bdev/part.c | 86 +++++++++++++++++++++++------------- lib/bdev/split/vbdev_split.c | 5 ++- 6 files changed, 129 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1ef11b80..2346913f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,11 @@ on each call. This allows multiple callers to query I/O statistics without confl with each other. Existing users will need to adjust their code to record the previous I/O statistics to calculate the delta between calls. +A new public header file bdev_module.h has been introduced to facilitate the development +of new bdev modules. This header includes an interface for the spdk_bdev_part and +spdk_bdev_part_base objects to enable the creation of multiple virtual bdevs on top of a +single base bdev. + ### Env The spdk_mem_map_translate() function now takes a size parameter to indicate the size of diff --git a/include/spdk/bdev_module.h b/include/spdk/bdev_module.h index 89f33ed02..aa1c4f5ba 100644 --- a/include/spdk/bdev_module.h +++ b/include/spdk/bdev_module.h @@ -736,10 +736,24 @@ uint32_t spdk_bdev_part_base_get_ref(struct spdk_bdev_part_base *part_base); typedef void (*spdk_bdev_part_base_free_fn)(void *ctx); struct spdk_bdev_part { - struct spdk_bdev bdev; - struct spdk_bdev_part_base *base; - uint64_t offset_blocks; + /* Entry into the module's global list of bdev parts */ TAILQ_ENTRY(spdk_bdev_part) tailq; + + /** + * Fields that are used internally by part.c These fields should only + * be accessed from a module using any pertinent get and set methods. + */ + struct bdev_part_internal_fields { + + /* This part's corresponding bdev object. Not to be confused with the base bdev */ + struct spdk_bdev bdev; + + /* The base to which this part belongs */ + struct spdk_bdev_part_base *base; + + /* number of blocks from the start of the base bdev to the start of this part */ + uint64_t offset_blocks; + } internal; }; struct spdk_bdev_part_channel { @@ -830,6 +844,47 @@ int spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_ */ void spdk_bdev_part_submit_request(struct spdk_bdev_part_channel *ch, struct spdk_bdev_io *bdev_io); +/** + * Return a pointer to this part's spdk_bdev. + * + * \param part An spdk_bdev_part object. + * + * \return A pointer to this part's spdk_bdev object. + */ +struct spdk_bdev *spdk_bdev_part_get_bdev(struct spdk_bdev_part *part); + +/** + * Return a pointer to this part's base. + * + * \param part An spdk_bdev_part object. + * + * \return A pointer to this part's spdk_bdev_part_base object. + */ +struct spdk_bdev_part_base *spdk_bdev_part_get_base(struct spdk_bdev_part *part); + +/** + * Return a pointer to this part's base bdev. + * + * The return value of this function is equivalent to calling + * spdk_bdev_part_base_get_bdev on this part's base. + * + * \param part An spdk_bdev_part object. + * + * \return A pointer to the bdev belonging to this part's base. + */ +struct spdk_bdev *spdk_bdev_part_get_base_bdev(struct spdk_bdev_part *part); + +/** + * Return this part's offset from the beginning of the base bdev. + * + * This function should not be called in the I/O path. Any block + * translations to I/O will be handled in spdk_bdev_part_submit_request. + * + * \param part An spdk_bdev_part object. + * + * \return the block offset of this part from it's underlying bdev. + */ +uint64_t spdk_bdev_part_get_offset_blocks(struct spdk_bdev_part *part); /* * Macro used to register module for later initialization. diff --git a/lib/bdev/error/vbdev_error.c b/lib/bdev/error/vbdev_error.c index 6fc965258..83e8c78bf 100644 --- a/lib/bdev/error/vbdev_error.c +++ b/lib/bdev/error/vbdev_error.c @@ -113,7 +113,7 @@ spdk_vbdev_inject_error(char *name, uint32_t io_type, uint32_t error_type, uint3 } TAILQ_FOREACH(part, &g_error_disks, tailq) { - if (bdev == &part->bdev) { + if (bdev == spdk_bdev_part_get_bdev(part)) { error_disk = (struct error_disk *)part; break; } @@ -206,7 +206,7 @@ static int vbdev_error_destruct(void *ctx) { struct error_disk *error_disk = ctx; - struct spdk_bdev *base_bdev = spdk_bdev_part_base_get_bdev(error_disk->part.base); + struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(&error_disk->part); int rc; rc = vbdev_error_config_remove(base_bdev->name); @@ -221,7 +221,7 @@ static int vbdev_error_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) { struct error_disk *error_disk = ctx; - struct spdk_bdev *base_bdev = spdk_bdev_part_base_get_bdev(error_disk->part.base); + struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(&error_disk->part); spdk_json_write_name(w, "error_disk"); spdk_json_write_object_begin(w); diff --git a/lib/bdev/gpt/vbdev_gpt.c b/lib/bdev/gpt/vbdev_gpt.c index b1f93757f..468a8f643 100644 --- a/lib/bdev/gpt/vbdev_gpt.c +++ b/lib/bdev/gpt/vbdev_gpt.c @@ -193,10 +193,12 @@ static int vbdev_gpt_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) { struct gpt_disk *gpt_disk = SPDK_CONTAINEROF(ctx, struct gpt_disk, part); - struct gpt_base *gpt_base = spdk_bdev_part_base_get_ctx(gpt_disk->part.base); - struct spdk_bdev *part_base_bdev = spdk_bdev_part_base_get_bdev(gpt_disk->part.base); + struct spdk_bdev_part_base *base_bdev = spdk_bdev_part_get_base(&gpt_disk->part); + struct gpt_base *gpt_base = spdk_bdev_part_base_get_ctx(base_bdev); + struct spdk_bdev *part_base_bdev = spdk_bdev_part_base_get_bdev(base_bdev); struct spdk_gpt *gpt = &gpt_base->gpt; struct spdk_gpt_partition_entry *gpt_entry = &gpt->partitions[gpt_disk->partition_index]; + uint64_t offset_blocks = spdk_bdev_part_get_offset_blocks(&gpt_disk->part); spdk_json_write_name(w, "gpt"); spdk_json_write_object_begin(w); @@ -205,7 +207,7 @@ vbdev_gpt_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) spdk_json_write_string(w, spdk_bdev_get_name(part_base_bdev)); spdk_json_write_name(w, "offset_blocks"); - spdk_json_write_uint64(w, gpt_disk->part.offset_blocks); + spdk_json_write_uint64(w, offset_blocks); spdk_json_write_name(w, "partition_type_guid"); write_guid(w, &gpt_entry->part_type_guid); diff --git a/lib/bdev/part.c b/lib/bdev/part.c index 6a008d5eb..29c4a97d8 100644 --- a/lib/bdev/part.c +++ b/lib/bdev/part.c @@ -107,9 +107,9 @@ spdk_bdev_part_free_cb(void *io_device) struct spdk_bdev_part_base *base; assert(part); - assert(part->base); + assert(part->internal.base); - base = part->base; + base = part->internal.base; TAILQ_REMOVE(base->tailq, part, tailq); @@ -118,8 +118,8 @@ spdk_bdev_part_free_cb(void *io_device) spdk_bdev_part_base_free(base); } - spdk_bdev_destruct_done(&part->bdev, 0); - free(part->bdev.name); + spdk_bdev_destruct_done(&part->internal.bdev, 0); + free(part->internal.bdev.name); free(part); } @@ -139,8 +139,8 @@ spdk_bdev_part_base_hotremove(struct spdk_bdev *base_bdev, struct bdev_part_tail struct spdk_bdev_part *part, *tmp; TAILQ_FOREACH_SAFE(part, tailq, tailq, tmp) { - if (part->base->bdev == base_bdev) { - spdk_bdev_unregister(&part->bdev, NULL, NULL); + if (part->internal.base->bdev == base_bdev) { + spdk_bdev_unregister(&part->internal.bdev, NULL, NULL); } } } @@ -150,7 +150,7 @@ spdk_bdev_part_io_type_supported(void *_part, enum spdk_bdev_io_type io_type) { struct spdk_bdev_part *part = _part; - return part->base->bdev->fn_table->io_type_supported(part->base->bdev, io_type); + return part->internal.base->bdev->fn_table->io_type_supported(part->internal.base->bdev, io_type); } static struct spdk_io_channel * @@ -161,6 +161,30 @@ spdk_bdev_part_get_io_channel(void *_part) return spdk_get_io_channel(part); } +struct spdk_bdev * +spdk_bdev_part_get_bdev(struct spdk_bdev_part *part) +{ + return &part->internal.bdev; +} + +struct spdk_bdev_part_base * +spdk_bdev_part_get_base(struct spdk_bdev_part *part) +{ + return part->internal.base; +} + +struct spdk_bdev * +spdk_bdev_part_get_base_bdev(struct spdk_bdev_part *part) +{ + return part->internal.base->bdev; +} + +uint64_t +spdk_bdev_part_get_offset_blocks(struct spdk_bdev_part *part) +{ + return part->internal.offset_blocks; +} + static void spdk_bdev_part_complete_io(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) { @@ -176,38 +200,38 @@ spdk_bdev_part_submit_request(struct spdk_bdev_part_channel *ch, struct spdk_bde { struct spdk_bdev_part *part = ch->part; struct spdk_io_channel *base_ch = ch->base_ch; - struct spdk_bdev_desc *base_desc = part->base->desc; + struct spdk_bdev_desc *base_desc = part->internal.base->desc; uint64_t offset; int rc = 0; /* Modify the I/O to adjust for the offset within the base bdev. */ switch (bdev_io->type) { case SPDK_BDEV_IO_TYPE_READ: - offset = bdev_io->u.bdev.offset_blocks + part->offset_blocks; + offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks; rc = spdk_bdev_readv_blocks(base_desc, base_ch, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, offset, bdev_io->u.bdev.num_blocks, spdk_bdev_part_complete_io, bdev_io); break; case SPDK_BDEV_IO_TYPE_WRITE: - offset = bdev_io->u.bdev.offset_blocks + part->offset_blocks; + offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks; rc = spdk_bdev_writev_blocks(base_desc, base_ch, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, offset, bdev_io->u.bdev.num_blocks, spdk_bdev_part_complete_io, bdev_io); break; case SPDK_BDEV_IO_TYPE_WRITE_ZEROES: - offset = bdev_io->u.bdev.offset_blocks + part->offset_blocks; + offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks; rc = spdk_bdev_write_zeroes_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks, spdk_bdev_part_complete_io, bdev_io); break; case SPDK_BDEV_IO_TYPE_UNMAP: - offset = bdev_io->u.bdev.offset_blocks + part->offset_blocks; + offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks; rc = spdk_bdev_unmap_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks, spdk_bdev_part_complete_io, bdev_io); break; case SPDK_BDEV_IO_TYPE_FLUSH: - offset = bdev_io->u.bdev.offset_blocks + part->offset_blocks; + offset = bdev_io->u.bdev.offset_blocks + part->internal.offset_blocks; rc = spdk_bdev_flush_blocks(base_desc, base_ch, offset, bdev_io->u.bdev.num_blocks, spdk_bdev_part_complete_io, bdev_io); break; @@ -232,13 +256,13 @@ spdk_bdev_part_channel_create_cb(void *io_device, void *ctx_buf) struct spdk_bdev_part_channel *ch = ctx_buf; ch->part = part; - ch->base_ch = spdk_bdev_get_io_channel(part->base->desc); + ch->base_ch = spdk_bdev_get_io_channel(part->internal.base->desc); if (ch->base_ch == NULL) { return -1; } - if (part->base->ch_create_cb) { - return part->base->ch_create_cb(io_device, ctx_buf); + if (part->internal.base->ch_create_cb) { + return part->internal.base->ch_create_cb(io_device, ctx_buf); } else { return 0; } @@ -250,8 +274,8 @@ spdk_bdev_part_channel_destroy_cb(void *io_device, void *ctx_buf) struct spdk_bdev_part *part = (struct spdk_bdev_part *)io_device; struct spdk_bdev_part_channel *ch = ctx_buf; - if (part->base->ch_destroy_cb) { - part->base->ch_destroy_cb(io_device, ctx_buf); + if (part->internal.base->ch_destroy_cb) { + part->internal.base->ch_destroy_cb(io_device, ctx_buf); } spdk_put_io_channel(ch->base_ch); } @@ -303,20 +327,20 @@ spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base char *name, uint64_t offset_blocks, uint64_t num_blocks, char *product_name) { - part->bdev.name = name; - part->bdev.blocklen = base->bdev->blocklen; - part->bdev.blockcnt = num_blocks; - part->offset_blocks = offset_blocks; + part->internal.bdev.name = name; + part->internal.bdev.blocklen = base->bdev->blocklen; + part->internal.bdev.blockcnt = num_blocks; + part->internal.offset_blocks = offset_blocks; - part->bdev.write_cache = base->bdev->write_cache; - part->bdev.need_aligned_buffer = base->bdev->need_aligned_buffer; - part->bdev.product_name = product_name; - part->bdev.ctxt = part; - part->bdev.module = base->module; - part->bdev.fn_table = base->fn_table; + part->internal.bdev.write_cache = base->bdev->write_cache; + part->internal.bdev.need_aligned_buffer = base->bdev->need_aligned_buffer; + part->internal.bdev.product_name = product_name; + part->internal.bdev.ctxt = part; + part->internal.bdev.module = base->module; + part->internal.bdev.fn_table = base->fn_table; __sync_fetch_and_add(&base->ref, 1); - part->base = base; + part->internal.base = base; if (!base->claimed) { int rc; @@ -324,7 +348,7 @@ spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base rc = spdk_bdev_module_claim_bdev(base->bdev, base->desc, base->module); if (rc) { SPDK_ERRLOG("could not claim bdev %s\n", spdk_bdev_get_name(base->bdev)); - free(part->bdev.name); + free(part->internal.bdev.name); return -1; } base->claimed = true; @@ -333,7 +357,7 @@ spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base spdk_io_device_register(part, spdk_bdev_part_channel_create_cb, spdk_bdev_part_channel_destroy_cb, base->channel_size); - spdk_vbdev_register(&part->bdev, &base->bdev, 1); + spdk_vbdev_register(&part->internal.bdev, &base->bdev, 1); TAILQ_INSERT_TAIL(base->tailq, part, tailq); return 0; diff --git a/lib/bdev/split/vbdev_split.c b/lib/bdev/split/vbdev_split.c index b676ec3ee..ef6f2a317 100644 --- a/lib/bdev/split/vbdev_split.c +++ b/lib/bdev/split/vbdev_split.c @@ -121,7 +121,8 @@ static int vbdev_split_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) { struct spdk_bdev_part *part = ctx; - struct spdk_bdev *split_base_bdev = spdk_bdev_part_base_get_bdev(part->base); + struct spdk_bdev *split_base_bdev = spdk_bdev_part_get_base_bdev(part); + uint64_t offset_blocks = spdk_bdev_part_get_offset_blocks(part); spdk_json_write_name(w, "split"); spdk_json_write_object_begin(w); @@ -129,7 +130,7 @@ vbdev_split_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) spdk_json_write_name(w, "base_bdev"); spdk_json_write_string(w, spdk_bdev_get_name(split_base_bdev)); spdk_json_write_name(w, "offset_blocks"); - spdk_json_write_uint64(w, part->offset_blocks); + spdk_json_write_uint64(w, offset_blocks); spdk_json_write_object_end(w);