diff options
author | Dan Williams <dan.j.williams@intel.com> | 2010-05-12 08:25:37 +1000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-07-05 11:10:46 -0700 |
commit | d04e05f72668d77b66c91756c3d64c21970ea2a7 (patch) | |
tree | b7441b5ab9ecaeae511f673cde3cfe6ff3db6523 /drivers/md/md.c | |
parent | 861fc8bdf88071da0e3ac140a23e532ae791ea43 (diff) | |
download | lwn-d04e05f72668d77b66c91756c3d64c21970ea2a7.tar.gz lwn-d04e05f72668d77b66c91756c3d64c21970ea2a7.zip |
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/md/md.c')
-rw-r--r-- | drivers/md/md.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index f2e719d25e9c..01470794d9c3 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5334,6 +5334,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, int err = 0; void __user *argp = (void __user *)arg; mddev_t *mddev = NULL; + int ro; if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -5469,6 +5470,34 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, 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; } /* |