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