diff options
-rw-r--r-- | drivers/md/md.c | 10 | ||||
-rw-r--r-- | drivers/md/raid1.c | 19 | ||||
-rw-r--r-- | drivers/md/raid5.c | 60 | ||||
-rw-r--r-- | include/linux/raid/md_k.h | 3 |
4 files changed, 58 insertions, 34 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index b9dfdfccdb78..1a637676a930 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -2594,7 +2594,7 @@ static int do_md_run(mddev_t * mddev) | |||
2594 | strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); | 2594 | strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); |
2595 | 2595 | ||
2596 | if (mddev->reshape_position != MaxSector && | 2596 | if (mddev->reshape_position != MaxSector && |
2597 | pers->reshape == NULL) { | 2597 | pers->start_reshape == NULL) { |
2598 | /* This personality cannot handle reshaping... */ | 2598 | /* This personality cannot handle reshaping... */ |
2599 | mddev->pers = NULL; | 2599 | mddev->pers = NULL; |
2600 | module_put(pers->owner); | 2600 | module_put(pers->owner); |
@@ -3556,14 +3556,16 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks) | |||
3556 | { | 3556 | { |
3557 | int rv; | 3557 | int rv; |
3558 | /* change the number of raid disks */ | 3558 | /* change the number of raid disks */ |
3559 | if (mddev->pers->reshape == NULL) | 3559 | if (mddev->pers->check_reshape == NULL) |
3560 | return -EINVAL; | 3560 | return -EINVAL; |
3561 | if (raid_disks <= 0 || | 3561 | if (raid_disks <= 0 || |
3562 | raid_disks >= mddev->max_disks) | 3562 | raid_disks >= mddev->max_disks) |
3563 | return -EINVAL; | 3563 | return -EINVAL; |
3564 | if (mddev->sync_thread) | 3564 | if (mddev->sync_thread || mddev->reshape_position != MaxSector) |
3565 | return -EBUSY; | 3565 | return -EBUSY; |
3566 | rv = mddev->pers->reshape(mddev, raid_disks); | 3566 | mddev->delta_disks = raid_disks - mddev->raid_disks; |
3567 | |||
3568 | rv = mddev->pers->check_reshape(mddev); | ||
3567 | return rv; | 3569 | return rv; |
3568 | } | 3570 | } |
3569 | 3571 | ||
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index b65b8cfbdf30..04418e10d1dc 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -1976,7 +1976,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors) | |||
1976 | return 0; | 1976 | return 0; |
1977 | } | 1977 | } |
1978 | 1978 | ||
1979 | static int raid1_reshape(mddev_t *mddev, int raid_disks) | 1979 | static int raid1_reshape(mddev_t *mddev) |
1980 | { | 1980 | { |
1981 | /* We need to: | 1981 | /* We need to: |
1982 | * 1/ resize the r1bio_pool | 1982 | * 1/ resize the r1bio_pool |
@@ -1993,10 +1993,22 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) | |||
1993 | struct pool_info *newpoolinfo; | 1993 | struct pool_info *newpoolinfo; |
1994 | mirror_info_t *newmirrors; | 1994 | mirror_info_t *newmirrors; |
1995 | conf_t *conf = mddev_to_conf(mddev); | 1995 | conf_t *conf = mddev_to_conf(mddev); |
1996 | int cnt; | 1996 | int cnt, raid_disks; |
1997 | 1997 | ||
1998 | int d, d2; | 1998 | int d, d2; |
1999 | 1999 | ||
2000 | /* Cannot change chunk_size, layout, or level */ | ||
2001 | if (mddev->chunk_size != mddev->new_chunk || | ||
2002 | mddev->layout != mddev->new_layout || | ||
2003 | mddev->level != mddev->new_level) { | ||
2004 | mddev->new_chunk = mddev->chunk_size; | ||
2005 | mddev->new_layout = mddev->layout; | ||
2006 | mddev->new_level = mddev->level; | ||
2007 | return -EINVAL; | ||
2008 | } | ||
2009 | |||
2010 | raid_disks = mddev->raid_disks + mddev->delta_disks; | ||
2011 | |||
2000 | if (raid_disks < conf->raid_disks) { | 2012 | if (raid_disks < conf->raid_disks) { |
2001 | cnt=0; | 2013 | cnt=0; |
2002 | for (d= 0; d < conf->raid_disks; d++) | 2014 | for (d= 0; d < conf->raid_disks; d++) |
@@ -2043,6 +2055,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) | |||
2043 | 2055 | ||
2044 | mddev->degraded += (raid_disks - conf->raid_disks); | 2056 | mddev->degraded += (raid_disks - conf->raid_disks); |
2045 | conf->raid_disks = mddev->raid_disks = raid_disks; | 2057 | conf->raid_disks = mddev->raid_disks = raid_disks; |
2058 | mddev->delta_disks = 0; | ||
2046 | 2059 | ||
2047 | conf->last_used = 0; /* just make sure it is in-range */ | 2060 | conf->last_used = 0; /* just make sure it is in-range */ |
2048 | lower_barrier(conf); | 2061 | lower_barrier(conf); |
@@ -2084,7 +2097,7 @@ static struct mdk_personality raid1_personality = | |||
2084 | .spare_active = raid1_spare_active, | 2097 | .spare_active = raid1_spare_active, |
2085 | .sync_request = sync_request, | 2098 | .sync_request = sync_request, |
2086 | .resize = raid1_resize, | 2099 | .resize = raid1_resize, |
2087 | .reshape = raid1_reshape, | 2100 | .check_reshape = raid1_reshape, |
2088 | .quiesce = raid1_quiesce, | 2101 | .quiesce = raid1_quiesce, |
2089 | }; | 2102 | }; |
2090 | 2103 | ||
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 089a32604305..355dafb98aac 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -2590,21 +2590,15 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors) | |||
2590 | } | 2590 | } |
2591 | 2591 | ||
2592 | #ifdef CONFIG_MD_RAID5_RESHAPE | 2592 | #ifdef CONFIG_MD_RAID5_RESHAPE |
2593 | static int raid5_reshape(mddev_t *mddev, int raid_disks) | 2593 | static int raid5_check_reshape(mddev_t *mddev) |
2594 | { | 2594 | { |
2595 | raid5_conf_t *conf = mddev_to_conf(mddev); | 2595 | raid5_conf_t *conf = mddev_to_conf(mddev); |
2596 | int err; | 2596 | int err; |
2597 | mdk_rdev_t *rdev; | ||
2598 | struct list_head *rtmp; | ||
2599 | int spares = 0; | ||
2600 | int added_devices = 0; | ||
2601 | 2597 | ||
2602 | if (mddev->degraded || | 2598 | if (mddev->delta_disks < 0 || |
2603 | test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) | 2599 | mddev->new_level != mddev->level) |
2604 | return -EBUSY; | 2600 | return -EINVAL; /* Cannot shrink array or change level yet */ |
2605 | if (conf->raid_disks > raid_disks) | 2601 | if (mddev->delta_disks == 0) |
2606 | return -EINVAL; /* Cannot shrink array yet */ | ||
2607 | if (conf->raid_disks == raid_disks) | ||
2608 | return 0; /* nothing to do */ | 2602 | return 0; /* nothing to do */ |
2609 | 2603 | ||
2610 | /* Can only proceed if there are plenty of stripe_heads. | 2604 | /* Can only proceed if there are plenty of stripe_heads. |
@@ -2615,30 +2609,48 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) | |||
2615 | * If the chunk size is greater, user-space should request more | 2609 | * If the chunk size is greater, user-space should request more |
2616 | * stripe_heads first. | 2610 | * stripe_heads first. |
2617 | */ | 2611 | */ |
2618 | if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes) { | 2612 | if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes || |
2613 | (mddev->new_chunk / STRIPE_SIZE) * 4 > conf->max_nr_stripes) { | ||
2619 | printk(KERN_WARNING "raid5: reshape: not enough stripes. Needed %lu\n", | 2614 | printk(KERN_WARNING "raid5: reshape: not enough stripes. Needed %lu\n", |
2620 | (mddev->chunk_size / STRIPE_SIZE)*4); | 2615 | (mddev->chunk_size / STRIPE_SIZE)*4); |
2621 | return -ENOSPC; | 2616 | return -ENOSPC; |
2622 | } | 2617 | } |
2623 | 2618 | ||
2619 | err = resize_stripes(conf, conf->raid_disks + mddev->delta_disks); | ||
2620 | if (err) | ||
2621 | return err; | ||
2622 | |||
2623 | /* looks like we might be able to manage this */ | ||
2624 | return 0; | ||
2625 | } | ||
2626 | |||
2627 | static int raid5_start_reshape(mddev_t *mddev) | ||
2628 | { | ||
2629 | raid5_conf_t *conf = mddev_to_conf(mddev); | ||
2630 | mdk_rdev_t *rdev; | ||
2631 | struct list_head *rtmp; | ||
2632 | int spares = 0; | ||
2633 | int added_devices = 0; | ||
2634 | |||
2635 | if (mddev->degraded || | ||
2636 | test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) | ||
2637 | return -EBUSY; | ||
2638 | |||
2624 | ITERATE_RDEV(mddev, rdev, rtmp) | 2639 | ITERATE_RDEV(mddev, rdev, rtmp) |
2625 | if (rdev->raid_disk < 0 && | 2640 | if (rdev->raid_disk < 0 && |
2626 | !test_bit(Faulty, &rdev->flags)) | 2641 | !test_bit(Faulty, &rdev->flags)) |
2627 | spares++; | 2642 | spares++; |
2628 | if (conf->raid_disks + spares < raid_disks-1) | 2643 | |
2644 | if (spares < mddev->delta_disks-1) | ||
2629 | /* Not enough devices even to make a degraded array | 2645 | /* Not enough devices even to make a degraded array |
2630 | * of that size | 2646 | * of that size |
2631 | */ | 2647 | */ |
2632 | return -EINVAL; | 2648 | return -EINVAL; |
2633 | 2649 | ||
2634 | err = resize_stripes(conf, raid_disks); | ||
2635 | if (err) | ||
2636 | return err; | ||
2637 | |||
2638 | atomic_set(&conf->reshape_stripes, 0); | 2650 | atomic_set(&conf->reshape_stripes, 0); |
2639 | spin_lock_irq(&conf->device_lock); | 2651 | spin_lock_irq(&conf->device_lock); |
2640 | conf->previous_raid_disks = conf->raid_disks; | 2652 | conf->previous_raid_disks = conf->raid_disks; |
2641 | conf->raid_disks = raid_disks; | 2653 | conf->raid_disks += mddev->delta_disks; |
2642 | conf->expand_progress = 0; | 2654 | conf->expand_progress = 0; |
2643 | conf->expand_lo = 0; | 2655 | conf->expand_lo = 0; |
2644 | spin_unlock_irq(&conf->device_lock); | 2656 | spin_unlock_irq(&conf->device_lock); |
@@ -2660,12 +2672,8 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) | |||
2660 | break; | 2672 | break; |
2661 | } | 2673 | } |
2662 | 2674 | ||
2663 | mddev->degraded = (raid_disks - conf->previous_raid_disks) - added_devices; | 2675 | mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices; |
2664 | mddev->new_chunk = mddev->chunk_size; | 2676 | mddev->raid_disks = conf->raid_disks; |
2665 | mddev->new_layout = mddev->layout; | ||
2666 | mddev->new_level = mddev->level; | ||
2667 | mddev->raid_disks = raid_disks; | ||
2668 | mddev->delta_disks = raid_disks - conf->previous_raid_disks; | ||
2669 | mddev->reshape_position = 0; | 2677 | mddev->reshape_position = 0; |
2670 | mddev->sb_dirty = 1; | 2678 | mddev->sb_dirty = 1; |
2671 | 2679 | ||
@@ -2679,7 +2687,6 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) | |||
2679 | mddev->recovery = 0; | 2687 | mddev->recovery = 0; |
2680 | spin_lock_irq(&conf->device_lock); | 2688 | spin_lock_irq(&conf->device_lock); |
2681 | mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks; | 2689 | mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks; |
2682 | mddev->delta_disks = 0; | ||
2683 | conf->expand_progress = MaxSector; | 2690 | conf->expand_progress = MaxSector; |
2684 | spin_unlock_irq(&conf->device_lock); | 2691 | spin_unlock_irq(&conf->device_lock); |
2685 | return -EAGAIN; | 2692 | return -EAGAIN; |
@@ -2752,7 +2759,8 @@ static struct mdk_personality raid5_personality = | |||
2752 | .sync_request = sync_request, | 2759 | .sync_request = sync_request, |
2753 | .resize = raid5_resize, | 2760 | .resize = raid5_resize, |
2754 | #ifdef CONFIG_MD_RAID5_RESHAPE | 2761 | #ifdef CONFIG_MD_RAID5_RESHAPE |
2755 | .reshape = raid5_reshape, | 2762 | .check_reshape = raid5_check_reshape, |
2763 | .start_reshape = raid5_start_reshape, | ||
2756 | #endif | 2764 | #endif |
2757 | .quiesce = raid5_quiesce, | 2765 | .quiesce = raid5_quiesce, |
2758 | }; | 2766 | }; |
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 1a6f9f2f6282..002ee631fabb 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h | |||
@@ -261,7 +261,8 @@ struct mdk_personality | |||
261 | int (*spare_active) (mddev_t *mddev); | 261 | int (*spare_active) (mddev_t *mddev); |
262 | sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster); | 262 | sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster); |
263 | int (*resize) (mddev_t *mddev, sector_t sectors); | 263 | int (*resize) (mddev_t *mddev, sector_t sectors); |
264 | int (*reshape) (mddev_t *mddev, int raid_disks); | 264 | int (*check_reshape) (mddev_t *mddev); |
265 | int (*start_reshape) (mddev_t *mddev); | ||
265 | int (*reconfig) (mddev_t *mddev, int layout, int chunk_size); | 266 | int (*reconfig) (mddev_t *mddev, int layout, int chunk_size); |
266 | /* quiesce moves between quiescence states | 267 | /* quiesce moves between quiescence states |
267 | * 0 - fully active | 268 | * 0 - fully active |