diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-05-11 13:33:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-05-11 13:33:31 -0400 |
commit | c91aa67eede4cdee97844854bdf5b695ab26893e (patch) | |
tree | 19ce86611cb61f293b45f40e18449e5e4554f2af /drivers/md | |
parent | 030bbdbf4c833bc69f502eae58498bc5572db736 (diff) | |
parent | bb27051f9fd7643f05d8f0babce3337f0b9b3087 (diff) |
Merge tag 'md/4.1-rc3-fixes' of git://neil.brown.name/md
Pull md bugfixes from Neil Brown:
"A few fixes for md.
Most of these are related to the new "batched stripe writeout", but
there are a few others"
* tag 'md/4.1-rc3-fixes' of git://neil.brown.name/md:
md/raid5: fix handling of degraded stripes in batches.
md/raid5: fix allocation of 'scribble' array.
md/raid5: don't record new size if resize_stripes fails.
md/raid5: avoid reading parity blocks for full-stripe write to degraded array
md/raid5: more incorrect BUG_ON in handle_stripe_fill.
md/raid5: new alloc_stripe() to allocate an initialize a stripe.
md-raid0: conditional mddev->queue access to suit dm-raid
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid0.c | 5 | ||||
-rw-r--r-- | drivers/md/raid5.c | 123 |
2 files changed, 73 insertions, 55 deletions
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 2cb59a641cd2..6a68ef5246d4 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
@@ -188,8 +188,9 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) | |||
188 | } | 188 | } |
189 | dev[j] = rdev1; | 189 | dev[j] = rdev1; |
190 | 190 | ||
191 | disk_stack_limits(mddev->gendisk, rdev1->bdev, | 191 | if (mddev->queue) |
192 | rdev1->data_offset << 9); | 192 | disk_stack_limits(mddev->gendisk, rdev1->bdev, |
193 | rdev1->data_offset << 9); | ||
193 | 194 | ||
194 | if (rdev1->bdev->bd_disk->queue->merge_bvec_fn) | 195 | if (rdev1->bdev->bd_disk->queue->merge_bvec_fn) |
195 | conf->has_merge_bvec = 1; | 196 | conf->has_merge_bvec = 1; |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 77dfd720aaa0..1ba97fdc6df1 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -1078,9 +1078,6 @@ again: | |||
1078 | pr_debug("skip op %ld on disc %d for sector %llu\n", | 1078 | pr_debug("skip op %ld on disc %d for sector %llu\n", |
1079 | bi->bi_rw, i, (unsigned long long)sh->sector); | 1079 | bi->bi_rw, i, (unsigned long long)sh->sector); |
1080 | clear_bit(R5_LOCKED, &sh->dev[i].flags); | 1080 | clear_bit(R5_LOCKED, &sh->dev[i].flags); |
1081 | if (sh->batch_head) | ||
1082 | set_bit(STRIPE_BATCH_ERR, | ||
1083 | &sh->batch_head->state); | ||
1084 | set_bit(STRIPE_HANDLE, &sh->state); | 1081 | set_bit(STRIPE_HANDLE, &sh->state); |
1085 | } | 1082 | } |
1086 | 1083 | ||
@@ -1971,17 +1968,30 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request) | |||
1971 | put_cpu(); | 1968 | put_cpu(); |
1972 | } | 1969 | } |
1973 | 1970 | ||
1971 | static struct stripe_head *alloc_stripe(struct kmem_cache *sc, gfp_t gfp) | ||
1972 | { | ||
1973 | struct stripe_head *sh; | ||
1974 | |||
1975 | sh = kmem_cache_zalloc(sc, gfp); | ||
1976 | if (sh) { | ||
1977 | spin_lock_init(&sh->stripe_lock); | ||
1978 | spin_lock_init(&sh->batch_lock); | ||
1979 | INIT_LIST_HEAD(&sh->batch_list); | ||
1980 | INIT_LIST_HEAD(&sh->lru); | ||
1981 | atomic_set(&sh->count, 1); | ||
1982 | } | ||
1983 | return sh; | ||
1984 | } | ||
1974 | static int grow_one_stripe(struct r5conf *conf, gfp_t gfp) | 1985 | static int grow_one_stripe(struct r5conf *conf, gfp_t gfp) |
1975 | { | 1986 | { |
1976 | struct stripe_head *sh; | 1987 | struct stripe_head *sh; |
1977 | sh = kmem_cache_zalloc(conf->slab_cache, gfp); | 1988 | |
1989 | sh = alloc_stripe(conf->slab_cache, gfp); | ||
1978 | if (!sh) | 1990 | if (!sh) |
1979 | return 0; | 1991 | return 0; |
1980 | 1992 | ||
1981 | sh->raid_conf = conf; | 1993 | sh->raid_conf = conf; |
1982 | 1994 | ||
1983 | spin_lock_init(&sh->stripe_lock); | ||
1984 | |||
1985 | if (grow_buffers(sh, gfp)) { | 1995 | if (grow_buffers(sh, gfp)) { |
1986 | shrink_buffers(sh); | 1996 | shrink_buffers(sh); |
1987 | kmem_cache_free(conf->slab_cache, sh); | 1997 | kmem_cache_free(conf->slab_cache, sh); |
@@ -1990,13 +2000,8 @@ static int grow_one_stripe(struct r5conf *conf, gfp_t gfp) | |||
1990 | sh->hash_lock_index = | 2000 | sh->hash_lock_index = |
1991 | conf->max_nr_stripes % NR_STRIPE_HASH_LOCKS; | 2001 | conf->max_nr_stripes % NR_STRIPE_HASH_LOCKS; |
1992 | /* we just created an active stripe so... */ | 2002 | /* we just created an active stripe so... */ |
1993 | atomic_set(&sh->count, 1); | ||
1994 | atomic_inc(&conf->active_stripes); | 2003 | atomic_inc(&conf->active_stripes); |
1995 | INIT_LIST_HEAD(&sh->lru); | ||
1996 | 2004 | ||
1997 | spin_lock_init(&sh->batch_lock); | ||
1998 | INIT_LIST_HEAD(&sh->batch_list); | ||
1999 | sh->batch_head = NULL; | ||
2000 | release_stripe(sh); | 2005 | release_stripe(sh); |
2001 | conf->max_nr_stripes++; | 2006 | conf->max_nr_stripes++; |
2002 | return 1; | 2007 | return 1; |
@@ -2060,6 +2065,35 @@ static struct flex_array *scribble_alloc(int num, int cnt, gfp_t flags) | |||
2060 | return ret; | 2065 | return ret; |
2061 | } | 2066 | } |
2062 | 2067 | ||
2068 | static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors) | ||
2069 | { | ||
2070 | unsigned long cpu; | ||
2071 | int err = 0; | ||
2072 | |||
2073 | mddev_suspend(conf->mddev); | ||
2074 | get_online_cpus(); | ||
2075 | for_each_present_cpu(cpu) { | ||
2076 | struct raid5_percpu *percpu; | ||
2077 | struct flex_array *scribble; | ||
2078 | |||
2079 | percpu = per_cpu_ptr(conf->percpu, cpu); | ||
2080 | scribble = scribble_alloc(new_disks, | ||
2081 | new_sectors / STRIPE_SECTORS, | ||
2082 | GFP_NOIO); | ||
2083 | |||
2084 | if (scribble) { | ||
2085 | flex_array_free(percpu->scribble); | ||
2086 | percpu->scribble = scribble; | ||
2087 | } else { | ||
2088 | err = -ENOMEM; | ||
2089 | break; | ||
2090 | } | ||
2091 | } | ||
2092 | put_online_cpus(); | ||
2093 | mddev_resume(conf->mddev); | ||
2094 | return err; | ||
2095 | } | ||
2096 | |||
2063 | static int resize_stripes(struct r5conf *conf, int newsize) | 2097 | static int resize_stripes(struct r5conf *conf, int newsize) |
2064 | { | 2098 | { |
2065 | /* Make all the stripes able to hold 'newsize' devices. | 2099 | /* Make all the stripes able to hold 'newsize' devices. |
@@ -2088,7 +2122,6 @@ static int resize_stripes(struct r5conf *conf, int newsize) | |||
2088 | struct stripe_head *osh, *nsh; | 2122 | struct stripe_head *osh, *nsh; |
2089 | LIST_HEAD(newstripes); | 2123 | LIST_HEAD(newstripes); |
2090 | struct disk_info *ndisks; | 2124 | struct disk_info *ndisks; |
2091 | unsigned long cpu; | ||
2092 | int err; | 2125 | int err; |
2093 | struct kmem_cache *sc; | 2126 | struct kmem_cache *sc; |
2094 | int i; | 2127 | int i; |
@@ -2109,13 +2142,11 @@ static int resize_stripes(struct r5conf *conf, int newsize) | |||
2109 | return -ENOMEM; | 2142 | return -ENOMEM; |
2110 | 2143 | ||
2111 | for (i = conf->max_nr_stripes; i; i--) { | 2144 | for (i = conf->max_nr_stripes; i; i--) { |
2112 | nsh = kmem_cache_zalloc(sc, GFP_KERNEL); | 2145 | nsh = alloc_stripe(sc, GFP_KERNEL); |
2113 | if (!nsh) | 2146 | if (!nsh) |
2114 | break; | 2147 | break; |
2115 | 2148 | ||
2116 | nsh->raid_conf = conf; | 2149 | nsh->raid_conf = conf; |
2117 | spin_lock_init(&nsh->stripe_lock); | ||
2118 | |||
2119 | list_add(&nsh->lru, &newstripes); | 2150 | list_add(&nsh->lru, &newstripes); |
2120 | } | 2151 | } |
2121 | if (i) { | 2152 | if (i) { |
@@ -2142,13 +2173,11 @@ static int resize_stripes(struct r5conf *conf, int newsize) | |||
2142 | lock_device_hash_lock(conf, hash)); | 2173 | lock_device_hash_lock(conf, hash)); |
2143 | osh = get_free_stripe(conf, hash); | 2174 | osh = get_free_stripe(conf, hash); |
2144 | unlock_device_hash_lock(conf, hash); | 2175 | unlock_device_hash_lock(conf, hash); |
2145 | atomic_set(&nsh->count, 1); | 2176 | |
2146 | for(i=0; i<conf->pool_size; i++) { | 2177 | for(i=0; i<conf->pool_size; i++) { |
2147 | nsh->dev[i].page = osh->dev[i].page; | 2178 | nsh->dev[i].page = osh->dev[i].page; |
2148 | nsh->dev[i].orig_page = osh->dev[i].page; | 2179 | nsh->dev[i].orig_page = osh->dev[i].page; |
2149 | } | 2180 | } |
2150 | for( ; i<newsize; i++) | ||
2151 | nsh->dev[i].page = NULL; | ||
2152 | nsh->hash_lock_index = hash; | 2181 | nsh->hash_lock_index = hash; |
2153 | kmem_cache_free(conf->slab_cache, osh); | 2182 | kmem_cache_free(conf->slab_cache, osh); |
2154 | cnt++; | 2183 | cnt++; |
@@ -2174,25 +2203,6 @@ static int resize_stripes(struct r5conf *conf, int newsize) | |||
2174 | } else | 2203 | } else |
2175 | err = -ENOMEM; | 2204 | err = -ENOMEM; |
2176 | 2205 | ||
2177 | get_online_cpus(); | ||
2178 | for_each_present_cpu(cpu) { | ||
2179 | struct raid5_percpu *percpu; | ||
2180 | struct flex_array *scribble; | ||
2181 | |||
2182 | percpu = per_cpu_ptr(conf->percpu, cpu); | ||
2183 | scribble = scribble_alloc(newsize, conf->chunk_sectors / | ||
2184 | STRIPE_SECTORS, GFP_NOIO); | ||
2185 | |||
2186 | if (scribble) { | ||
2187 | flex_array_free(percpu->scribble); | ||
2188 | percpu->scribble = scribble; | ||
2189 | } else { | ||
2190 | err = -ENOMEM; | ||
2191 | break; | ||
2192 | } | ||
2193 | } | ||
2194 | put_online_cpus(); | ||
2195 | |||
2196 | /* Step 4, return new stripes to service */ | 2206 | /* Step 4, return new stripes to service */ |
2197 | while(!list_empty(&newstripes)) { | 2207 | while(!list_empty(&newstripes)) { |
2198 | nsh = list_entry(newstripes.next, struct stripe_head, lru); | 2208 | nsh = list_entry(newstripes.next, struct stripe_head, lru); |
@@ -2212,7 +2222,8 @@ static int resize_stripes(struct r5conf *conf, int newsize) | |||
2212 | 2222 | ||
2213 | conf->slab_cache = sc; | 2223 | conf->slab_cache = sc; |
2214 | conf->active_name = 1-conf->active_name; | 2224 | conf->active_name = 1-conf->active_name; |
2215 | conf->pool_size = newsize; | 2225 | if (!err) |
2226 | conf->pool_size = newsize; | ||
2216 | return err; | 2227 | return err; |
2217 | } | 2228 | } |
2218 | 2229 | ||
@@ -2434,7 +2445,7 @@ static void raid5_end_write_request(struct bio *bi, int error) | |||
2434 | } | 2445 | } |
2435 | rdev_dec_pending(rdev, conf->mddev); | 2446 | rdev_dec_pending(rdev, conf->mddev); |
2436 | 2447 | ||
2437 | if (sh->batch_head && !uptodate) | 2448 | if (sh->batch_head && !uptodate && !replacement) |
2438 | set_bit(STRIPE_BATCH_ERR, &sh->batch_head->state); | 2449 | set_bit(STRIPE_BATCH_ERR, &sh->batch_head->state); |
2439 | 2450 | ||
2440 | if (!test_and_clear_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags)) | 2451 | if (!test_and_clear_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags)) |
@@ -3278,7 +3289,9 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s, | |||
3278 | /* reconstruct-write isn't being forced */ | 3289 | /* reconstruct-write isn't being forced */ |
3279 | return 0; | 3290 | return 0; |
3280 | for (i = 0; i < s->failed; i++) { | 3291 | for (i = 0; i < s->failed; i++) { |
3281 | if (!test_bit(R5_UPTODATE, &fdev[i]->flags) && | 3292 | if (s->failed_num[i] != sh->pd_idx && |
3293 | s->failed_num[i] != sh->qd_idx && | ||
3294 | !test_bit(R5_UPTODATE, &fdev[i]->flags) && | ||
3282 | !test_bit(R5_OVERWRITE, &fdev[i]->flags)) | 3295 | !test_bit(R5_OVERWRITE, &fdev[i]->flags)) |
3283 | return 1; | 3296 | return 1; |
3284 | } | 3297 | } |
@@ -3298,6 +3311,7 @@ static int fetch_block(struct stripe_head *sh, struct stripe_head_state *s, | |||
3298 | */ | 3311 | */ |
3299 | BUG_ON(test_bit(R5_Wantcompute, &dev->flags)); | 3312 | BUG_ON(test_bit(R5_Wantcompute, &dev->flags)); |
3300 | BUG_ON(test_bit(R5_Wantread, &dev->flags)); | 3313 | BUG_ON(test_bit(R5_Wantread, &dev->flags)); |
3314 | BUG_ON(sh->batch_head); | ||
3301 | if ((s->uptodate == disks - 1) && | 3315 | if ((s->uptodate == disks - 1) && |
3302 | (s->failed && (disk_idx == s->failed_num[0] || | 3316 | (s->failed && (disk_idx == s->failed_num[0] || |
3303 | disk_idx == s->failed_num[1]))) { | 3317 | disk_idx == s->failed_num[1]))) { |
@@ -3366,7 +3380,6 @@ static void handle_stripe_fill(struct stripe_head *sh, | |||
3366 | { | 3380 | { |
3367 | int i; | 3381 | int i; |
3368 | 3382 | ||
3369 | BUG_ON(sh->batch_head); | ||
3370 | /* look for blocks to read/compute, skip this if a compute | 3383 | /* look for blocks to read/compute, skip this if a compute |
3371 | * is already in flight, or if the stripe contents are in the | 3384 | * is already in flight, or if the stripe contents are in the |
3372 | * midst of changing due to a write | 3385 | * midst of changing due to a write |
@@ -4198,15 +4211,9 @@ static void check_break_stripe_batch_list(struct stripe_head *sh) | |||
4198 | return; | 4211 | return; |
4199 | 4212 | ||
4200 | head_sh = sh; | 4213 | head_sh = sh; |
4201 | do { | ||
4202 | sh = list_first_entry(&sh->batch_list, | ||
4203 | struct stripe_head, batch_list); | ||
4204 | BUG_ON(sh == head_sh); | ||
4205 | } while (!test_bit(STRIPE_DEGRADED, &sh->state)); | ||
4206 | 4214 | ||
4207 | while (sh != head_sh) { | 4215 | list_for_each_entry_safe(sh, next, &head_sh->batch_list, batch_list) { |
4208 | next = list_first_entry(&sh->batch_list, | 4216 | |
4209 | struct stripe_head, batch_list); | ||
4210 | list_del_init(&sh->batch_list); | 4217 | list_del_init(&sh->batch_list); |
4211 | 4218 | ||
4212 | set_mask_bits(&sh->state, ~STRIPE_EXPAND_SYNC_FLAG, | 4219 | set_mask_bits(&sh->state, ~STRIPE_EXPAND_SYNC_FLAG, |
@@ -4226,8 +4233,6 @@ static void check_break_stripe_batch_list(struct stripe_head *sh) | |||
4226 | 4233 | ||
4227 | set_bit(STRIPE_HANDLE, &sh->state); | 4234 | set_bit(STRIPE_HANDLE, &sh->state); |
4228 | release_stripe(sh); | 4235 | release_stripe(sh); |
4229 | |||
4230 | sh = next; | ||
4231 | } | 4236 | } |
4232 | } | 4237 | } |
4233 | 4238 | ||
@@ -6221,8 +6226,11 @@ static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu | |||
6221 | percpu->spare_page = alloc_page(GFP_KERNEL); | 6226 | percpu->spare_page = alloc_page(GFP_KERNEL); |
6222 | if (!percpu->scribble) | 6227 | if (!percpu->scribble) |
6223 | percpu->scribble = scribble_alloc(max(conf->raid_disks, | 6228 | percpu->scribble = scribble_alloc(max(conf->raid_disks, |
6224 | conf->previous_raid_disks), conf->chunk_sectors / | 6229 | conf->previous_raid_disks), |
6225 | STRIPE_SECTORS, GFP_KERNEL); | 6230 | max(conf->chunk_sectors, |
6231 | conf->prev_chunk_sectors) | ||
6232 | / STRIPE_SECTORS, | ||
6233 | GFP_KERNEL); | ||
6226 | 6234 | ||
6227 | if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) { | 6235 | if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) { |
6228 | free_scratch_buffer(conf, percpu); | 6236 | free_scratch_buffer(conf, percpu); |
@@ -7198,6 +7206,15 @@ static int check_reshape(struct mddev *mddev) | |||
7198 | if (!check_stripe_cache(mddev)) | 7206 | if (!check_stripe_cache(mddev)) |
7199 | return -ENOSPC; | 7207 | return -ENOSPC; |
7200 | 7208 | ||
7209 | if (mddev->new_chunk_sectors > mddev->chunk_sectors || | ||
7210 | mddev->delta_disks > 0) | ||
7211 | if (resize_chunks(conf, | ||
7212 | conf->previous_raid_disks | ||
7213 | + max(0, mddev->delta_disks), | ||
7214 | max(mddev->new_chunk_sectors, | ||
7215 | mddev->chunk_sectors) | ||
7216 | ) < 0) | ||
7217 | return -ENOMEM; | ||
7201 | return resize_stripes(conf, (conf->previous_raid_disks | 7218 | return resize_stripes(conf, (conf->previous_raid_disks |
7202 | + mddev->delta_disks)); | 7219 | + mddev->delta_disks)); |
7203 | } | 7220 | } |