@@ -443,11 +443,20 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
dd->dm_dev.mode = mode;
dd->dm_dev.bdev = NULL;
- if ((r = open_dev(dd, dev, t->md))) {
+ r = open_dev(dd, dev, t->md);
+ if (r == -EROFS) {
+ dd->dm_dev.mode &= ~FMODE_WRITE;
+ r = open_dev(dd, dev, t->md);
+ }
+ if (r) {
kfree(dd);
return r;
}
+ /* Modify the table mode, too */
+ if (dd->dm_dev.mode != mode)
+ t->mode = dd->dm_dev.mode;
+
format_dev_t(dd->dm_dev.name, dev);
atomic_set(&dd->count, 0);
@@ -384,16 +384,25 @@ int dm_deleting_md(struct mapped_device *md)
static int dm_blk_open(struct block_device *bdev, fmode_t mode)
{
struct mapped_device *md;
+ int retval = 0;
spin_lock(&_minor_lock);
md = bdev->bd_disk->private_data;
- if (!md)
+ if (!md) {
+ retval = -ENXIO;
goto out;
+ }
if (test_bit(DMF_FREEING, &md->flags) ||
dm_deleting_md(md)) {
md = NULL;
+ retval = -ENXIO;
+ goto out;
+ }
+ if (get_disk_ro(md->disk) && (mode & FMODE_WRITE)) {
+ md = NULL;
+ retval = -EROFS;
goto out;
}
@@ -403,7 +412,7 @@ static int dm_blk_open(struct block_device *bdev, fmode_t mode)
out:
spin_unlock(&_minor_lock);
- return md ? 0 : -ENXIO;
+ return retval;
}
static void dm_blk_close(struct gendisk *disk, fmode_t mode)
@@ -2156,6 +2165,10 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
else
clear_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
+ if (!(dm_table_get_mode(t) & FMODE_WRITE))
+ set_disk_ro(md->disk, 1);
+ else
+ set_disk_ro(md->disk, 0);
dm_sync_table(md);
return old_map;
Currently we cannot create device-mapper tables for multipath devices whenever the underlying devices are read-only. This patch modifies the device-mapper to set the 'READ-ONLY' flag automatically whenever a read-only device is added to the table. Signed-off-by: Hannes Reinecke <hare@suse.de> --- drivers/md/dm-table.c | 11 ++++++++++- drivers/md/dm.c | 17 +++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-)