diff options
Diffstat (limited to 'drivers/md/raid5.c')
| -rw-r--r-- | drivers/md/raid5.c | 123 |
1 files changed, 70 insertions, 53 deletions
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 | } |
