Commit ceaa0c7f authored by Tomasz Zawadzki's avatar Tomasz Zawadzki
Browse files

lib/blob: complete multiple persists



When blob persist starts, there can already be multiple
of such requests pending. It is possible to complete
a set of persists at once, if blob state after their
execution would be the same. This is the case when
persists are already pending when a particular persist
request is started.

This patch implements such mechanism by introducing
persists_to_complete queue, containing entries that
were previously queued up before starting the current
persist request. If there are any entries in this queue,
further requests are put into pending_persists.

When first request from persists_to_complete is persisted,
completions are issued for all requests on that queue at once.
If at that point there are any new entries on pending_persists,
all of them are put into persists_to_complete. Persist process is started
again with the first request from that queue.

Signed-off-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I10063e55d6f821b1863de016d3148da6a719a422
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7643


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent 119158cd
Loading
Loading
Loading
Loading
+21 −12
Original line number Diff line number Diff line
@@ -300,6 +300,7 @@ blob_alloc(struct spdk_blob_store *bs, spdk_blob_id id)
	TAILQ_INIT(&blob->xattrs);
	TAILQ_INIT(&blob->xattrs_internal);
	TAILQ_INIT(&blob->pending_persists);
	TAILQ_INIT(&blob->persists_to_complete);

	return blob;
}
@@ -322,6 +323,7 @@ blob_free(struct spdk_blob *blob)
{
	assert(blob != NULL);
	assert(TAILQ_EMPTY(&blob->pending_persists));
	assert(TAILQ_EMPTY(&blob->persists_to_complete));

	free(blob->active.extent_pages);
	free(blob->clean.extent_pages);
@@ -1635,25 +1637,32 @@ blob_persist_complete_cb(void *arg)
static void
blob_persist_complete(spdk_bs_sequence_t *seq, struct spdk_blob_persist_ctx *ctx, int bserrno)
{
	struct spdk_blob_persist_ctx	*next_persist;
	struct spdk_blob_persist_ctx	*next_persist, *tmp;
	struct spdk_blob		*blob = ctx->blob;

	if (bserrno == 0) {
		blob_mark_clean(blob);
	}

	assert(ctx == TAILQ_FIRST(&blob->pending_persists));
	TAILQ_REMOVE(&blob->pending_persists, ctx, link);
	assert(ctx == TAILQ_FIRST(&blob->persists_to_complete));

	next_persist = TAILQ_FIRST(&blob->pending_persists);
	/* Complete all persists that were pending when the current persist started */
	TAILQ_FOREACH_SAFE(next_persist, &blob->persists_to_complete, link, tmp) {
		TAILQ_REMOVE(&blob->persists_to_complete, next_persist, link);
		spdk_thread_send_msg(spdk_get_thread(), blob_persist_complete_cb, next_persist);
	}

	spdk_thread_send_msg(spdk_get_thread(), blob_persist_complete_cb, ctx);
	if (TAILQ_EMPTY(&blob->pending_persists)) {
		return;
	}

	/* Queue up all pending persists for completion and start blob persist with first one */
	TAILQ_SWAP(&blob->persists_to_complete, &blob->pending_persists, spdk_blob_persist_ctx, link);
	next_persist = TAILQ_FIRST(&blob->persists_to_complete);

	if (next_persist != NULL) {
	blob->state = SPDK_BLOB_STATE_DIRTY;
	blob_persist_check_dirty(next_persist);
}
}

static void
blob_persist_clear_extents_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno)
@@ -2272,7 +2281,7 @@ blob_persist(spdk_bs_sequence_t *seq, struct spdk_blob *blob,

	blob_verify_md_op(blob);

	if (blob->state == SPDK_BLOB_STATE_CLEAN && TAILQ_EMPTY(&blob->pending_persists)) {
	if (blob->state == SPDK_BLOB_STATE_CLEAN && TAILQ_EMPTY(&blob->persists_to_complete)) {
		cb_fn(seq, cb_arg, 0);
		return;
	}
@@ -2289,11 +2298,11 @@ blob_persist(spdk_bs_sequence_t *seq, struct spdk_blob *blob,

	/* Multiple blob persists can affect one another, via blob->state or
	 * blob mutable data changes. To prevent it, queue up the persists. */
	if (!TAILQ_EMPTY(&blob->pending_persists)) {
	if (!TAILQ_EMPTY(&blob->persists_to_complete)) {
		TAILQ_INSERT_TAIL(&blob->pending_persists, ctx, link);
		return;
	}
	TAILQ_INSERT_HEAD(&blob->pending_persists, ctx, link);
	TAILQ_INSERT_HEAD(&blob->persists_to_complete, ctx, link);

	blob_persist_check_dirty(ctx);
}
+1 −0
Original line number Diff line number Diff line
@@ -168,6 +168,7 @@ struct spdk_blob {

	/* A list of pending metadata pending_persists */
	TAILQ_HEAD(, spdk_blob_persist_ctx) pending_persists;
	TAILQ_HEAD(, spdk_blob_persist_ctx) persists_to_complete;

	/* Number of data clusters retrived from extent table,
	 * that many have to be read from extent pages. */