diff options
author | NeilBrown <neilb@suse.de> | 2009-03-31 00:19:07 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2009-03-31 00:19:07 -0400 |
commit | 784052ecc6ade6b6acf4f67e4ada8e5f2e6df446 (patch) | |
tree | f0b1060215922ba30a4d676a00dbdad8ddb724c9 /drivers/md | |
parent | 86b42c713be3e5f6807aa14b4cbdb005d35c64d5 (diff) |
md/raid5: prepare for allowing reshape to change chunksize.
Add "prev_chunk" to raid5_conf_t, similar to "previous_raid_disks", to
remember what the chunk size was before the reshape that is currently
underway.
This seems like duplication with "chunk_size" and "new_chunk" in
mddev_t, and to some extent it is, but there are differences.
The values in mddev_t are always defined and often the same.
The prev* values are only defined if a reshape is underway.
Also (and more significantly) the raid5_conf_t values will be changed
at the same time (inside an appropriate lock) that the reshape is
started by setting reshape_position. In contrast, the new_chunk value
is set when the sysfs file is written which could be well before the
reshape starts.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid5.c | 43 | ||||
-rw-r--r-- | drivers/md/raid5.h | 1 |
2 files changed, 28 insertions, 16 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 73cdf43a6479..7638cc31e7e8 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -299,7 +299,7 @@ static int grow_buffers(struct stripe_head *sh, int num) | |||
299 | return 0; | 299 | return 0; |
300 | } | 300 | } |
301 | 301 | ||
302 | static void raid5_build_block(struct stripe_head *sh, int i); | 302 | static void raid5_build_block(struct stripe_head *sh, int i, int previous); |
303 | static void stripe_set_idx(sector_t stripe, raid5_conf_t *conf, int previous, | 303 | static void stripe_set_idx(sector_t stripe, raid5_conf_t *conf, int previous, |
304 | struct stripe_head *sh); | 304 | struct stripe_head *sh); |
305 | 305 | ||
@@ -337,7 +337,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int previous) | |||
337 | BUG(); | 337 | BUG(); |
338 | } | 338 | } |
339 | dev->flags = 0; | 339 | dev->flags = 0; |
340 | raid5_build_block(sh, i); | 340 | raid5_build_block(sh, i, previous); |
341 | } | 341 | } |
342 | insert_hash(conf, sh); | 342 | insert_hash(conf, sh); |
343 | } | 343 | } |
@@ -1212,9 +1212,9 @@ static void raid5_end_write_request(struct bio *bi, int error) | |||
1212 | } | 1212 | } |
1213 | 1213 | ||
1214 | 1214 | ||
1215 | static sector_t compute_blocknr(struct stripe_head *sh, int i); | 1215 | static sector_t compute_blocknr(struct stripe_head *sh, int i, int previous); |
1216 | 1216 | ||
1217 | static void raid5_build_block(struct stripe_head *sh, int i) | 1217 | static void raid5_build_block(struct stripe_head *sh, int i, int previous) |
1218 | { | 1218 | { |
1219 | struct r5dev *dev = &sh->dev[i]; | 1219 | struct r5dev *dev = &sh->dev[i]; |
1220 | 1220 | ||
@@ -1230,7 +1230,7 @@ static void raid5_build_block(struct stripe_head *sh, int i) | |||
1230 | dev->req.bi_private = sh; | 1230 | dev->req.bi_private = sh; |
1231 | 1231 | ||
1232 | dev->flags = 0; | 1232 | dev->flags = 0; |
1233 | dev->sector = compute_blocknr(sh, i); | 1233 | dev->sector = compute_blocknr(sh, i, previous); |
1234 | } | 1234 | } |
1235 | 1235 | ||
1236 | static void error(mddev_t *mddev, mdk_rdev_t *rdev) | 1236 | static void error(mddev_t *mddev, mdk_rdev_t *rdev) |
@@ -1273,7 +1273,8 @@ static sector_t raid5_compute_sector(raid5_conf_t *conf, sector_t r_sector, | |||
1273 | int pd_idx, qd_idx; | 1273 | int pd_idx, qd_idx; |
1274 | int ddf_layout = 0; | 1274 | int ddf_layout = 0; |
1275 | sector_t new_sector; | 1275 | sector_t new_sector; |
1276 | int sectors_per_chunk = conf->chunk_size >> 9; | 1276 | int sectors_per_chunk = previous ? (conf->prev_chunk >> 9) |
1277 | : (conf->chunk_size >> 9); | ||
1277 | int raid_disks = previous ? conf->previous_raid_disks | 1278 | int raid_disks = previous ? conf->previous_raid_disks |
1278 | : conf->raid_disks; | 1279 | : conf->raid_disks; |
1279 | int data_disks = raid_disks - conf->max_degraded; | 1280 | int data_disks = raid_disks - conf->max_degraded; |
@@ -1472,13 +1473,14 @@ static sector_t raid5_compute_sector(raid5_conf_t *conf, sector_t r_sector, | |||
1472 | } | 1473 | } |
1473 | 1474 | ||
1474 | 1475 | ||
1475 | static sector_t compute_blocknr(struct stripe_head *sh, int i) | 1476 | static sector_t compute_blocknr(struct stripe_head *sh, int i, int previous) |
1476 | { | 1477 | { |
1477 | raid5_conf_t *conf = sh->raid_conf; | 1478 | raid5_conf_t *conf = sh->raid_conf; |
1478 | int raid_disks = sh->disks; | 1479 | int raid_disks = sh->disks; |
1479 | int data_disks = raid_disks - conf->max_degraded; | 1480 | int data_disks = raid_disks - conf->max_degraded; |
1480 | sector_t new_sector = sh->sector, check; | 1481 | sector_t new_sector = sh->sector, check; |
1481 | int sectors_per_chunk = conf->chunk_size >> 9; | 1482 | int sectors_per_chunk = previous ? (conf->prev_chunk >> 9) |
1483 | : (conf->chunk_size >> 9); | ||
1482 | sector_t stripe; | 1484 | sector_t stripe; |
1483 | int chunk_offset; | 1485 | int chunk_offset; |
1484 | int chunk_number, dummy1, dd_idx = i; | 1486 | int chunk_number, dummy1, dd_idx = i; |
@@ -1579,8 +1581,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i) | |||
1579 | r_sector = (sector_t)chunk_number * sectors_per_chunk + chunk_offset; | 1581 | r_sector = (sector_t)chunk_number * sectors_per_chunk + chunk_offset; |
1580 | 1582 | ||
1581 | check = raid5_compute_sector(conf, r_sector, | 1583 | check = raid5_compute_sector(conf, r_sector, |
1582 | (raid_disks != conf->raid_disks), | 1584 | previous, &dummy1, &sh2); |
1583 | &dummy1, &sh2); | ||
1584 | if (check != sh->sector || dummy1 != dd_idx || sh2.pd_idx != sh->pd_idx | 1585 | if (check != sh->sector || dummy1 != dd_idx || sh2.pd_idx != sh->pd_idx |
1585 | || sh2.qd_idx != sh->qd_idx) { | 1586 | || sh2.qd_idx != sh->qd_idx) { |
1586 | printk(KERN_ERR "compute_blocknr: map not correct\n"); | 1587 | printk(KERN_ERR "compute_blocknr: map not correct\n"); |
@@ -1992,7 +1993,9 @@ static int page_is_zero(struct page *p) | |||
1992 | static void stripe_set_idx(sector_t stripe, raid5_conf_t *conf, int previous, | 1993 | static void stripe_set_idx(sector_t stripe, raid5_conf_t *conf, int previous, |
1993 | struct stripe_head *sh) | 1994 | struct stripe_head *sh) |
1994 | { | 1995 | { |
1995 | int sectors_per_chunk = conf->chunk_size >> 9; | 1996 | int sectors_per_chunk = |
1997 | previous ? (conf->prev_chunk >> 9) | ||
1998 | : (conf->chunk_size >> 9); | ||
1996 | int dd_idx; | 1999 | int dd_idx; |
1997 | int chunk_offset = sector_div(stripe, sectors_per_chunk); | 2000 | int chunk_offset = sector_div(stripe, sectors_per_chunk); |
1998 | int disks = previous ? conf->previous_raid_disks : conf->raid_disks; | 2001 | int disks = previous ? conf->previous_raid_disks : conf->raid_disks; |
@@ -2662,7 +2665,7 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh, | |||
2662 | int dd_idx, j; | 2665 | int dd_idx, j; |
2663 | struct stripe_head *sh2; | 2666 | struct stripe_head *sh2; |
2664 | 2667 | ||
2665 | sector_t bn = compute_blocknr(sh, i); | 2668 | sector_t bn = compute_blocknr(sh, i, 1); |
2666 | sector_t s = raid5_compute_sector(conf, bn, 0, | 2669 | sector_t s = raid5_compute_sector(conf, bn, 0, |
2667 | &dd_idx, NULL); | 2670 | &dd_idx, NULL); |
2668 | sh2 = get_active_stripe(conf, s, 0, 1); | 2671 | sh2 = get_active_stripe(conf, s, 0, 1); |
@@ -3318,6 +3321,8 @@ static int raid5_mergeable_bvec(struct request_queue *q, | |||
3318 | if ((bvm->bi_rw & 1) == WRITE) | 3321 | if ((bvm->bi_rw & 1) == WRITE) |
3319 | return biovec->bv_len; /* always allow writes to be mergeable */ | 3322 | return biovec->bv_len; /* always allow writes to be mergeable */ |
3320 | 3323 | ||
3324 | if (mddev->new_chunk < mddev->chunk_size) | ||
3325 | chunk_sectors = mddev->new_chunk >> 9; | ||
3321 | max = (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9; | 3326 | max = (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9; |
3322 | if (max < 0) max = 0; | 3327 | if (max < 0) max = 0; |
3323 | if (max <= biovec->bv_len && bio_sectors == 0) | 3328 | if (max <= biovec->bv_len && bio_sectors == 0) |
@@ -3333,6 +3338,8 @@ static int in_chunk_boundary(mddev_t *mddev, struct bio *bio) | |||
3333 | unsigned int chunk_sectors = mddev->chunk_size >> 9; | 3338 | unsigned int chunk_sectors = mddev->chunk_size >> 9; |
3334 | unsigned int bio_sectors = bio->bi_size >> 9; | 3339 | unsigned int bio_sectors = bio->bi_size >> 9; |
3335 | 3340 | ||
3341 | if (mddev->new_chunk < mddev->chunk_size) | ||
3342 | chunk_sectors = mddev->new_chunk >> 9; | ||
3336 | return chunk_sectors >= | 3343 | return chunk_sectors >= |
3337 | ((sector & (chunk_sectors - 1)) + bio_sectors); | 3344 | ((sector & (chunk_sectors - 1)) + bio_sectors); |
3338 | } | 3345 | } |
@@ -3788,7 +3795,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped | |||
3788 | BUG_ON(conf->reshape_progress == 0); | 3795 | BUG_ON(conf->reshape_progress == 0); |
3789 | stripe_addr = writepos; | 3796 | stripe_addr = writepos; |
3790 | BUG_ON((mddev->dev_sectors & | 3797 | BUG_ON((mddev->dev_sectors & |
3791 | ~((sector_t)mddev->chunk_size / 512 - 1)) | 3798 | ~((sector_t)conf->chunk_size / 512 - 1)) |
3792 | - (conf->chunk_size / 512) - stripe_addr | 3799 | - (conf->chunk_size / 512) - stripe_addr |
3793 | != sector_nr); | 3800 | != sector_nr); |
3794 | } else { | 3801 | } else { |
@@ -3811,7 +3818,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped | |||
3811 | if (conf->level == 6 && | 3818 | if (conf->level == 6 && |
3812 | j == sh->qd_idx) | 3819 | j == sh->qd_idx) |
3813 | continue; | 3820 | continue; |
3814 | s = compute_blocknr(sh, j); | 3821 | s = compute_blocknr(sh, j, 0); |
3815 | if (s < raid5_size(mddev, 0, 0)) { | 3822 | if (s < raid5_size(mddev, 0, 0)) { |
3816 | skipped = 1; | 3823 | skipped = 1; |
3817 | continue; | 3824 | continue; |
@@ -4217,6 +4224,7 @@ raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks) | |||
4217 | } | 4224 | } |
4218 | 4225 | ||
4219 | sectors &= ~((sector_t)mddev->chunk_size/512 - 1); | 4226 | sectors &= ~((sector_t)mddev->chunk_size/512 - 1); |
4227 | sectors &= ~((sector_t)mddev->new_chunk/512 - 1); | ||
4220 | return sectors * (raid_disks - conf->max_degraded); | 4228 | return sectors * (raid_disks - conf->max_degraded); |
4221 | } | 4229 | } |
4222 | 4230 | ||
@@ -4322,6 +4330,8 @@ static raid5_conf_t *setup_conf(mddev_t *mddev) | |||
4322 | conf->algorithm = mddev->new_layout; | 4330 | conf->algorithm = mddev->new_layout; |
4323 | conf->max_nr_stripes = NR_STRIPES; | 4331 | conf->max_nr_stripes = NR_STRIPES; |
4324 | conf->reshape_progress = mddev->reshape_position; | 4332 | conf->reshape_progress = mddev->reshape_position; |
4333 | if (conf->reshape_progress != MaxSector) | ||
4334 | conf->prev_chunk = mddev->chunk_size; | ||
4325 | 4335 | ||
4326 | memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + | 4336 | memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + |
4327 | conf->raid_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024; | 4337 | conf->raid_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024; |
@@ -4385,7 +4395,7 @@ static int run(mddev_t *mddev) | |||
4385 | * geometry. | 4395 | * geometry. |
4386 | */ | 4396 | */ |
4387 | here_new = mddev->reshape_position; | 4397 | here_new = mddev->reshape_position; |
4388 | if (sector_div(here_new, (mddev->chunk_size>>9)* | 4398 | if (sector_div(here_new, (mddev->new_chunk>>9)* |
4389 | (mddev->raid_disks - max_degraded))) { | 4399 | (mddev->raid_disks - max_degraded))) { |
4390 | printk(KERN_ERR "raid5: reshape_position not " | 4400 | printk(KERN_ERR "raid5: reshape_position not " |
4391 | "on a stripe boundary\n"); | 4401 | "on a stripe boundary\n"); |
@@ -4789,7 +4799,8 @@ static int raid5_check_reshape(mddev_t *mddev) | |||
4789 | if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes || | 4799 | if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes || |
4790 | (mddev->new_chunk / STRIPE_SIZE) * 4 > conf->max_nr_stripes) { | 4800 | (mddev->new_chunk / STRIPE_SIZE) * 4 > conf->max_nr_stripes) { |
4791 | printk(KERN_WARNING "raid5: reshape: not enough stripes. Needed %lu\n", | 4801 | printk(KERN_WARNING "raid5: reshape: not enough stripes. Needed %lu\n", |
4792 | (mddev->chunk_size / STRIPE_SIZE)*4); | 4802 | (max(mddev->chunk_size, mddev->new_chunk) |
4803 | / STRIPE_SIZE)*4); | ||
4793 | return -ENOSPC; | 4804 | return -ENOSPC; |
4794 | } | 4805 | } |
4795 | 4806 | ||
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index a081fb40a5a2..b9c93280fc1d 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h | |||
@@ -350,6 +350,7 @@ struct raid5_private_data { | |||
350 | */ | 350 | */ |
351 | sector_t reshape_safe; | 351 | sector_t reshape_safe; |
352 | int previous_raid_disks; | 352 | int previous_raid_disks; |
353 | int prev_chunk; | ||
353 | short generation; /* increments with every reshape */ | 354 | short generation; /* increments with every reshape */ |
354 | 355 | ||
355 | struct list_head handle_list; /* stripes needing handling */ | 356 | struct list_head handle_list; /* stripes needing handling */ |