staging: lustre: obdclass: guarantee all keys filled
authorHongchao Zhang <hongchao.zhang@intel.com>
Wed, 2 May 2018 18:21:47 +0000 (14:21 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 7 May 2018 01:47:09 +0000 (18:47 -0700)
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
version is equal to the current key_set_version.

In lu_context_refill, the key_set_version should be protected
before comparing it to version stored in the lu_context.

Signed-off-by: Hongchao Zhang <hongchao.zhang@intel.com>
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8346
Reviewed-on: https://review.whamcloud.com/26099
Reviewed-on: https://review.whamcloud.com/27448
Reviewed-on: https://review.whamcloud.com/27994
Reviewed-by: Patrick Farrell <paf@cray.com>
Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com>
Reviewed-by: Mike Pershin <mike.pershin@intel.com>
Reviewed-by: Fan Yong <fan.yong@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
Signed-off-by: James Simmons <jsimmons@infradead.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/lustre/lustre/obdclass/lu_object.c

index 96f21a5dafc418c55e1d5d957419665394e71a99..be10104f8ba6b114aec02ae3c24566d482aaf135 100644 (file)
@@ -1396,8 +1396,8 @@ void lu_context_key_degister(struct lu_context_key *key)
 
        lu_context_key_quiesce(key);
 
-       ++key_set_version;
        write_lock(&lu_keys_guard);
+       ++key_set_version;
        key_fini(&lu_shrink_env.le_ctx, key->lct_index);
 
        /**
@@ -1556,15 +1556,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)
 {
+       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)
@@ -1583,6 +1586,7 @@ static void keys_fini(struct lu_context *ctx)
 
 static int keys_fill(struct lu_context *ctx)
 {
+       unsigned int pre_version;
        unsigned int i;
 
        /*
@@ -1596,8 +1600,10 @@ 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);
 
+refill:
        LINVRNT(ctx->lc_value);
        for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) {
                struct lu_context_key *key;
@@ -1638,9 +1644,17 @@ static int keys_fill(struct lu_context *ctx)
                        if (key->lct_exit)
                                ctx->lc_tags |= LCT_HAS_EXIT;
                }
-               ctx->lc_version = key_set_version;
        }
+
+       read_lock(&lu_keys_guard);
+       if (pre_version != key_set_version) {
+               pre_version = key_set_version;
+               read_unlock(&lu_keys_guard);
+               goto refill;
+       }
+       ctx->lc_version = key_set_version;
        atomic_dec(&lu_key_initing_cnt);
+       read_unlock(&lu_keys_guard);
        return 0;
 }
 
@@ -1749,7 +1763,14 @@ EXPORT_SYMBOL(lu_context_exit);
  */
 int lu_context_refill(struct lu_context *ctx)
 {
-       return likely(ctx->lc_version == key_set_version) ? 0 : keys_fill(ctx);
+       read_lock(&lu_keys_guard);
+       if (likely(ctx->lc_version == key_set_version)) {
+               read_unlock(&lu_keys_guard);
+               return 0;
+       }
+
+       read_unlock(&lu_keys_guard);
+       return keys_fill(ctx);
 }
 
 /**