]> git.karo-electronics.de Git - linux-beck.git/commitdiff
md/raid5-cache: release the stripe_head at the appropriate location
authorJackieLiu <liuyun01@kylinos.cn>
Mon, 28 Nov 2016 08:19:20 +0000 (16:19 +0800)
committerShaohua Li <shli@fb.com>
Tue, 29 Nov 2016 22:46:22 +0000 (14:46 -0800)
If we released the 'stripe_head' in r5c_recovery_flush_log,
ctx->cached_list will both release the data-parity stripes and
data-only stripes, which will become empty.
And we also need to use the data-only stripes in
r5c_recovery_rewrite_data_only_stripes, so we should wait util rewrite
data-only stripes is done before releasing them.

Reviewed-by: Zhengyuan Liu <liuzhengyuan@kylinos.cn>
Reviewed-by: Song Liu <songliubraving@fb.com>
Signed-off-by: JackieLiu <liuyun01@kylinos.cn>
Signed-off-by: Shaohua Li <shli@fb.com>
drivers/md/raid5-cache.c

index 5ef20c57731fea83240417f37722483de8cc232e..7b9149ef685ce1b09e73dded0db23d07d4c3d7b9 100644 (file)
@@ -1948,7 +1948,7 @@ static void r5c_recovery_load_one_stripe(struct r5l_log *log,
 static int r5c_recovery_flush_log(struct r5l_log *log,
                                  struct r5l_recovery_ctx *ctx)
 {
-       struct stripe_head *sh, *next;
+       struct stripe_head *sh;
        int ret = 0;
 
        /* scan through the log */
@@ -1977,11 +1977,9 @@ static int r5c_recovery_flush_log(struct r5l_log *log,
        r5c_recovery_replay_stripes(&ctx->cached_list, ctx);
 
        /* load data-only stripes to stripe cache */
-       list_for_each_entry_safe(sh, next, &ctx->cached_list, lru) {
+       list_for_each_entry(sh, &ctx->cached_list, lru) {
                WARN_ON(!test_bit(STRIPE_R5C_CACHING, &sh->state));
                r5c_recovery_load_one_stripe(log, sh);
-               list_del_init(&sh->lru);
-               raid5_release_stripe(sh);
                ctx->data_only_stripes++;
        }
 
@@ -2061,7 +2059,7 @@ static int
 r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log,
                                       struct r5l_recovery_ctx *ctx)
 {
-       struct stripe_head *sh;
+       struct stripe_head *sh, *next;
        struct mddev *mddev = log->rdev->mddev;
        struct page *page;
 
@@ -2073,7 +2071,7 @@ r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log,
        }
 
        ctx->seq += 10;
-       list_for_each_entry(sh, &ctx->cached_list, lru) {
+       list_for_each_entry_safe(sh, next, &ctx->cached_list, lru) {
                struct r5l_meta_block *mb;
                int i;
                int offset;
@@ -2119,6 +2117,9 @@ r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log,
                sh->log_start = ctx->pos;
                ctx->pos = write_pos;
                ctx->seq += 1;
+
+               list_del_init(&sh->lru);
+               raid5_release_stripe(sh);
        }
        __free_page(page);
        return 0;