From e58f8d609a81576eaf5bc9d0fa53bef274a01bfc Mon Sep 17 00:00:00 2001 From: Hongchao Zhang Date: Sun, 16 Apr 2017 04:04:48 +0800 Subject: [PATCH] LU-8346 obdclass: guarantee all keys filled In keys_fill, the key_set_version could be changed after the keys are filled, then the keys in this context won't be refilled by the following lu_context_refill for its verion is equal to the current key_set_verion. Change-Id: Ibaa49ec6e95ffee902cfa98f18ac9e66f2127bf1 Signed-off-by: Hongchao Zhang Reviewed-on: https://review.whamcloud.com/26099 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Mike Pershin Reviewed-by: Fan Yong Reviewed-by: Oleg Drokin --- lustre/obdclass/lu_object.c | 74 +++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/lustre/obdclass/lu_object.c b/lustre/obdclass/lu_object.c index 1be5a9d..cc89029 100644 --- a/lustre/obdclass/lu_object.c +++ b/lustre/obdclass/lu_object.c @@ -1615,15 +1615,18 @@ void lu_context_key_quiesce(struct lu_context_key *key) list_for_each_entry(ctx, &lu_context_remembered, lc_remember) key_fini(ctx, key->lct_index); - write_unlock(&lu_keys_guard); + ++key_set_version; + write_unlock(&lu_keys_guard); } } void lu_context_key_revive(struct lu_context_key *key) { - key->lct_tags &= ~LCT_QUIESCENT; - ++key_set_version; + write_lock(&lu_keys_guard); + key->lct_tags &= ~LCT_QUIESCENT; + ++key_set_version; + write_unlock(&lu_keys_guard); } static void keys_fini(struct lu_context *ctx) @@ -1643,6 +1646,7 @@ static void keys_fini(struct lu_context *ctx) static int keys_fill(struct lu_context *ctx) { unsigned int i; + unsigned pre_version; /* * A serialisation with lu_context_key_quiesce() is needed, but some @@ -1655,24 +1659,26 @@ static int keys_fill(struct lu_context *ctx) */ read_lock(&lu_keys_guard); atomic_inc(&lu_key_initing_cnt); + pre_version = key_set_version; read_unlock(&lu_keys_guard); - LINVRNT(ctx->lc_value != NULL); - for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) { - struct lu_context_key *key; +refill: + LINVRNT(ctx->lc_value != NULL); + for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) { + struct lu_context_key *key; - key = lu_keys[i]; - if (ctx->lc_value[i] == NULL && key != NULL && - (key->lct_tags & ctx->lc_tags) && - /* - * Don't create values for a LCT_QUIESCENT key, as this - * will pin module owning a key. - */ - !(key->lct_tags & LCT_QUIESCENT)) { - void *value; - - LINVRNT(key->lct_init != NULL); - LINVRNT(key->lct_index == i); + key = lu_keys[i]; + if (ctx->lc_value[i] == NULL && key != NULL && + (key->lct_tags & ctx->lc_tags) && + /* + * Don't create values for a LCT_QUIESCENT key, as this + * will pin module owning a key. + */ + !(key->lct_tags & LCT_QUIESCENT)) { + void *value; + + LINVRNT(key->lct_init != NULL); + LINVRNT(key->lct_index == i); LASSERT(key->lct_owner != NULL); if (!(ctx->lc_tags & LCT_NOREF) && @@ -1689,19 +1695,27 @@ static int keys_fill(struct lu_context *ctx) lu_ref_add_atomic(&key->lct_reference, "ctx", ctx); atomic_inc(&key->lct_used); - /* - * This is the only place in the code, where an - * element of ctx->lc_value[] array is set to non-NULL - * value. - */ - ctx->lc_value[i] = value; - if (key->lct_exit != NULL) - ctx->lc_tags |= LCT_HAS_EXIT; - } - ctx->lc_version = key_set_version; - } + /* + * This is the only place in the code, where an + * element of ctx->lc_value[] array is set to non-NULL + * value. + */ + ctx->lc_value[i] = value; + if (key->lct_exit != NULL) + ctx->lc_tags |= LCT_HAS_EXIT; + } + } + + read_lock(&lu_keys_guard); + if (pre_version != key_set_version) { + pre_version = key_set_version; + read_unlock(&lu_keys_guard); + goto refill; + } + atomic_dec(&lu_key_initing_cnt); - return 0; + read_unlock(&lu_keys_guard); + return 0; } static int keys_init(struct lu_context *ctx) -- 1.8.3.1