diff options
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 87 |
1 files changed, 81 insertions, 6 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 81abefc172d9..d29215d966da 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -4049,6 +4049,8 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped | |||
4049 | sector_nr = conf->reshape_progress; | 4049 | sector_nr = conf->reshape_progress; |
4050 | sector_div(sector_nr, new_data_disks); | 4050 | sector_div(sector_nr, new_data_disks); |
4051 | if (sector_nr) { | 4051 | if (sector_nr) { |
4052 | mddev->curr_resync_completed = sector_nr; | ||
4053 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); | ||
4052 | *skipped = 1; | 4054 | *skipped = 1; |
4053 | return sector_nr; | 4055 | return sector_nr; |
4054 | } | 4056 | } |
@@ -4821,11 +4823,40 @@ static raid5_conf_t *setup_conf(mddev_t *mddev) | |||
4821 | return ERR_PTR(-ENOMEM); | 4823 | return ERR_PTR(-ENOMEM); |
4822 | } | 4824 | } |
4823 | 4825 | ||
4826 | |||
4827 | static int only_parity(int raid_disk, int algo, int raid_disks, int max_degraded) | ||
4828 | { | ||
4829 | switch (algo) { | ||
4830 | case ALGORITHM_PARITY_0: | ||
4831 | if (raid_disk < max_degraded) | ||
4832 | return 1; | ||
4833 | break; | ||
4834 | case ALGORITHM_PARITY_N: | ||
4835 | if (raid_disk >= raid_disks - max_degraded) | ||
4836 | return 1; | ||
4837 | break; | ||
4838 | case ALGORITHM_PARITY_0_6: | ||
4839 | if (raid_disk == 0 || | ||
4840 | raid_disk == raid_disks - 1) | ||
4841 | return 1; | ||
4842 | break; | ||
4843 | case ALGORITHM_LEFT_ASYMMETRIC_6: | ||
4844 | case ALGORITHM_RIGHT_ASYMMETRIC_6: | ||
4845 | case ALGORITHM_LEFT_SYMMETRIC_6: | ||
4846 | case ALGORITHM_RIGHT_SYMMETRIC_6: | ||
4847 | if (raid_disk == raid_disks - 1) | ||
4848 | return 1; | ||
4849 | } | ||
4850 | return 0; | ||
4851 | } | ||
4852 | |||
4824 | static int run(mddev_t *mddev) | 4853 | static int run(mddev_t *mddev) |
4825 | { | 4854 | { |
4826 | raid5_conf_t *conf; | 4855 | raid5_conf_t *conf; |
4827 | int working_disks = 0, chunk_size; | 4856 | int working_disks = 0, chunk_size; |
4857 | int dirty_parity_disks = 0; | ||
4828 | mdk_rdev_t *rdev; | 4858 | mdk_rdev_t *rdev; |
4859 | sector_t reshape_offset = 0; | ||
4829 | 4860 | ||
4830 | if (mddev->recovery_cp != MaxSector) | 4861 | if (mddev->recovery_cp != MaxSector) |
4831 | printk(KERN_NOTICE "raid5: %s is not clean" | 4862 | printk(KERN_NOTICE "raid5: %s is not clean" |
@@ -4859,6 +4890,7 @@ static int run(mddev_t *mddev) | |||
4859 | "on a stripe boundary\n"); | 4890 | "on a stripe boundary\n"); |
4860 | return -EINVAL; | 4891 | return -EINVAL; |
4861 | } | 4892 | } |
4893 | reshape_offset = here_new * mddev->new_chunk_sectors; | ||
4862 | /* here_new is the stripe we will write to */ | 4894 | /* here_new is the stripe we will write to */ |
4863 | here_old = mddev->reshape_position; | 4895 | here_old = mddev->reshape_position; |
4864 | sector_div(here_old, mddev->chunk_sectors * | 4896 | sector_div(here_old, mddev->chunk_sectors * |
@@ -4914,10 +4946,51 @@ static int run(mddev_t *mddev) | |||
4914 | /* | 4946 | /* |
4915 | * 0 for a fully functional array, 1 or 2 for a degraded array. | 4947 | * 0 for a fully functional array, 1 or 2 for a degraded array. |
4916 | */ | 4948 | */ |
4917 | list_for_each_entry(rdev, &mddev->disks, same_set) | 4949 | list_for_each_entry(rdev, &mddev->disks, same_set) { |
4918 | if (rdev->raid_disk >= 0 && | 4950 | if (rdev->raid_disk < 0) |
4919 | test_bit(In_sync, &rdev->flags)) | 4951 | continue; |
4952 | if (test_bit(In_sync, &rdev->flags)) | ||
4920 | working_disks++; | 4953 | working_disks++; |
4954 | /* This disc is not fully in-sync. However if it | ||
4955 | * just stored parity (beyond the recovery_offset), | ||
4956 | * when we don't need to be concerned about the | ||
4957 | * array being dirty. | ||
4958 | * When reshape goes 'backwards', we never have | ||
4959 | * partially completed devices, so we only need | ||
4960 | * to worry about reshape going forwards. | ||
4961 | */ | ||
4962 | /* Hack because v0.91 doesn't store recovery_offset properly. */ | ||
4963 | if (mddev->major_version == 0 && | ||
4964 | mddev->minor_version > 90) | ||
4965 | rdev->recovery_offset = reshape_offset; | ||
4966 | |||
4967 | printk("%d: w=%d pa=%d pr=%d m=%d a=%d r=%d op1=%d op2=%d\n", | ||
4968 | rdev->raid_disk, working_disks, conf->prev_algo, | ||
4969 | conf->previous_raid_disks, conf->max_degraded, | ||
4970 | conf->algorithm, conf->raid_disks, | ||
4971 | only_parity(rdev->raid_disk, | ||
4972 | conf->prev_algo, | ||
4973 | conf->previous_raid_disks, | ||
4974 | conf->max_degraded), | ||
4975 | only_parity(rdev->raid_disk, | ||
4976 | conf->algorithm, | ||
4977 | conf->raid_disks, | ||
4978 | conf->max_degraded)); | ||
4979 | if (rdev->recovery_offset < reshape_offset) { | ||
4980 | /* We need to check old and new layout */ | ||
4981 | if (!only_parity(rdev->raid_disk, | ||
4982 | conf->algorithm, | ||
4983 | conf->raid_disks, | ||
4984 | conf->max_degraded)) | ||
4985 | continue; | ||
4986 | } | ||
4987 | if (!only_parity(rdev->raid_disk, | ||
4988 | conf->prev_algo, | ||
4989 | conf->previous_raid_disks, | ||
4990 | conf->max_degraded)) | ||
4991 | continue; | ||
4992 | dirty_parity_disks++; | ||
4993 | } | ||
4921 | 4994 | ||
4922 | mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks) | 4995 | mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks) |
4923 | - working_disks); | 4996 | - working_disks); |
@@ -4933,7 +5006,7 @@ static int run(mddev_t *mddev) | |||
4933 | mddev->dev_sectors &= ~(mddev->chunk_sectors - 1); | 5006 | mddev->dev_sectors &= ~(mddev->chunk_sectors - 1); |
4934 | mddev->resync_max_sectors = mddev->dev_sectors; | 5007 | mddev->resync_max_sectors = mddev->dev_sectors; |
4935 | 5008 | ||
4936 | if (mddev->degraded > 0 && | 5009 | if (mddev->degraded > dirty_parity_disks && |
4937 | mddev->recovery_cp != MaxSector) { | 5010 | mddev->recovery_cp != MaxSector) { |
4938 | if (mddev->ok_start_degraded) | 5011 | if (mddev->ok_start_degraded) |
4939 | printk(KERN_WARNING | 5012 | printk(KERN_WARNING |
@@ -5359,9 +5432,11 @@ static int raid5_start_reshape(mddev_t *mddev) | |||
5359 | !test_bit(Faulty, &rdev->flags)) { | 5432 | !test_bit(Faulty, &rdev->flags)) { |
5360 | if (raid5_add_disk(mddev, rdev) == 0) { | 5433 | if (raid5_add_disk(mddev, rdev) == 0) { |
5361 | char nm[20]; | 5434 | char nm[20]; |
5362 | set_bit(In_sync, &rdev->flags); | 5435 | if (rdev->raid_disk >= conf->previous_raid_disks) |
5436 | set_bit(In_sync, &rdev->flags); | ||
5437 | else | ||
5438 | rdev->recovery_offset = 0; | ||
5363 | added_devices++; | 5439 | added_devices++; |
5364 | rdev->recovery_offset = 0; | ||
5365 | sprintf(nm, "rd%d", rdev->raid_disk); | 5440 | sprintf(nm, "rd%d", rdev->raid_disk); |
5366 | if (sysfs_create_link(&mddev->kobj, | 5441 | if (sysfs_create_link(&mddev->kobj, |
5367 | &rdev->kobj, nm)) | 5442 | &rdev->kobj, nm)) |