diff options
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 88 |
1 files changed, 58 insertions, 30 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 6c20b44509d8..7a6df515b008 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -178,10 +178,10 @@ static int grow_buffers(struct stripe_head *sh, int num) | |||
178 | 178 | ||
179 | static void raid5_build_block (struct stripe_head *sh, int i); | 179 | static void raid5_build_block (struct stripe_head *sh, int i); |
180 | 180 | ||
181 | static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) | 181 | static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int disks) |
182 | { | 182 | { |
183 | raid5_conf_t *conf = sh->raid_conf; | 183 | raid5_conf_t *conf = sh->raid_conf; |
184 | int disks = conf->raid_disks, i; | 184 | int i; |
185 | 185 | ||
186 | if (atomic_read(&sh->count) != 0) | 186 | if (atomic_read(&sh->count) != 0) |
187 | BUG(); | 187 | BUG(); |
@@ -198,7 +198,9 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) | |||
198 | sh->pd_idx = pd_idx; | 198 | sh->pd_idx = pd_idx; |
199 | sh->state = 0; | 199 | sh->state = 0; |
200 | 200 | ||
201 | for (i=disks; i--; ) { | 201 | sh->disks = disks; |
202 | |||
203 | for (i = sh->disks; i--; ) { | ||
202 | struct r5dev *dev = &sh->dev[i]; | 204 | struct r5dev *dev = &sh->dev[i]; |
203 | 205 | ||
204 | if (dev->toread || dev->towrite || dev->written || | 206 | if (dev->toread || dev->towrite || dev->written || |
@@ -215,7 +217,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) | |||
215 | insert_hash(conf, sh); | 217 | insert_hash(conf, sh); |
216 | } | 218 | } |
217 | 219 | ||
218 | static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) | 220 | static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector, int disks) |
219 | { | 221 | { |
220 | struct stripe_head *sh; | 222 | struct stripe_head *sh; |
221 | struct hlist_node *hn; | 223 | struct hlist_node *hn; |
@@ -223,7 +225,7 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) | |||
223 | CHECK_DEVLOCK(); | 225 | CHECK_DEVLOCK(); |
224 | PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector); | 226 | PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector); |
225 | hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash) | 227 | hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash) |
226 | if (sh->sector == sector) | 228 | if (sh->sector == sector && sh->disks == disks) |
227 | return sh; | 229 | return sh; |
228 | PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector); | 230 | PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector); |
229 | return NULL; | 231 | return NULL; |
@@ -232,8 +234,8 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) | |||
232 | static void unplug_slaves(mddev_t *mddev); | 234 | static void unplug_slaves(mddev_t *mddev); |
233 | static void raid5_unplug_device(request_queue_t *q); | 235 | static void raid5_unplug_device(request_queue_t *q); |
234 | 236 | ||
235 | static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector, | 237 | static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector, int disks, |
236 | int pd_idx, int noblock) | 238 | int pd_idx, int noblock) |
237 | { | 239 | { |
238 | struct stripe_head *sh; | 240 | struct stripe_head *sh; |
239 | 241 | ||
@@ -245,7 +247,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector | |||
245 | wait_event_lock_irq(conf->wait_for_stripe, | 247 | wait_event_lock_irq(conf->wait_for_stripe, |
246 | conf->quiesce == 0, | 248 | conf->quiesce == 0, |
247 | conf->device_lock, /* nothing */); | 249 | conf->device_lock, /* nothing */); |
248 | sh = __find_stripe(conf, sector); | 250 | sh = __find_stripe(conf, sector, disks); |
249 | if (!sh) { | 251 | if (!sh) { |
250 | if (!conf->inactive_blocked) | 252 | if (!conf->inactive_blocked) |
251 | sh = get_free_stripe(conf); | 253 | sh = get_free_stripe(conf); |
@@ -263,7 +265,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector | |||
263 | ); | 265 | ); |
264 | conf->inactive_blocked = 0; | 266 | conf->inactive_blocked = 0; |
265 | } else | 267 | } else |
266 | init_stripe(sh, sector, pd_idx); | 268 | init_stripe(sh, sector, pd_idx, disks); |
267 | } else { | 269 | } else { |
268 | if (atomic_read(&sh->count)) { | 270 | if (atomic_read(&sh->count)) { |
269 | if (!list_empty(&sh->lru)) | 271 | if (!list_empty(&sh->lru)) |
@@ -300,6 +302,7 @@ static int grow_one_stripe(raid5_conf_t *conf) | |||
300 | kmem_cache_free(conf->slab_cache, sh); | 302 | kmem_cache_free(conf->slab_cache, sh); |
301 | return 0; | 303 | return 0; |
302 | } | 304 | } |
305 | sh->disks = conf->raid_disks; | ||
303 | /* we just created an active stripe so... */ | 306 | /* we just created an active stripe so... */ |
304 | atomic_set(&sh->count, 1); | 307 | atomic_set(&sh->count, 1); |
305 | atomic_inc(&conf->active_stripes); | 308 | atomic_inc(&conf->active_stripes); |
@@ -483,7 +486,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, | |||
483 | { | 486 | { |
484 | struct stripe_head *sh = bi->bi_private; | 487 | struct stripe_head *sh = bi->bi_private; |
485 | raid5_conf_t *conf = sh->raid_conf; | 488 | raid5_conf_t *conf = sh->raid_conf; |
486 | int disks = conf->raid_disks, i; | 489 | int disks = sh->disks, i; |
487 | int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); | 490 | int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); |
488 | 491 | ||
489 | if (bi->bi_size) | 492 | if (bi->bi_size) |
@@ -581,7 +584,7 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done, | |||
581 | { | 584 | { |
582 | struct stripe_head *sh = bi->bi_private; | 585 | struct stripe_head *sh = bi->bi_private; |
583 | raid5_conf_t *conf = sh->raid_conf; | 586 | raid5_conf_t *conf = sh->raid_conf; |
584 | int disks = conf->raid_disks, i; | 587 | int disks = sh->disks, i; |
585 | unsigned long flags; | 588 | unsigned long flags; |
586 | int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); | 589 | int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); |
587 | 590 | ||
@@ -735,7 +738,7 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks, | |||
735 | static sector_t compute_blocknr(struct stripe_head *sh, int i) | 738 | static sector_t compute_blocknr(struct stripe_head *sh, int i) |
736 | { | 739 | { |
737 | raid5_conf_t *conf = sh->raid_conf; | 740 | raid5_conf_t *conf = sh->raid_conf; |
738 | int raid_disks = conf->raid_disks, data_disks = raid_disks - 1; | 741 | int raid_disks = sh->disks, data_disks = raid_disks - 1; |
739 | sector_t new_sector = sh->sector, check; | 742 | sector_t new_sector = sh->sector, check; |
740 | int sectors_per_chunk = conf->chunk_size >> 9; | 743 | int sectors_per_chunk = conf->chunk_size >> 9; |
741 | sector_t stripe; | 744 | sector_t stripe; |
@@ -836,8 +839,7 @@ static void copy_data(int frombio, struct bio *bio, | |||
836 | 839 | ||
837 | static void compute_block(struct stripe_head *sh, int dd_idx) | 840 | static void compute_block(struct stripe_head *sh, int dd_idx) |
838 | { | 841 | { |
839 | raid5_conf_t *conf = sh->raid_conf; | 842 | int i, count, disks = sh->disks; |
840 | int i, count, disks = conf->raid_disks; | ||
841 | void *ptr[MAX_XOR_BLOCKS], *p; | 843 | void *ptr[MAX_XOR_BLOCKS], *p; |
842 | 844 | ||
843 | PRINTK("compute_block, stripe %llu, idx %d\n", | 845 | PRINTK("compute_block, stripe %llu, idx %d\n", |
@@ -867,7 +869,7 @@ static void compute_block(struct stripe_head *sh, int dd_idx) | |||
867 | static void compute_parity(struct stripe_head *sh, int method) | 869 | static void compute_parity(struct stripe_head *sh, int method) |
868 | { | 870 | { |
869 | raid5_conf_t *conf = sh->raid_conf; | 871 | raid5_conf_t *conf = sh->raid_conf; |
870 | int i, pd_idx = sh->pd_idx, disks = conf->raid_disks, count; | 872 | int i, pd_idx = sh->pd_idx, disks = sh->disks, count; |
871 | void *ptr[MAX_XOR_BLOCKS]; | 873 | void *ptr[MAX_XOR_BLOCKS]; |
872 | struct bio *chosen; | 874 | struct bio *chosen; |
873 | 875 | ||
@@ -1055,7 +1057,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in | |||
1055 | static void handle_stripe(struct stripe_head *sh) | 1057 | static void handle_stripe(struct stripe_head *sh) |
1056 | { | 1058 | { |
1057 | raid5_conf_t *conf = sh->raid_conf; | 1059 | raid5_conf_t *conf = sh->raid_conf; |
1058 | int disks = conf->raid_disks; | 1060 | int disks = sh->disks; |
1059 | struct bio *return_bi= NULL; | 1061 | struct bio *return_bi= NULL; |
1060 | struct bio *bi; | 1062 | struct bio *bi; |
1061 | int i; | 1063 | int i; |
@@ -1649,12 +1651,10 @@ static inline void raid5_plug_device(raid5_conf_t *conf) | |||
1649 | spin_unlock_irq(&conf->device_lock); | 1651 | spin_unlock_irq(&conf->device_lock); |
1650 | } | 1652 | } |
1651 | 1653 | ||
1652 | static int make_request (request_queue_t *q, struct bio * bi) | 1654 | static int make_request(request_queue_t *q, struct bio * bi) |
1653 | { | 1655 | { |
1654 | mddev_t *mddev = q->queuedata; | 1656 | mddev_t *mddev = q->queuedata; |
1655 | raid5_conf_t *conf = mddev_to_conf(mddev); | 1657 | raid5_conf_t *conf = mddev_to_conf(mddev); |
1656 | const unsigned int raid_disks = conf->raid_disks; | ||
1657 | const unsigned int data_disks = raid_disks - 1; | ||
1658 | unsigned int dd_idx, pd_idx; | 1658 | unsigned int dd_idx, pd_idx; |
1659 | sector_t new_sector; | 1659 | sector_t new_sector; |
1660 | sector_t logical_sector, last_sector; | 1660 | sector_t logical_sector, last_sector; |
@@ -1678,20 +1678,48 @@ static int make_request (request_queue_t *q, struct bio * bi) | |||
1678 | 1678 | ||
1679 | for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { | 1679 | for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { |
1680 | DEFINE_WAIT(w); | 1680 | DEFINE_WAIT(w); |
1681 | int disks; | ||
1681 | 1682 | ||
1682 | new_sector = raid5_compute_sector(logical_sector, | 1683 | retry: |
1683 | raid_disks, data_disks, &dd_idx, &pd_idx, conf); | 1684 | if (likely(conf->expand_progress == MaxSector)) |
1684 | 1685 | disks = conf->raid_disks; | |
1686 | else { | ||
1687 | spin_lock_irq(&conf->device_lock); | ||
1688 | disks = conf->raid_disks; | ||
1689 | if (logical_sector >= conf->expand_progress) | ||
1690 | disks = conf->previous_raid_disks; | ||
1691 | spin_unlock_irq(&conf->device_lock); | ||
1692 | } | ||
1693 | new_sector = raid5_compute_sector(logical_sector, disks, disks - 1, | ||
1694 | &dd_idx, &pd_idx, conf); | ||
1685 | PRINTK("raid5: make_request, sector %llu logical %llu\n", | 1695 | PRINTK("raid5: make_request, sector %llu logical %llu\n", |
1686 | (unsigned long long)new_sector, | 1696 | (unsigned long long)new_sector, |
1687 | (unsigned long long)logical_sector); | 1697 | (unsigned long long)logical_sector); |
1688 | 1698 | ||
1689 | retry: | ||
1690 | prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); | 1699 | prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); |
1691 | sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK)); | 1700 | sh = get_active_stripe(conf, new_sector, disks, pd_idx, (bi->bi_rw&RWA_MASK)); |
1692 | if (sh) { | 1701 | if (sh) { |
1693 | if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) { | 1702 | if (unlikely(conf->expand_progress != MaxSector)) { |
1694 | /* Add failed due to overlap. Flush everything | 1703 | /* expansion might have moved on while waiting for a |
1704 | * stripe, so we much do the range check again. | ||
1705 | */ | ||
1706 | int must_retry = 0; | ||
1707 | spin_lock_irq(&conf->device_lock); | ||
1708 | if (logical_sector < conf->expand_progress && | ||
1709 | disks == conf->previous_raid_disks) | ||
1710 | /* mismatch, need to try again */ | ||
1711 | must_retry = 1; | ||
1712 | spin_unlock_irq(&conf->device_lock); | ||
1713 | if (must_retry) { | ||
1714 | release_stripe(sh); | ||
1715 | goto retry; | ||
1716 | } | ||
1717 | } | ||
1718 | |||
1719 | if (test_bit(STRIPE_EXPANDING, &sh->state) || | ||
1720 | !add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) { | ||
1721 | /* Stripe is busy expanding or | ||
1722 | * add failed due to overlap. Flush everything | ||
1695 | * and wait a while | 1723 | * and wait a while |
1696 | */ | 1724 | */ |
1697 | raid5_unplug_device(mddev->queue); | 1725 | raid5_unplug_device(mddev->queue); |
@@ -1703,7 +1731,6 @@ static int make_request (request_queue_t *q, struct bio * bi) | |||
1703 | raid5_plug_device(conf); | 1731 | raid5_plug_device(conf); |
1704 | handle_stripe(sh); | 1732 | handle_stripe(sh); |
1705 | release_stripe(sh); | 1733 | release_stripe(sh); |
1706 | |||
1707 | } else { | 1734 | } else { |
1708 | /* cannot get stripe for read-ahead, just give-up */ | 1735 | /* cannot get stripe for read-ahead, just give-up */ |
1709 | clear_bit(BIO_UPTODATE, &bi->bi_flags); | 1736 | clear_bit(BIO_UPTODATE, &bi->bi_flags); |
@@ -1779,9 +1806,9 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1779 | 1806 | ||
1780 | first_sector = raid5_compute_sector((sector_t)stripe*data_disks*sectors_per_chunk | 1807 | first_sector = raid5_compute_sector((sector_t)stripe*data_disks*sectors_per_chunk |
1781 | + chunk_offset, raid_disks, data_disks, &dd_idx, &pd_idx, conf); | 1808 | + chunk_offset, raid_disks, data_disks, &dd_idx, &pd_idx, conf); |
1782 | sh = get_active_stripe(conf, sector_nr, pd_idx, 1); | 1809 | sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1); |
1783 | if (sh == NULL) { | 1810 | if (sh == NULL) { |
1784 | sh = get_active_stripe(conf, sector_nr, pd_idx, 0); | 1811 | sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 0); |
1785 | /* make sure we don't swamp the stripe cache if someone else | 1812 | /* make sure we don't swamp the stripe cache if someone else |
1786 | * is trying to get access | 1813 | * is trying to get access |
1787 | */ | 1814 | */ |
@@ -1998,6 +2025,7 @@ static int run(mddev_t *mddev) | |||
1998 | conf->level = mddev->level; | 2025 | conf->level = mddev->level; |
1999 | conf->algorithm = mddev->layout; | 2026 | conf->algorithm = mddev->layout; |
2000 | conf->max_nr_stripes = NR_STRIPES; | 2027 | conf->max_nr_stripes = NR_STRIPES; |
2028 | conf->expand_progress = MaxSector; | ||
2001 | 2029 | ||
2002 | /* device size must be a multiple of chunk size */ | 2030 | /* device size must be a multiple of chunk size */ |
2003 | mddev->size &= ~(mddev->chunk_size/1024 -1); | 2031 | mddev->size &= ~(mddev->chunk_size/1024 -1); |
@@ -2128,7 +2156,7 @@ static void print_sh (struct stripe_head *sh) | |||
2128 | printk("sh %llu, count %d.\n", | 2156 | printk("sh %llu, count %d.\n", |
2129 | (unsigned long long)sh->sector, atomic_read(&sh->count)); | 2157 | (unsigned long long)sh->sector, atomic_read(&sh->count)); |
2130 | printk("sh %llu, ", (unsigned long long)sh->sector); | 2158 | printk("sh %llu, ", (unsigned long long)sh->sector); |
2131 | for (i = 0; i < sh->raid_conf->raid_disks; i++) { | 2159 | for (i = 0; i < sh->disks; i++) { |
2132 | printk("(cache%d: %p %ld) ", | 2160 | printk("(cache%d: %p %ld) ", |
2133 | i, sh->dev[i].page, sh->dev[i].flags); | 2161 | i, sh->dev[i].page, sh->dev[i].flags); |
2134 | } | 2162 | } |