diff options
Diffstat (limited to 'drivers/md/raid5-cache.c')
| -rw-r--r-- | drivers/md/raid5-cache.c | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index ec3a5ef7fee0..cbbe6b6535be 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c | |||
| @@ -1935,12 +1935,14 @@ out: | |||
| 1935 | } | 1935 | } |
| 1936 | 1936 | ||
| 1937 | static struct stripe_head * | 1937 | static struct stripe_head * |
| 1938 | r5c_recovery_alloc_stripe(struct r5conf *conf, | 1938 | r5c_recovery_alloc_stripe( |
| 1939 | sector_t stripe_sect) | 1939 | struct r5conf *conf, |
| 1940 | sector_t stripe_sect, | ||
| 1941 | int noblock) | ||
| 1940 | { | 1942 | { |
| 1941 | struct stripe_head *sh; | 1943 | struct stripe_head *sh; |
| 1942 | 1944 | ||
| 1943 | sh = raid5_get_active_stripe(conf, stripe_sect, 0, 1, 0); | 1945 | sh = raid5_get_active_stripe(conf, stripe_sect, 0, noblock, 0); |
| 1944 | if (!sh) | 1946 | if (!sh) |
| 1945 | return NULL; /* no more stripe available */ | 1947 | return NULL; /* no more stripe available */ |
| 1946 | 1948 | ||
| @@ -2150,7 +2152,7 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log, | |||
| 2150 | stripe_sect); | 2152 | stripe_sect); |
| 2151 | 2153 | ||
| 2152 | if (!sh) { | 2154 | if (!sh) { |
| 2153 | sh = r5c_recovery_alloc_stripe(conf, stripe_sect); | 2155 | sh = r5c_recovery_alloc_stripe(conf, stripe_sect, 1); |
| 2154 | /* | 2156 | /* |
| 2155 | * cannot get stripe from raid5_get_active_stripe | 2157 | * cannot get stripe from raid5_get_active_stripe |
| 2156 | * try replay some stripes | 2158 | * try replay some stripes |
| @@ -2159,20 +2161,29 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log, | |||
| 2159 | r5c_recovery_replay_stripes( | 2161 | r5c_recovery_replay_stripes( |
| 2160 | cached_stripe_list, ctx); | 2162 | cached_stripe_list, ctx); |
| 2161 | sh = r5c_recovery_alloc_stripe( | 2163 | sh = r5c_recovery_alloc_stripe( |
| 2162 | conf, stripe_sect); | 2164 | conf, stripe_sect, 1); |
| 2163 | } | 2165 | } |
| 2164 | if (!sh) { | 2166 | if (!sh) { |
| 2167 | int new_size = conf->min_nr_stripes * 2; | ||
| 2165 | pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n", | 2168 | pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n", |
| 2166 | mdname(mddev), | 2169 | mdname(mddev), |
| 2167 | conf->min_nr_stripes * 2); | 2170 | new_size); |
| 2168 | raid5_set_cache_size(mddev, | 2171 | ret = raid5_set_cache_size(mddev, new_size); |
| 2169 | conf->min_nr_stripes * 2); | 2172 | if (conf->min_nr_stripes <= new_size / 2) { |
| 2170 | sh = r5c_recovery_alloc_stripe(conf, | 2173 | pr_err("md/raid:%s: Cannot increase cache size, ret=%d, new_size=%d, min_nr_stripes=%d, max_nr_stripes=%d\n", |
| 2171 | stripe_sect); | 2174 | mdname(mddev), |
| 2175 | ret, | ||
| 2176 | new_size, | ||
| 2177 | conf->min_nr_stripes, | ||
| 2178 | conf->max_nr_stripes); | ||
| 2179 | return -ENOMEM; | ||
| 2180 | } | ||
| 2181 | sh = r5c_recovery_alloc_stripe( | ||
| 2182 | conf, stripe_sect, 0); | ||
| 2172 | } | 2183 | } |
| 2173 | if (!sh) { | 2184 | if (!sh) { |
| 2174 | pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n", | 2185 | pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n", |
| 2175 | mdname(mddev)); | 2186 | mdname(mddev)); |
| 2176 | return -ENOMEM; | 2187 | return -ENOMEM; |
| 2177 | } | 2188 | } |
| 2178 | list_add_tail(&sh->lru, cached_stripe_list); | 2189 | list_add_tail(&sh->lru, cached_stripe_list); |
