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: Tomasz Zawadzki <tomasz.zawadzki@intel.com> Change-Id: I10063e55d6f821b1863de016d3148da6a719a422 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7643 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
parent
119158cda8
commit
ceaa0c7fa9
@ -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,24 +1637,31 @@ 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);
|
||||
|
||||
spdk_thread_send_msg(spdk_get_thread(), blob_persist_complete_cb, ctx);
|
||||
|
||||
if (next_persist != NULL) {
|
||||
blob->state = SPDK_BLOB_STATE_DIRTY;
|
||||
blob_persist_check_dirty(next_persist);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
blob->state = SPDK_BLOB_STATE_DIRTY;
|
||||
blob_persist_check_dirty(next_persist);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user