diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 160 |
1 files changed, 122 insertions, 38 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 2b4315d7e5d6..65814b0340cb 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -33,6 +33,7 @@ | |||
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/kernel.h> | ||
36 | #include <linux/kthread.h> | 37 | #include <linux/kthread.h> |
37 | #include <linux/linkage.h> | 38 | #include <linux/linkage.h> |
38 | #include <linux/raid/md.h> | 39 | #include <linux/raid/md.h> |
@@ -273,6 +274,7 @@ static mddev_t * mddev_find(dev_t unit) | |||
273 | atomic_set(&new->active, 1); | 274 | atomic_set(&new->active, 1); |
274 | spin_lock_init(&new->write_lock); | 275 | spin_lock_init(&new->write_lock); |
275 | init_waitqueue_head(&new->sb_wait); | 276 | init_waitqueue_head(&new->sb_wait); |
277 | new->reshape_position = MaxSector; | ||
276 | 278 | ||
277 | new->queue = blk_alloc_queue(GFP_KERNEL); | 279 | new->queue = blk_alloc_queue(GFP_KERNEL); |
278 | if (!new->queue) { | 280 | if (!new->queue) { |
@@ -589,14 +591,41 @@ abort: | |||
589 | return ret; | 591 | return ret; |
590 | } | 592 | } |
591 | 593 | ||
594 | |||
595 | static u32 md_csum_fold(u32 csum) | ||
596 | { | ||
597 | csum = (csum & 0xffff) + (csum >> 16); | ||
598 | return (csum & 0xffff) + (csum >> 16); | ||
599 | } | ||
600 | |||
592 | static unsigned int calc_sb_csum(mdp_super_t * sb) | 601 | static unsigned int calc_sb_csum(mdp_super_t * sb) |
593 | { | 602 | { |
603 | u64 newcsum = 0; | ||
604 | u32 *sb32 = (u32*)sb; | ||
605 | int i; | ||
594 | unsigned int disk_csum, csum; | 606 | unsigned int disk_csum, csum; |
595 | 607 | ||
596 | disk_csum = sb->sb_csum; | 608 | disk_csum = sb->sb_csum; |
597 | sb->sb_csum = 0; | 609 | sb->sb_csum = 0; |
598 | csum = csum_partial((void *)sb, MD_SB_BYTES, 0); | 610 | |
611 | for (i = 0; i < MD_SB_BYTES/4 ; i++) | ||
612 | newcsum += sb32[i]; | ||
613 | csum = (newcsum & 0xffffffff) + (newcsum>>32); | ||
614 | |||
615 | |||
616 | #ifdef CONFIG_ALPHA | ||
617 | /* This used to use csum_partial, which was wrong for several | ||
618 | * reasons including that different results are returned on | ||
619 | * different architectures. It isn't critical that we get exactly | ||
620 | * the same return value as before (we always csum_fold before | ||
621 | * testing, and that removes any differences). However as we | ||
622 | * know that csum_partial always returned a 16bit value on | ||
623 | * alphas, do a fold to maximise conformity to previous behaviour. | ||
624 | */ | ||
625 | sb->sb_csum = md_csum_fold(disk_csum); | ||
626 | #else | ||
599 | sb->sb_csum = disk_csum; | 627 | sb->sb_csum = disk_csum; |
628 | #endif | ||
600 | return csum; | 629 | return csum; |
601 | } | 630 | } |
602 | 631 | ||
@@ -684,7 +713,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version | |||
684 | if (sb->raid_disks <= 0) | 713 | if (sb->raid_disks <= 0) |
685 | goto abort; | 714 | goto abort; |
686 | 715 | ||
687 | if (csum_fold(calc_sb_csum(sb)) != csum_fold(sb->sb_csum)) { | 716 | if (md_csum_fold(calc_sb_csum(sb)) != md_csum_fold(sb->sb_csum)) { |
688 | printk(KERN_WARNING "md: invalid superblock checksum on %s\n", | 717 | printk(KERN_WARNING "md: invalid superblock checksum on %s\n", |
689 | b); | 718 | b); |
690 | goto abort; | 719 | goto abort; |
@@ -694,6 +723,17 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version | |||
694 | rdev->data_offset = 0; | 723 | rdev->data_offset = 0; |
695 | rdev->sb_size = MD_SB_BYTES; | 724 | rdev->sb_size = MD_SB_BYTES; |
696 | 725 | ||
726 | if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) { | ||
727 | if (sb->level != 1 && sb->level != 4 | ||
728 | && sb->level != 5 && sb->level != 6 | ||
729 | && sb->level != 10) { | ||
730 | /* FIXME use a better test */ | ||
731 | printk(KERN_WARNING | ||
732 | "md: bitmaps not supported for this level.\n"); | ||
733 | goto abort; | ||
734 | } | ||
735 | } | ||
736 | |||
697 | if (sb->level == LEVEL_MULTIPATH) | 737 | if (sb->level == LEVEL_MULTIPATH) |
698 | rdev->desc_nr = -1; | 738 | rdev->desc_nr = -1; |
699 | else | 739 | else |
@@ -792,16 +832,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) | |||
792 | mddev->max_disks = MD_SB_DISKS; | 832 | mddev->max_disks = MD_SB_DISKS; |
793 | 833 | ||
794 | if (sb->state & (1<<MD_SB_BITMAP_PRESENT) && | 834 | if (sb->state & (1<<MD_SB_BITMAP_PRESENT) && |
795 | mddev->bitmap_file == NULL) { | 835 | mddev->bitmap_file == NULL) |
796 | if (mddev->level != 1 && mddev->level != 4 | ||
797 | && mddev->level != 5 && mddev->level != 6 | ||
798 | && mddev->level != 10) { | ||
799 | /* FIXME use a better test */ | ||
800 | printk(KERN_WARNING "md: bitmaps not supported for this level.\n"); | ||
801 | return -EINVAL; | ||
802 | } | ||
803 | mddev->bitmap_offset = mddev->default_bitmap_offset; | 836 | mddev->bitmap_offset = mddev->default_bitmap_offset; |
804 | } | ||
805 | 837 | ||
806 | } else if (mddev->pers == NULL) { | 838 | } else if (mddev->pers == NULL) { |
807 | /* Insist on good event counter while assembling */ | 839 | /* Insist on good event counter while assembling */ |
@@ -1058,6 +1090,18 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) | |||
1058 | bdevname(rdev->bdev,b)); | 1090 | bdevname(rdev->bdev,b)); |
1059 | return -EINVAL; | 1091 | return -EINVAL; |
1060 | } | 1092 | } |
1093 | if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)) { | ||
1094 | if (sb->level != cpu_to_le32(1) && | ||
1095 | sb->level != cpu_to_le32(4) && | ||
1096 | sb->level != cpu_to_le32(5) && | ||
1097 | sb->level != cpu_to_le32(6) && | ||
1098 | sb->level != cpu_to_le32(10)) { | ||
1099 | printk(KERN_WARNING | ||
1100 | "md: bitmaps not supported for this level.\n"); | ||
1101 | return -EINVAL; | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1061 | rdev->preferred_minor = 0xffff; | 1105 | rdev->preferred_minor = 0xffff; |
1062 | rdev->data_offset = le64_to_cpu(sb->data_offset); | 1106 | rdev->data_offset = le64_to_cpu(sb->data_offset); |
1063 | atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read)); | 1107 | atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read)); |
@@ -1141,14 +1185,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1141 | mddev->max_disks = (4096-256)/2; | 1185 | mddev->max_disks = (4096-256)/2; |
1142 | 1186 | ||
1143 | if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) && | 1187 | if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) && |
1144 | mddev->bitmap_file == NULL ) { | 1188 | mddev->bitmap_file == NULL ) |
1145 | if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6 | ||
1146 | && mddev->level != 10) { | ||
1147 | printk(KERN_WARNING "md: bitmaps not supported for this level.\n"); | ||
1148 | return -EINVAL; | ||
1149 | } | ||
1150 | mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset); | 1189 | mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset); |
1151 | } | 1190 | |
1152 | if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) { | 1191 | if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) { |
1153 | mddev->reshape_position = le64_to_cpu(sb->reshape_position); | 1192 | mddev->reshape_position = le64_to_cpu(sb->reshape_position); |
1154 | mddev->delta_disks = le32_to_cpu(sb->delta_disks); | 1193 | mddev->delta_disks = le32_to_cpu(sb->delta_disks); |
@@ -2204,6 +2243,10 @@ static ssize_t | |||
2204 | layout_show(mddev_t *mddev, char *page) | 2243 | layout_show(mddev_t *mddev, char *page) |
2205 | { | 2244 | { |
2206 | /* just a number, not meaningful for all levels */ | 2245 | /* just a number, not meaningful for all levels */ |
2246 | if (mddev->reshape_position != MaxSector && | ||
2247 | mddev->layout != mddev->new_layout) | ||
2248 | return sprintf(page, "%d (%d)\n", | ||
2249 | mddev->new_layout, mddev->layout); | ||
2207 | return sprintf(page, "%d\n", mddev->layout); | 2250 | return sprintf(page, "%d\n", mddev->layout); |
2208 | } | 2251 | } |
2209 | 2252 | ||
@@ -2212,13 +2255,16 @@ layout_store(mddev_t *mddev, const char *buf, size_t len) | |||
2212 | { | 2255 | { |
2213 | char *e; | 2256 | char *e; |
2214 | unsigned long n = simple_strtoul(buf, &e, 10); | 2257 | unsigned long n = simple_strtoul(buf, &e, 10); |
2215 | if (mddev->pers) | ||
2216 | return -EBUSY; | ||
2217 | 2258 | ||
2218 | if (!*buf || (*e && *e != '\n')) | 2259 | if (!*buf || (*e && *e != '\n')) |
2219 | return -EINVAL; | 2260 | return -EINVAL; |
2220 | 2261 | ||
2221 | mddev->layout = n; | 2262 | if (mddev->pers) |
2263 | return -EBUSY; | ||
2264 | if (mddev->reshape_position != MaxSector) | ||
2265 | mddev->new_layout = n; | ||
2266 | else | ||
2267 | mddev->layout = n; | ||
2222 | return len; | 2268 | return len; |
2223 | } | 2269 | } |
2224 | static struct md_sysfs_entry md_layout = | 2270 | static struct md_sysfs_entry md_layout = |
@@ -2230,6 +2276,10 @@ raid_disks_show(mddev_t *mddev, char *page) | |||
2230 | { | 2276 | { |
2231 | if (mddev->raid_disks == 0) | 2277 | if (mddev->raid_disks == 0) |
2232 | return 0; | 2278 | return 0; |
2279 | if (mddev->reshape_position != MaxSector && | ||
2280 | mddev->delta_disks != 0) | ||
2281 | return sprintf(page, "%d (%d)\n", mddev->raid_disks, | ||
2282 | mddev->raid_disks - mddev->delta_disks); | ||
2233 | return sprintf(page, "%d\n", mddev->raid_disks); | 2283 | return sprintf(page, "%d\n", mddev->raid_disks); |
2234 | } | 2284 | } |
2235 | 2285 | ||
@@ -2247,7 +2297,11 @@ raid_disks_store(mddev_t *mddev, const char *buf, size_t len) | |||
2247 | 2297 | ||
2248 | if (mddev->pers) | 2298 | if (mddev->pers) |
2249 | rv = update_raid_disks(mddev, n); | 2299 | rv = update_raid_disks(mddev, n); |
2250 | else | 2300 | else if (mddev->reshape_position != MaxSector) { |
2301 | int olddisks = mddev->raid_disks - mddev->delta_disks; | ||
2302 | mddev->delta_disks = n - olddisks; | ||
2303 | mddev->raid_disks = n; | ||
2304 | } else | ||
2251 | mddev->raid_disks = n; | 2305 | mddev->raid_disks = n; |
2252 | return rv ? rv : len; | 2306 | return rv ? rv : len; |
2253 | } | 2307 | } |
@@ -2257,6 +2311,10 @@ __ATTR(raid_disks, S_IRUGO|S_IWUSR, raid_disks_show, raid_disks_store); | |||
2257 | static ssize_t | 2311 | static ssize_t |
2258 | chunk_size_show(mddev_t *mddev, char *page) | 2312 | chunk_size_show(mddev_t *mddev, char *page) |
2259 | { | 2313 | { |
2314 | if (mddev->reshape_position != MaxSector && | ||
2315 | mddev->chunk_size != mddev->new_chunk) | ||
2316 | return sprintf(page, "%d (%d)\n", mddev->new_chunk, | ||
2317 | mddev->chunk_size); | ||
2260 | return sprintf(page, "%d\n", mddev->chunk_size); | 2318 | return sprintf(page, "%d\n", mddev->chunk_size); |
2261 | } | 2319 | } |
2262 | 2320 | ||
@@ -2267,12 +2325,15 @@ chunk_size_store(mddev_t *mddev, const char *buf, size_t len) | |||
2267 | char *e; | 2325 | char *e; |
2268 | unsigned long n = simple_strtoul(buf, &e, 10); | 2326 | unsigned long n = simple_strtoul(buf, &e, 10); |
2269 | 2327 | ||
2270 | if (mddev->pers) | ||
2271 | return -EBUSY; | ||
2272 | if (!*buf || (*e && *e != '\n')) | 2328 | if (!*buf || (*e && *e != '\n')) |
2273 | return -EINVAL; | 2329 | return -EINVAL; |
2274 | 2330 | ||
2275 | mddev->chunk_size = n; | 2331 | if (mddev->pers) |
2332 | return -EBUSY; | ||
2333 | else if (mddev->reshape_position != MaxSector) | ||
2334 | mddev->new_chunk = n; | ||
2335 | else | ||
2336 | mddev->chunk_size = n; | ||
2276 | return len; | 2337 | return len; |
2277 | } | 2338 | } |
2278 | static struct md_sysfs_entry md_chunk_size = | 2339 | static struct md_sysfs_entry md_chunk_size = |
@@ -2637,8 +2698,7 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len) | |||
2637 | minor = simple_strtoul(buf, &e, 10); | 2698 | minor = simple_strtoul(buf, &e, 10); |
2638 | if (e==buf || (*e && *e != '\n') ) | 2699 | if (e==buf || (*e && *e != '\n') ) |
2639 | return -EINVAL; | 2700 | return -EINVAL; |
2640 | if (major >= sizeof(super_types)/sizeof(super_types[0]) || | 2701 | if (major >= ARRAY_SIZE(super_types) || super_types[major].name == NULL) |
2641 | super_types[major].name == NULL) | ||
2642 | return -ENOENT; | 2702 | return -ENOENT; |
2643 | mddev->major_version = major; | 2703 | mddev->major_version = major; |
2644 | mddev->minor_version = minor; | 2704 | mddev->minor_version = minor; |
@@ -2859,6 +2919,37 @@ suspend_hi_store(mddev_t *mddev, const char *buf, size_t len) | |||
2859 | static struct md_sysfs_entry md_suspend_hi = | 2919 | static struct md_sysfs_entry md_suspend_hi = |
2860 | __ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store); | 2920 | __ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store); |
2861 | 2921 | ||
2922 | static ssize_t | ||
2923 | reshape_position_show(mddev_t *mddev, char *page) | ||
2924 | { | ||
2925 | if (mddev->reshape_position != MaxSector) | ||
2926 | return sprintf(page, "%llu\n", | ||
2927 | (unsigned long long)mddev->reshape_position); | ||
2928 | strcpy(page, "none\n"); | ||
2929 | return 5; | ||
2930 | } | ||
2931 | |||
2932 | static ssize_t | ||
2933 | reshape_position_store(mddev_t *mddev, const char *buf, size_t len) | ||
2934 | { | ||
2935 | char *e; | ||
2936 | unsigned long long new = simple_strtoull(buf, &e, 10); | ||
2937 | if (mddev->pers) | ||
2938 | return -EBUSY; | ||
2939 | if (buf == e || (*e && *e != '\n')) | ||
2940 | return -EINVAL; | ||
2941 | mddev->reshape_position = new; | ||
2942 | mddev->delta_disks = 0; | ||
2943 | mddev->new_level = mddev->level; | ||
2944 | mddev->new_layout = mddev->layout; | ||
2945 | mddev->new_chunk = mddev->chunk_size; | ||
2946 | return len; | ||
2947 | } | ||
2948 | |||
2949 | static struct md_sysfs_entry md_reshape_position = | ||
2950 | __ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show, | ||
2951 | reshape_position_store); | ||
2952 | |||
2862 | 2953 | ||
2863 | static struct attribute *md_default_attrs[] = { | 2954 | static struct attribute *md_default_attrs[] = { |
2864 | &md_level.attr, | 2955 | &md_level.attr, |
@@ -2871,6 +2962,7 @@ static struct attribute *md_default_attrs[] = { | |||
2871 | &md_new_device.attr, | 2962 | &md_new_device.attr, |
2872 | &md_safe_delay.attr, | 2963 | &md_safe_delay.attr, |
2873 | &md_array_state.attr, | 2964 | &md_array_state.attr, |
2965 | &md_reshape_position.attr, | ||
2874 | NULL, | 2966 | NULL, |
2875 | }; | 2967 | }; |
2876 | 2968 | ||
@@ -3409,6 +3501,7 @@ static int do_md_stop(mddev_t * mddev, int mode) | |||
3409 | mddev->size = 0; | 3501 | mddev->size = 0; |
3410 | mddev->raid_disks = 0; | 3502 | mddev->raid_disks = 0; |
3411 | mddev->recovery_cp = 0; | 3503 | mddev->recovery_cp = 0; |
3504 | mddev->reshape_position = MaxSector; | ||
3412 | 3505 | ||
3413 | } else if (mddev->pers) | 3506 | } else if (mddev->pers) |
3414 | printk(KERN_INFO "md: %s switched to read-only mode.\n", | 3507 | printk(KERN_INFO "md: %s switched to read-only mode.\n", |
@@ -4019,7 +4112,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) | |||
4019 | if (info->raid_disks == 0) { | 4112 | if (info->raid_disks == 0) { |
4020 | /* just setting version number for superblock loading */ | 4113 | /* just setting version number for superblock loading */ |
4021 | if (info->major_version < 0 || | 4114 | if (info->major_version < 0 || |
4022 | info->major_version >= sizeof(super_types)/sizeof(super_types[0]) || | 4115 | info->major_version >= ARRAY_SIZE(super_types) || |
4023 | super_types[info->major_version].name == NULL) { | 4116 | super_types[info->major_version].name == NULL) { |
4024 | /* maybe try to auto-load a module? */ | 4117 | /* maybe try to auto-load a module? */ |
4025 | printk(KERN_INFO | 4118 | printk(KERN_INFO |
@@ -4941,15 +5034,6 @@ static int md_seq_open(struct inode *inode, struct file *file) | |||
4941 | return error; | 5034 | return error; |
4942 | } | 5035 | } |
4943 | 5036 | ||
4944 | static int md_seq_release(struct inode *inode, struct file *file) | ||
4945 | { | ||
4946 | struct seq_file *m = file->private_data; | ||
4947 | struct mdstat_info *mi = m->private; | ||
4948 | m->private = NULL; | ||
4949 | kfree(mi); | ||
4950 | return seq_release(inode, file); | ||
4951 | } | ||
4952 | |||
4953 | static unsigned int mdstat_poll(struct file *filp, poll_table *wait) | 5037 | static unsigned int mdstat_poll(struct file *filp, poll_table *wait) |
4954 | { | 5038 | { |
4955 | struct seq_file *m = filp->private_data; | 5039 | struct seq_file *m = filp->private_data; |
@@ -4971,7 +5055,7 @@ static const struct file_operations md_seq_fops = { | |||
4971 | .open = md_seq_open, | 5055 | .open = md_seq_open, |
4972 | .read = seq_read, | 5056 | .read = seq_read, |
4973 | .llseek = seq_lseek, | 5057 | .llseek = seq_lseek, |
4974 | .release = md_seq_release, | 5058 | .release = seq_release_private, |
4975 | .poll = mdstat_poll, | 5059 | .poll = mdstat_poll, |
4976 | }; | 5060 | }; |
4977 | 5061 | ||