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 | }; |
