aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2005-11-09 00:39:36 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-09 10:56:38 -0500
commitf91de92ed6bfb70a3ff607558c910c7bf34d45e9 (patch)
tree7891da2296aba0302b48220bdd291acc0e92e810 /drivers/md/md.c
parent19133a4298223422742db7b5f940e8c54c6a1846 (diff)
[PATCH] md: allow md arrays to be started read-only (module parameter).
When an md array is started, the superblock will be written, and resync may commense. This is not good if you want to be completely read-only as, for example, when preparing to resume from a suspend-to-disk image. So introduce a module parameter "start_ro" which can be set to '1' at boot, at module load, or via /sys/module/md_mod/parameters/start_ro When this is set, new arrays get an 'auto-ro' mode, which disables all internal io (superblock updates, resync, recovery) and is automatically switched to 'rw' when the first write request arrives. The array can be set to true 'ro' mode using 'mdadm -r' before the first write request, or resync can be started without a write using 'mdadm -w'. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c59
1 files changed, 51 insertions, 8 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 8238c1c0ec09..d002b8301fc2 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -131,6 +131,8 @@ static ctl_table raid_root_table[] = {
131 131
132static struct block_device_operations md_fops; 132static struct block_device_operations md_fops;
133 133
134static int start_readonly;
135
134/* 136/*
135 * Enables to iterate over all existing md arrays 137 * Enables to iterate over all existing md arrays
136 * all_mddevs_lock protects this list. 138 * all_mddevs_lock protects this list.
@@ -2029,6 +2031,9 @@ static int do_md_run(mddev_t * mddev)
2029 mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ 2031 mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
2030 mddev->barriers_work = 1; 2032 mddev->barriers_work = 1;
2031 2033
2034 if (start_readonly)
2035 mddev->ro = 2; /* read-only, but switch on first write */
2036
2032 /* before we start the array running, initialise the bitmap */ 2037 /* before we start the array running, initialise the bitmap */
2033 err = bitmap_create(mddev); 2038 err = bitmap_create(mddev);
2034 if (err) 2039 if (err)
@@ -2141,7 +2146,7 @@ static int do_md_stop(mddev_t * mddev, int ro)
2141 2146
2142 if (ro) { 2147 if (ro) {
2143 err = -ENXIO; 2148 err = -ENXIO;
2144 if (mddev->ro) 2149 if (mddev->ro==1)
2145 goto out; 2150 goto out;
2146 mddev->ro = 1; 2151 mddev->ro = 1;
2147 } else { 2152 } else {
@@ -3258,12 +3263,22 @@ static int md_ioctl(struct inode *inode, struct file *file,
3258 3263
3259 /* 3264 /*
3260 * The remaining ioctls are changing the state of the 3265 * The remaining ioctls are changing the state of the
3261 * superblock, so we do not allow read-only arrays 3266 * superblock, so we do not allow them on read-only arrays.
3262 * here: 3267 * However non-MD ioctls (e.g. get-size) will still come through
3268 * here and hit the 'default' below, so only disallow
3269 * 'md' ioctls, and switch to rw mode if started auto-readonly.
3263 */ 3270 */
3264 if (mddev->ro) { 3271 if (_IOC_TYPE(cmd) == MD_MAJOR &&
3265 err = -EROFS; 3272 mddev->ro && mddev->pers) {
3266 goto abort_unlock; 3273 if (mddev->ro == 2) {
3274 mddev->ro = 0;
3275 set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
3276 md_wakeup_thread(mddev->thread);
3277
3278 } else {
3279 err = -EROFS;
3280 goto abort_unlock;
3281 }
3267 } 3282 }
3268 3283
3269 switch (cmd) 3284 switch (cmd)
@@ -3651,8 +3666,10 @@ static int md_seq_show(struct seq_file *seq, void *v)
3651 seq_printf(seq, "%s : %sactive", mdname(mddev), 3666 seq_printf(seq, "%s : %sactive", mdname(mddev),
3652 mddev->pers ? "" : "in"); 3667 mddev->pers ? "" : "in");
3653 if (mddev->pers) { 3668 if (mddev->pers) {
3654 if (mddev->ro) 3669 if (mddev->ro==1)
3655 seq_printf(seq, " (read-only)"); 3670 seq_printf(seq, " (read-only)");
3671 if (mddev->ro==2)
3672 seq_printf(seq, "(auto-read-only)");
3656 seq_printf(seq, " %s", mddev->pers->name); 3673 seq_printf(seq, " %s", mddev->pers->name);
3657 } 3674 }
3658 3675
@@ -3696,7 +3713,9 @@ static int md_seq_show(struct seq_file *seq, void *v)
3696 status_resync (seq, mddev); 3713 status_resync (seq, mddev);
3697 seq_printf(seq, "\n "); 3714 seq_printf(seq, "\n ");
3698 } else if (mddev->curr_resync == 1 || mddev->curr_resync == 2) 3715 } else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
3699 seq_printf(seq, " resync=DELAYED\n "); 3716 seq_printf(seq, "\tresync=DELAYED\n ");
3717 else if (mddev->recovery_cp < MaxSector)
3718 seq_printf(seq, "\tresync=PENDING\n ");
3700 } else 3719 } else
3701 seq_printf(seq, "\n "); 3720 seq_printf(seq, "\n ");
3702 3721
@@ -3833,6 +3852,13 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
3833 if (bio_data_dir(bi) != WRITE) 3852 if (bio_data_dir(bi) != WRITE)
3834 return; 3853 return;
3835 3854
3855 BUG_ON(mddev->ro == 1);
3856 if (mddev->ro == 2) {
3857 /* need to switch to read/write */
3858 mddev->ro = 0;
3859 set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
3860 md_wakeup_thread(mddev->thread);
3861 }
3836 atomic_inc(&mddev->writes_pending); 3862 atomic_inc(&mddev->writes_pending);
3837 if (mddev->in_sync) { 3863 if (mddev->in_sync) {
3838 spin_lock_irq(&mddev->write_lock); 3864 spin_lock_irq(&mddev->write_lock);
@@ -4431,6 +4457,23 @@ static __exit void md_exit(void)
4431module_init(md_init) 4457module_init(md_init)
4432module_exit(md_exit) 4458module_exit(md_exit)
4433 4459
4460static int get_ro(char *buffer, struct kernel_param *kp)
4461{
4462 return sprintf(buffer, "%d", start_readonly);
4463}
4464static int set_ro(const char *val, struct kernel_param *kp)
4465{
4466 char *e;
4467 int num = simple_strtoul(val, &e, 10);
4468 if (*val && (*e == '\0' || *e == '\n')) {
4469 start_readonly = num;
4470 return 0;;
4471 }
4472 return -EINVAL;
4473}
4474
4475module_param_call(start_ro, set_ro, get_ro, NULL, 0600);
4476
4434EXPORT_SYMBOL(register_md_personality); 4477EXPORT_SYMBOL(register_md_personality);
4435EXPORT_SYMBOL(unregister_md_personality); 4478EXPORT_SYMBOL(unregister_md_personality);
4436EXPORT_SYMBOL(md_error); 4479EXPORT_SYMBOL(md_error);