diff options
author | Alexei Naberezhnov <anaberezhnov@fb.com> | 2018-03-28 02:54:16 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-02-06 19:30:16 +0300 |
commit | e7f11c55ad6048fa5a8b0bc412b44eeb455822f9 (patch) | |
tree | c954910817327e94efe59fcd5b7bd0a3a772623f /drivers/md/raid5.c | |
parent | 5b3109eb89dd800354481b76a1b856d303d3d2a8 (diff) | |
download | linux-e7f11c55ad6048fa5a8b0bc412b44eeb455822f9.tar.xz |
md/raid5: fix 'out of memory' during raid cache recovery
commit 483cbbeddd5fe2c80fd4141ff0748fa06c4ff146 upstream.
This fixes the case when md array assembly fails because of raid cache recovery
unable to allocate a stripe, despite attempts to replay stripes and increase
cache size. This happens because stripes released by r5c_recovery_replay_stripes
and raid5_set_cache_size don't become available for allocation immediately.
Released stripes first are placed on conf->released_stripes list and require
md thread to merge them on conf->inactive_list before they can be allocated.
Patch allows final allocation attempt during cache recovery to wait for
new stripes to become availabe for allocation.
Cc: linux-raid@vger.kernel.org
Cc: Shaohua Li <shli@kernel.org>
Cc: linux-stable <stable@vger.kernel.org> # 4.10+
Fixes: b4c625c67362 ("md/r5cache: r5cache recovery: part 1")
Signed-off-by: Alexei Naberezhnov <anaberezhnov@fb.com>
Signed-off-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index e4e98f47865d..45a3551d3afd 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -6357,6 +6357,7 @@ raid5_show_stripe_cache_size(struct mddev *mddev, char *page) int raid5_set_cache_size(struct mddev *mddev, int size) { + int result = 0; struct r5conf *conf = mddev->private; if (size <= 16 || size > 32768) @@ -6373,11 +6374,14 @@ raid5_set_cache_size(struct mddev *mddev, int size) mutex_lock(&conf->cache_size_mutex); while (size > conf->max_nr_stripes) - if (!grow_one_stripe(conf, GFP_KERNEL)) + if (!grow_one_stripe(conf, GFP_KERNEL)) { + conf->min_nr_stripes = conf->max_nr_stripes; + result = -ENOMEM; break; + } mutex_unlock(&conf->cache_size_mutex); - return 0; + return result; } EXPORT_SYMBOL(raid5_set_cache_size); |