blob: allow inserting cluster from non metadata thread

This will be needed for thin provisioning, since a write
I/O may result in needing to insert a cluster into the
blob and that write I/O may not have been performed
on the metadata thread.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Change-Id: I84b0cb6e7af87b1f9c6cab4e2c24fa26b12e2c06
Reviewed-on: https://review.gerrithub.io/396737
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Jim Harris 2018-01-26 14:48:19 -07:00 committed by Daniel Verkamp
parent 71dba27cab
commit 98d28d604d
2 changed files with 152 additions and 2 deletions

View File

@ -50,6 +50,8 @@
static int spdk_bs_register_md_thread(struct spdk_blob_store *bs); static int spdk_bs_register_md_thread(struct spdk_blob_store *bs);
static int spdk_bs_unregister_md_thread(struct spdk_blob_store *bs); static int spdk_bs_unregister_md_thread(struct spdk_blob_store *bs);
static void _spdk_blob_close_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno); static void _spdk_blob_close_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno);
void _spdk_blob_insert_cluster_on_md_thread(struct spdk_blob_data *blob, uint32_t cluster_num,
uint64_t cluster, spdk_blob_op_complete cb_fn, void *cb_arg);
static inline size_t static inline size_t
divide_round_up(size_t num, size_t divisor) divide_round_up(size_t num, size_t divisor)
@ -3214,6 +3216,71 @@ spdk_blob_sync_md(struct spdk_blob *_blob, spdk_blob_op_complete cb_fn, void *cb
/* END spdk_blob_sync_md */ /* END spdk_blob_sync_md */
struct spdk_blob_insert_cluster_ctx {
struct spdk_thread *thread;
struct spdk_blob_data *blob;
uint32_t cluster_num; /* cluster index in blob */
uint32_t cluster; /* cluster on disk */
int rc;
spdk_blob_op_complete cb_fn;
void *cb_arg;
};
static void
_spdk_blob_insert_cluster_msg_cpl(void *arg)
{
struct spdk_blob_insert_cluster_ctx *ctx = arg;
ctx->cb_fn(ctx->cb_arg, ctx->rc);
free(ctx);
}
static void
_spdk_blob_insert_cluster_msg_cb(void *arg, int bserrno)
{
struct spdk_blob_insert_cluster_ctx *ctx = arg;
ctx->rc = bserrno;
spdk_thread_send_msg(ctx->thread, _spdk_blob_insert_cluster_msg_cpl, ctx);
}
static void
_spdk_blob_insert_cluster_msg(void *arg)
{
struct spdk_blob_insert_cluster_ctx *ctx = arg;
ctx->rc = _spdk_blob_insert_cluster(ctx->blob, ctx->cluster_num, ctx->cluster);
if (ctx->rc != 0) {
spdk_thread_send_msg(ctx->thread, _spdk_blob_insert_cluster_msg_cpl, ctx);
return;
}
ctx->blob->state = SPDK_BLOB_STATE_DIRTY;
_spdk_blob_sync_md(ctx->blob, _spdk_blob_insert_cluster_msg_cb, ctx);
}
void
_spdk_blob_insert_cluster_on_md_thread(struct spdk_blob_data *blob, uint32_t cluster_num,
uint64_t cluster, spdk_blob_op_complete cb_fn, void *cb_arg)
{
struct spdk_blob_insert_cluster_ctx *ctx;
ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL) {
cb_fn(cb_arg, -ENOMEM);
return;
}
ctx->thread = spdk_get_thread();
ctx->blob = blob;
ctx->cluster_num = cluster_num;
ctx->cluster = cluster;
ctx->cb_fn = cb_fn;
ctx->cb_arg = cb_arg;
spdk_thread_send_msg(blob->bs->md_thread, _spdk_blob_insert_cluster_msg, ctx);
}
/* START spdk_blob_close */ /* START spdk_blob_close */
static void static void

View File

@ -2679,7 +2679,7 @@ blob_thin_prov_alloc(void)
spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
CU_ASSERT(g_bserrno == 0); CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blob != NULL); SPDK_CU_ASSERT_FATAL(g_blob != NULL);
blob = g_blob; blob = g_blob;
blob_data = __blob_to_data(blob); blob_data = __blob_to_data(blob);
@ -2698,6 +2698,88 @@ blob_thin_prov_alloc(void)
g_bs = NULL; g_bs = NULL;
} }
static void
blob_insert_cluster_msg(void)
{
struct spdk_blob_store *bs;
struct spdk_bs_dev *dev;
struct spdk_blob *blob;
struct spdk_blob_data *blob_data;
struct spdk_blob_opts opts;
spdk_blob_id blobid;
uint64_t free_clusters;
dev = init_dev();
spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
bs = g_bs;
free_clusters = spdk_bs_free_cluster_count(bs);
/* Set blob as thin provisioned */
spdk_blob_opts_init(&opts);
opts.thin_provision = true;
opts.num_clusters = 4;
spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs));
blobid = g_blobid;
spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
blob = g_blob;
blob_data = __blob_to_data(blob);
CU_ASSERT(blob_data->active.num_clusters == 4);
CU_ASSERT(spdk_blob_get_num_clusters(blob) == 4);
CU_ASSERT(blob_data->active.clusters[1] == 0);
_spdk_bs_claim_cluster(bs, 0xF);
_spdk_blob_insert_cluster_on_md_thread(blob_data, 1, 0xF, blob_op_complete, NULL);
CU_ASSERT(blob_data->active.clusters[1] != 0);
spdk_blob_close(blob, blob_op_complete, NULL);
CU_ASSERT(g_bserrno == 0);
/* Unload the blob store */
spdk_bs_unload(g_bs, bs_op_complete, NULL);
CU_ASSERT(g_bserrno == 0);
g_bs = NULL;
g_blob = NULL;
g_blobid = 0;
/* Load an existing blob store */
dev = init_dev();
spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL);
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
bs = g_bs;
spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL);
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blob != NULL);
blob = g_blob;
blob_data = __blob_to_data(blob);
CU_ASSERT(blob_data->active.clusters[1] != 0);
spdk_blob_close(blob, blob_op_complete, NULL);
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
CU_ASSERT(g_bserrno == 0);
spdk_bs_unload(g_bs, bs_op_complete, NULL);
CU_ASSERT(g_bserrno == 0);
g_bs = NULL;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
CU_pSuite suite = NULL; CU_pSuite suite = NULL;
@ -2746,7 +2828,8 @@ int main(int argc, char **argv)
CU_add_test(suite, "blob_flags", blob_flags) == NULL || CU_add_test(suite, "blob_flags", blob_flags) == NULL ||
CU_add_test(suite, "bs_version", bs_version) == NULL || CU_add_test(suite, "bs_version", bs_version) == NULL ||
CU_add_test(suite, "blob_set_xattrs", blob_set_xattrs) == NULL || CU_add_test(suite, "blob_set_xattrs", blob_set_xattrs) == NULL ||
CU_add_test(suite, "blob_thin_prov_alloc", blob_thin_prov_alloc) == NULL CU_add_test(suite, "blob_thin_prov_alloc", blob_thin_prov_alloc) == NULL ||
CU_add_test(suite, "blob_insert_cluster_msg", blob_insert_cluster_msg) == NULL
) { ) {
CU_cleanup_registry(); CU_cleanup_registry();
return CU_get_error(); return CU_get_error();