diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 81 |
1 files changed, 33 insertions, 48 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 0a3a4bdcd4af..aaa3d465de4e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -32,31 +32,21 @@ | |||
32 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 32 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/kthread.h> | 35 | #include <linux/kthread.h> |
38 | #include <linux/linkage.h> | ||
39 | #include <linux/raid/md.h> | 36 | #include <linux/raid/md.h> |
40 | #include <linux/raid/bitmap.h> | 37 | #include <linux/raid/bitmap.h> |
41 | #include <linux/sysctl.h> | 38 | #include <linux/sysctl.h> |
42 | #include <linux/buffer_head.h> /* for invalidate_bdev */ | 39 | #include <linux/buffer_head.h> /* for invalidate_bdev */ |
43 | #include <linux/poll.h> | 40 | #include <linux/poll.h> |
44 | #include <linux/mutex.h> | ||
45 | #include <linux/ctype.h> | 41 | #include <linux/ctype.h> |
46 | #include <linux/freezer.h> | 42 | #include <linux/hdreg.h> |
47 | 43 | #include <linux/proc_fs.h> | |
48 | #include <linux/init.h> | 44 | #include <linux/random.h> |
49 | 45 | #include <linux/reboot.h> | |
50 | #include <linux/file.h> | 46 | #include <linux/file.h> |
51 | 47 | #include <linux/delay.h> | |
52 | #ifdef CONFIG_KMOD | ||
53 | #include <linux/kmod.h> | ||
54 | #endif | ||
55 | |||
56 | #include <asm/unaligned.h> | ||
57 | 48 | ||
58 | #define MAJOR_NR MD_MAJOR | 49 | #define MAJOR_NR MD_MAJOR |
59 | #define MD_DRIVER | ||
60 | 50 | ||
61 | /* 63 partitions with the alternate major number (mdp) */ | 51 | /* 63 partitions with the alternate major number (mdp) */ |
62 | #define MdpMinorShift 6 | 52 | #define MdpMinorShift 6 |
@@ -66,7 +56,7 @@ | |||
66 | 56 | ||
67 | 57 | ||
68 | #ifndef MODULE | 58 | #ifndef MODULE |
69 | static void autostart_arrays (int part); | 59 | static void autostart_arrays(int part); |
70 | #endif | 60 | #endif |
71 | 61 | ||
72 | static LIST_HEAD(pers_list); | 62 | static LIST_HEAD(pers_list); |
@@ -212,7 +202,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock); | |||
212 | ) | 202 | ) |
213 | 203 | ||
214 | 204 | ||
215 | static int md_fail_request (struct request_queue *q, struct bio *bio) | 205 | static int md_fail_request(struct request_queue *q, struct bio *bio) |
216 | { | 206 | { |
217 | bio_io_error(bio); | 207 | bio_io_error(bio); |
218 | return 0; | 208 | return 0; |
@@ -2106,8 +2096,6 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) | |||
2106 | 2096 | ||
2107 | if (strict_strtoull(buf, 10, &size) < 0) | 2097 | if (strict_strtoull(buf, 10, &size) < 0) |
2108 | return -EINVAL; | 2098 | return -EINVAL; |
2109 | if (size < my_mddev->size) | ||
2110 | return -EINVAL; | ||
2111 | if (my_mddev->pers && rdev->raid_disk >= 0) { | 2099 | if (my_mddev->pers && rdev->raid_disk >= 0) { |
2112 | if (my_mddev->persistent) { | 2100 | if (my_mddev->persistent) { |
2113 | size = super_types[my_mddev->major_version]. | 2101 | size = super_types[my_mddev->major_version]. |
@@ -2118,9 +2106,9 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) | |||
2118 | size = (rdev->bdev->bd_inode->i_size >> 10); | 2106 | size = (rdev->bdev->bd_inode->i_size >> 10); |
2119 | size -= rdev->data_offset/2; | 2107 | size -= rdev->data_offset/2; |
2120 | } | 2108 | } |
2121 | if (size < my_mddev->size) | ||
2122 | return -EINVAL; /* component must fit device */ | ||
2123 | } | 2109 | } |
2110 | if (size < my_mddev->size) | ||
2111 | return -EINVAL; /* component must fit device */ | ||
2124 | 2112 | ||
2125 | rdev->size = size; | 2113 | rdev->size = size; |
2126 | if (size > oldsize && my_mddev->external) { | 2114 | if (size > oldsize && my_mddev->external) { |
@@ -2406,12 +2394,11 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len) | |||
2406 | int i; | 2394 | int i; |
2407 | unsigned long msec; | 2395 | unsigned long msec; |
2408 | char buf[30]; | 2396 | char buf[30]; |
2409 | char *e; | 2397 | |
2410 | /* remove a period, and count digits after it */ | 2398 | /* remove a period, and count digits after it */ |
2411 | if (len >= sizeof(buf)) | 2399 | if (len >= sizeof(buf)) |
2412 | return -EINVAL; | 2400 | return -EINVAL; |
2413 | strlcpy(buf, cbuf, len); | 2401 | strlcpy(buf, cbuf, sizeof(buf)); |
2414 | buf[len] = 0; | ||
2415 | for (i=0; i<len; i++) { | 2402 | for (i=0; i<len; i++) { |
2416 | if (dot) { | 2403 | if (dot) { |
2417 | if (isdigit(buf[i])) { | 2404 | if (isdigit(buf[i])) { |
@@ -2424,8 +2411,7 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len) | |||
2424 | buf[i] = 0; | 2411 | buf[i] = 0; |
2425 | } | 2412 | } |
2426 | } | 2413 | } |
2427 | msec = simple_strtoul(buf, &e, 10); | 2414 | if (strict_strtoul(buf, 10, &msec) < 0) |
2428 | if (e == buf || (*e && *e != '\n')) | ||
2429 | return -EINVAL; | 2415 | return -EINVAL; |
2430 | msec = (msec * 1000) / scale; | 2416 | msec = (msec * 1000) / scale; |
2431 | if (msec == 0) | 2417 | if (msec == 0) |
@@ -2727,9 +2713,9 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) | |||
2727 | break; | 2713 | break; |
2728 | case read_auto: | 2714 | case read_auto: |
2729 | if (mddev->pers) { | 2715 | if (mddev->pers) { |
2730 | if (mddev->ro != 1) | 2716 | if (mddev->ro == 0) |
2731 | err = do_md_stop(mddev, 1, 0); | 2717 | err = do_md_stop(mddev, 1, 0); |
2732 | else | 2718 | else if (mddev->ro == 1) |
2733 | err = restart_array(mddev); | 2719 | err = restart_array(mddev); |
2734 | if (err == 0) { | 2720 | if (err == 0) { |
2735 | mddev->ro = 2; | 2721 | mddev->ro = 2; |
@@ -2945,7 +2931,13 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len) | |||
2945 | { | 2931 | { |
2946 | int major, minor; | 2932 | int major, minor; |
2947 | char *e; | 2933 | char *e; |
2948 | if (!list_empty(&mddev->disks)) | 2934 | /* Changing the details of 'external' metadata is |
2935 | * always permitted. Otherwise there must be | ||
2936 | * no devices attached to the array. | ||
2937 | */ | ||
2938 | if (mddev->external && strncmp(buf, "external:", 9) == 0) | ||
2939 | ; | ||
2940 | else if (!list_empty(&mddev->disks)) | ||
2949 | return -EBUSY; | 2941 | return -EBUSY; |
2950 | 2942 | ||
2951 | if (cmd_match(buf, "none")) { | 2943 | if (cmd_match(buf, "none")) { |
@@ -3527,17 +3519,12 @@ static int do_md_run(mddev_t * mddev) | |||
3527 | return -EINVAL; | 3519 | return -EINVAL; |
3528 | } | 3520 | } |
3529 | /* | 3521 | /* |
3530 | * chunk-size has to be a power of 2 and multiples of PAGE_SIZE | 3522 | * chunk-size has to be a power of 2 |
3531 | */ | 3523 | */ |
3532 | if ( (1 << ffz(~chunk_size)) != chunk_size) { | 3524 | if ( (1 << ffz(~chunk_size)) != chunk_size) { |
3533 | printk(KERN_ERR "chunk_size of %d not valid\n", chunk_size); | 3525 | printk(KERN_ERR "chunk_size of %d not valid\n", chunk_size); |
3534 | return -EINVAL; | 3526 | return -EINVAL; |
3535 | } | 3527 | } |
3536 | if (chunk_size < PAGE_SIZE) { | ||
3537 | printk(KERN_ERR "too small chunk_size: %d < %ld\n", | ||
3538 | chunk_size, PAGE_SIZE); | ||
3539 | return -EINVAL; | ||
3540 | } | ||
3541 | 3528 | ||
3542 | /* devices must have minimum size of one chunk */ | 3529 | /* devices must have minimum size of one chunk */ |
3543 | rdev_for_each(rdev, tmp, mddev) { | 3530 | rdev_for_each(rdev, tmp, mddev) { |
@@ -3555,12 +3542,10 @@ static int do_md_run(mddev_t * mddev) | |||
3555 | } | 3542 | } |
3556 | } | 3543 | } |
3557 | 3544 | ||
3558 | #ifdef CONFIG_KMOD | ||
3559 | if (mddev->level != LEVEL_NONE) | 3545 | if (mddev->level != LEVEL_NONE) |
3560 | request_module("md-level-%d", mddev->level); | 3546 | request_module("md-level-%d", mddev->level); |
3561 | else if (mddev->clevel[0]) | 3547 | else if (mddev->clevel[0]) |
3562 | request_module("md-%s", mddev->clevel); | 3548 | request_module("md-%s", mddev->clevel); |
3563 | #endif | ||
3564 | 3549 | ||
3565 | /* | 3550 | /* |
3566 | * Drop all container device buffers, from now on | 3551 | * Drop all container device buffers, from now on |
@@ -3971,10 +3956,10 @@ static void autorun_array(mddev_t *mddev) | |||
3971 | } | 3956 | } |
3972 | printk("\n"); | 3957 | printk("\n"); |
3973 | 3958 | ||
3974 | err = do_md_run (mddev); | 3959 | err = do_md_run(mddev); |
3975 | if (err) { | 3960 | if (err) { |
3976 | printk(KERN_WARNING "md: do_md_run() returned %d\n", err); | 3961 | printk(KERN_WARNING "md: do_md_run() returned %d\n", err); |
3977 | do_md_stop (mddev, 0, 0); | 3962 | do_md_stop(mddev, 0, 0); |
3978 | } | 3963 | } |
3979 | } | 3964 | } |
3980 | 3965 | ||
@@ -4333,7 +4318,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) | |||
4333 | 4318 | ||
4334 | if (!(info->state & (1<<MD_DISK_FAULTY))) { | 4319 | if (!(info->state & (1<<MD_DISK_FAULTY))) { |
4335 | int err; | 4320 | int err; |
4336 | rdev = md_import_device (dev, -1, 0); | 4321 | rdev = md_import_device(dev, -1, 0); |
4337 | if (IS_ERR(rdev)) { | 4322 | if (IS_ERR(rdev)) { |
4338 | printk(KERN_WARNING | 4323 | printk(KERN_WARNING |
4339 | "md: error, md_import_device() returned %ld\n", | 4324 | "md: error, md_import_device() returned %ld\n", |
@@ -4415,7 +4400,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) | |||
4415 | return -EINVAL; | 4400 | return -EINVAL; |
4416 | } | 4401 | } |
4417 | 4402 | ||
4418 | rdev = md_import_device (dev, -1, 0); | 4403 | rdev = md_import_device(dev, -1, 0); |
4419 | if (IS_ERR(rdev)) { | 4404 | if (IS_ERR(rdev)) { |
4420 | printk(KERN_WARNING | 4405 | printk(KERN_WARNING |
4421 | "md: error, md_import_device() returned %ld\n", | 4406 | "md: error, md_import_device() returned %ld\n", |
@@ -4934,11 +4919,11 @@ static int md_ioctl(struct inode *inode, struct file *file, | |||
4934 | goto done_unlock; | 4919 | goto done_unlock; |
4935 | 4920 | ||
4936 | case STOP_ARRAY: | 4921 | case STOP_ARRAY: |
4937 | err = do_md_stop (mddev, 0, 1); | 4922 | err = do_md_stop(mddev, 0, 1); |
4938 | goto done_unlock; | 4923 | goto done_unlock; |
4939 | 4924 | ||
4940 | case STOP_ARRAY_RO: | 4925 | case STOP_ARRAY_RO: |
4941 | err = do_md_stop (mddev, 1, 1); | 4926 | err = do_md_stop(mddev, 1, 1); |
4942 | goto done_unlock; | 4927 | goto done_unlock; |
4943 | 4928 | ||
4944 | } | 4929 | } |
@@ -4987,7 +4972,7 @@ static int md_ioctl(struct inode *inode, struct file *file, | |||
4987 | goto done_unlock; | 4972 | goto done_unlock; |
4988 | 4973 | ||
4989 | case RUN_ARRAY: | 4974 | case RUN_ARRAY: |
4990 | err = do_md_run (mddev); | 4975 | err = do_md_run(mddev); |
4991 | goto done_unlock; | 4976 | goto done_unlock; |
4992 | 4977 | ||
4993 | case SET_BITMAP_FILE: | 4978 | case SET_BITMAP_FILE: |
@@ -5425,11 +5410,11 @@ static int md_seq_show(struct seq_file *seq, void *v) | |||
5425 | seq_printf(seq, " super non-persistent"); | 5410 | seq_printf(seq, " super non-persistent"); |
5426 | 5411 | ||
5427 | if (mddev->pers) { | 5412 | if (mddev->pers) { |
5428 | mddev->pers->status (seq, mddev); | 5413 | mddev->pers->status(seq, mddev); |
5429 | seq_printf(seq, "\n "); | 5414 | seq_printf(seq, "\n "); |
5430 | if (mddev->pers->sync_request) { | 5415 | if (mddev->pers->sync_request) { |
5431 | if (mddev->curr_resync > 2) { | 5416 | if (mddev->curr_resync > 2) { |
5432 | status_resync (seq, mddev); | 5417 | status_resync(seq, mddev); |
5433 | seq_printf(seq, "\n "); | 5418 | seq_printf(seq, "\n "); |
5434 | } else if (mddev->curr_resync == 1 || mddev->curr_resync == 2) | 5419 | } else if (mddev->curr_resync == 1 || mddev->curr_resync == 2) |
5435 | seq_printf(seq, "\tresync=DELAYED\n "); | 5420 | seq_printf(seq, "\tresync=DELAYED\n "); |
@@ -6260,7 +6245,7 @@ static int md_notify_reboot(struct notifier_block *this, | |||
6260 | * appears to still be in use. Hence | 6245 | * appears to still be in use. Hence |
6261 | * the '100'. | 6246 | * the '100'. |
6262 | */ | 6247 | */ |
6263 | do_md_stop (mddev, 1, 100); | 6248 | do_md_stop(mddev, 1, 100); |
6264 | mddev_unlock(mddev); | 6249 | mddev_unlock(mddev); |
6265 | } | 6250 | } |
6266 | /* | 6251 | /* |
@@ -6304,7 +6289,7 @@ static int __init md_init(void) | |||
6304 | raid_table_header = register_sysctl_table(raid_root_table); | 6289 | raid_table_header = register_sysctl_table(raid_root_table); |
6305 | 6290 | ||
6306 | md_geninit(); | 6291 | md_geninit(); |
6307 | return (0); | 6292 | return 0; |
6308 | } | 6293 | } |
6309 | 6294 | ||
6310 | 6295 | ||