aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2010-05-12 08:25:37 +1000
committerGreg Kroah-Hartman <gregkh@suse.de>2010-07-05 11:08:44 -0700
commit789242303b22bddc1cd03a0c013bfdc091556d83 (patch)
tree9a277434e72b550407efec099ab4be18f1abae76 /drivers
parentf2a41e6807357c237ec2bbd61e79cb1558e48b8a (diff)
md: set mddev readonly flag on blkdev BLKROSET ioctl
commit e2218350465e7e0931676b4849b594c978437bce upstream. When the user sets the block device to readwrite then the mddev should follow suit. Otherwise, the BUG_ON in md_write_start() will be set to trigger. The reverse direction, setting mddev->ro to match a set readonly request, can be ignored because the blkdev level readonly flag precludes the need to have mddev->ro set correctly. Nevermind the fact that setting mddev->ro to 1 may fail if the array is in use. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/md.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index b60d328f6b1..4d96950c4b2 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4816,6 +4816,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
int err = 0;
void __user *argp = (void __user *)arg;
mddev_t *mddev = NULL;
+ int ro;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -4951,6 +4952,34 @@ static int md_ioctl(struct inode *inode, struct file *file,
err = do_md_stop (mddev, 1, 1);
goto done_unlock;
+ case BLKROSET:
+ if (get_user(ro, (int __user *)(arg))) {
+ err = -EFAULT;
+ goto done_unlock;
+ }
+ err = -EINVAL;
+
+ /* if the bdev is going readonly the value of mddev->ro
+ * does not matter, no writes are coming
+ */
+ if (ro)
+ goto done_unlock;
+
+ /* are we are already prepared for writes? */
+ if (mddev->ro != 1)
+ goto done_unlock;
+
+ /* transitioning to readauto need only happen for
+ * arrays that call md_write_start
+ */
+ if (mddev->pers) {
+ err = restart_array(mddev);
+ if (err == 0) {
+ mddev->ro = 2;
+ set_disk_ro(mddev->gendisk, 0);
+ }
+ }
+ goto done_unlock;
}
/*