diff --git a/lib/blob/Makefile b/lib/blob/Makefile index fbaf61918..996155bfb 100644 --- a/lib/blob/Makefile +++ b/lib/blob/Makefile @@ -34,7 +34,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk -C_SRCS = blobstore.c request.c zeroes.c +C_SRCS = blobstore.c request.c zeroes.c blob_bs_dev.c LIBNAME = blob DIRS-y += bdev diff --git a/lib/blob/blob_bs_dev.c b/lib/blob/blob_bs_dev.c new file mode 100644 index 000000000..310c04801 --- /dev/null +++ b/lib/blob/blob_bs_dev.c @@ -0,0 +1,150 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" +#include "spdk/blob.h" +#include "spdk/log.h" +#include "blobstore.h" + +static void +blob_bs_dev_write(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload, + uint64_t lba, uint32_t lba_count, + struct spdk_bs_dev_cb_args *cb_args) +{ + cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM); + assert(false); +} + +static void +blob_bs_dev_writev(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, + struct iovec *iov, int iovcnt, + uint64_t lba, uint32_t lba_count, + struct spdk_bs_dev_cb_args *cb_args) +{ + cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM); + assert(false); +} + +static void +blob_bs_dev_write_zeroes(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, + uint64_t lba, uint32_t lba_count, + struct spdk_bs_dev_cb_args *cb_args) +{ + cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM); + assert(false); +} + +static void +blob_bs_dev_unmap(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, + uint64_t lba, uint32_t lba_count, + struct spdk_bs_dev_cb_args *cb_args) +{ + cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM); + assert(false); +} + +static void +blob_bs_dev_read_cpl(void *cb_arg, int bserrno) +{ + struct spdk_bs_dev_cb_args *cb_args = (struct spdk_bs_dev_cb_args *)cb_arg; + + cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, bserrno); +} + +static inline void +blob_bs_dev_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload, + uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args) +{ + struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev; + + spdk_bs_io_read_blob(b->blob, channel, payload, lba, lba_count, + blob_bs_dev_read_cpl, cb_args); +} + +static inline void +blob_bs_dev_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, + struct iovec *iov, int iovcnt, + uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args) +{ + struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev; + + spdk_bs_io_readv_blob(b->blob, channel, iov, iovcnt, lba, lba_count, + blob_bs_dev_read_cpl, cb_args); +} + +static void +blob_bs_dev_destroy_cpl(void *cb_arg, int bserrno) +{ + struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)cb_arg; + + if (bserrno != 0) { + SPDK_ERRLOG("Error on blob_bs_dev destroy: %d", bserrno); + } + free(b); +} + +static void +blob_bs_dev_destroy(struct spdk_bs_dev *bs_dev) +{ + struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)bs_dev; + + spdk_blob_close(b->blob, blob_bs_dev_destroy_cpl, b); +} + + +struct spdk_bs_dev * +spdk_bs_create_blob_bs_dev(struct spdk_blob *blob) +{ + struct spdk_blob_bs_dev *b; + + b = calloc(1, sizeof(*b)); + if (b == NULL) { + return NULL; + } + /* snapshot blob */ + b->bs_dev.blockcnt = __blob_to_data(blob)->active.num_clusters * + __blob_to_data(blob)->bs->pages_per_cluster; + b->bs_dev.blocklen = SPDK_BS_PAGE_SIZE; + b->bs_dev.create_channel = NULL; + b->bs_dev.destroy_channel = NULL; + b->bs_dev.destroy = blob_bs_dev_destroy; + b->bs_dev.write = blob_bs_dev_write; + b->bs_dev.writev = blob_bs_dev_writev; + b->bs_dev.read = blob_bs_dev_read; + b->bs_dev.readv = blob_bs_dev_readv; + b->bs_dev.write_zeroes = blob_bs_dev_write_zeroes; + b->bs_dev.unmap = blob_bs_dev_unmap; + b->blob = blob; + + return &b->bs_dev; +} diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 156e507ef..346a3d61f 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -206,6 +206,10 @@ _spdk_blob_free(struct spdk_blob *blob) _spdk_xattrs_free(&blob->xattrs); _spdk_xattrs_free(&blob->xattrs_internal); + if (blob->back_bs_dev) { + blob->back_bs_dev->destroy(blob->back_bs_dev); + } + free(blob); } @@ -749,6 +753,7 @@ struct spdk_blob_load_ctx { struct spdk_blob_md_page *pages; uint32_t num_pages; + spdk_bs_sequence_t *seq; spdk_bs_sequence_cpl cb_fn; void *cb_arg; @@ -767,12 +772,57 @@ _spdk_blob_md_page_calc_crc(void *page) } +static void +_spdk_blob_load_final(void *cb_arg, int bserrno) +{ + struct spdk_blob_load_ctx *ctx = cb_arg; + struct spdk_blob_data *blob = ctx->blob; + + _spdk_blob_mark_clean(blob); + + ctx->cb_fn(ctx->seq, ctx->cb_arg, bserrno); + + /* Free the memory */ + spdk_dma_free(ctx->pages); + free(ctx); +} + +static void +_spdk_blob_load_snapshot_cpl(void *cb_arg, struct spdk_blob *snapshot, int bserrno) +{ + struct spdk_blob_load_ctx *ctx = cb_arg; + struct spdk_blob_data *blob = ctx->blob; + + if (bserrno != 0) { + goto error; + } + + blob->back_bs_dev = spdk_bs_create_blob_bs_dev(snapshot); + + if (blob->back_bs_dev == NULL) { + bserrno = -ENOMEM; + goto error; + } + + _spdk_blob_load_final(ctx, bserrno); + return; + +error: + SPDK_ERRLOG("Snapshot fail\n"); + _spdk_blob_free(blob); + ctx->cb_fn(ctx->seq, NULL, bserrno); + spdk_dma_free(ctx->pages); + free(ctx); +} + static void _spdk_blob_load_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) { struct spdk_blob_load_ctx *ctx = cb_arg; struct spdk_blob *blob = ctx->blob; struct spdk_blob_md_page *page; + const void *value; + size_t len; int rc; uint32_t crc; @@ -820,18 +870,32 @@ _spdk_blob_load_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) free(ctx); return; } + ctx->seq = seq; - if (spdk_blob_is_thin_provisioned(blob) == true) { - blob->back_bs_dev = spdk_bs_create_zeroes_dev(); + + if (spdk_blob_is_thin_provisioned(blob)) { + rc = _spdk_blob_get_xattr_value(blob, BLOB_SNAPSHOT, &value, &len, true); + if (rc == 0) { + if (len != sizeof(spdk_blob_id)) { + _spdk_blob_free(blob); + ctx->cb_fn(seq, NULL, -EINVAL); + spdk_dma_free(ctx->pages); + free(ctx); + return; + } + /* open snapshot blob and continue in the callback function */ + spdk_bs_open_blob(blob->bs, *(spdk_blob_id *)value, + _spdk_blob_load_snapshot_cpl, ctx); + return; + } else { + /* add zeroes_dev for thin provisioned blob */ + blob->back_bs_dev = spdk_bs_create_zeroes_dev(); + } + } else { + /* standard blob */ + blob->back_bs_dev = NULL; } - - _spdk_blob_mark_clean(blob); - - ctx->cb_fn(seq, ctx->cb_arg, rc); - - /* Free the memory */ - spdk_dma_free(ctx->pages); - free(ctx); + _spdk_blob_load_final(ctx, bserrno); } /* Load a blob from disk given a blobid */ diff --git a/lib/blob/blobstore.h b/lib/blob/blobstore.h index 09a668765..aec14dbf4 100644 --- a/lib/blob/blobstore.h +++ b/lib/blob/blobstore.h @@ -195,6 +195,15 @@ enum spdk_blob_op_type { SPDK_BLOB_READV, }; +/* back bs_dev */ + +#define BLOB_SNAPSHOT "SNAP" + +struct spdk_blob_bs_dev { + struct spdk_bs_dev bs_dev; + struct spdk_blob *blob; +}; + /* On-Disk Data Structures * * The following data structures exist on disk. @@ -329,6 +338,7 @@ SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_super_block) == 0x1000, "Invalid super #pragma pack(pop) struct spdk_bs_dev *spdk_bs_create_zeroes_dev(void); +struct spdk_bs_dev *spdk_bs_create_blob_bs_dev(struct spdk_blob *blob); /* Unit Conversions * diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index 7c7725c6f..2fcb9934e 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -41,6 +41,7 @@ #include "blob/blobstore.c" #include "blob/request.c" #include "blob/zeroes.c" +#include "blob/blob_bs_dev.c" struct spdk_blob_store *g_bs; spdk_blob_id g_blobid;