|
|
@@ -1935,12 +1935,14 @@ out:
|
|
|
}
|
|
|
|
|
|
static struct stripe_head *
|
|
|
-r5c_recovery_alloc_stripe(struct r5conf *conf,
|
|
|
- sector_t stripe_sect)
|
|
|
+r5c_recovery_alloc_stripe(
|
|
|
+ struct r5conf *conf,
|
|
|
+ sector_t stripe_sect,
|
|
|
+ int noblock)
|
|
|
{
|
|
|
struct stripe_head *sh;
|
|
|
|
|
|
- sh = raid5_get_active_stripe(conf, stripe_sect, 0, 1, 0);
|
|
|
+ sh = raid5_get_active_stripe(conf, stripe_sect, 0, noblock, 0);
|
|
|
if (!sh)
|
|
|
return NULL; /* no more stripe available */
|
|
|
|
|
|
@@ -2150,7 +2152,7 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
|
|
|
stripe_sect);
|
|
|
|
|
|
if (!sh) {
|
|
|
- sh = r5c_recovery_alloc_stripe(conf, stripe_sect);
|
|
|
+ sh = r5c_recovery_alloc_stripe(conf, stripe_sect, 1);
|
|
|
/*
|
|
|
* cannot get stripe from raid5_get_active_stripe
|
|
|
* try replay some stripes
|
|
|
@@ -2159,20 +2161,29 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
|
|
|
r5c_recovery_replay_stripes(
|
|
|
cached_stripe_list, ctx);
|
|
|
sh = r5c_recovery_alloc_stripe(
|
|
|
- conf, stripe_sect);
|
|
|
+ conf, stripe_sect, 1);
|
|
|
}
|
|
|
if (!sh) {
|
|
|
+ int new_size = conf->min_nr_stripes * 2;
|
|
|
pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n",
|
|
|
mdname(mddev),
|
|
|
- conf->min_nr_stripes * 2);
|
|
|
- raid5_set_cache_size(mddev,
|
|
|
- conf->min_nr_stripes * 2);
|
|
|
- sh = r5c_recovery_alloc_stripe(conf,
|
|
|
- stripe_sect);
|
|
|
+ new_size);
|
|
|
+ ret = raid5_set_cache_size(mddev, new_size);
|
|
|
+ if (conf->min_nr_stripes <= new_size / 2) {
|
|
|
+ pr_err("md/raid:%s: Cannot increase cache size, ret=%d, new_size=%d, min_nr_stripes=%d, max_nr_stripes=%d\n",
|
|
|
+ mdname(mddev),
|
|
|
+ ret,
|
|
|
+ new_size,
|
|
|
+ conf->min_nr_stripes,
|
|
|
+ conf->max_nr_stripes);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ sh = r5c_recovery_alloc_stripe(
|
|
|
+ conf, stripe_sect, 0);
|
|
|
}
|
|
|
if (!sh) {
|
|
|
pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n",
|
|
|
- mdname(mddev));
|
|
|
+ mdname(mddev));
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
list_add_tail(&sh->lru, cached_stripe_list);
|