Blob Blame History Raw
From: Hannes Reinecke <hare@suse.de>
Date: Tue, 19 Jan 2016 12:00:37 +0100
Subject: dm multipath devices are not getting created for readonly devices
References: bnc#382705
Patch-Mainline: Submitted, 04/07/2016 - dm-devel@redhat.com

Currently we cannot create device-mapper tables for multipath devices
whenever they are read-only.
This patch modifies the device-mapper to set the 'READ-ONLY' flag
automatically whenever a read-only is added to the table.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/md/dm-table.c |    5 ++++-
 drivers/md/dm.c       |   24 +++++++++++++++++++++---
 2 files changed, 25 insertions(+), 4 deletions(-)

--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -451,11 +451,14 @@ int dm_get_device(struct dm_target *ti,
 			return r;
 		}
 
+		if (dd->dm_dev->mode != mode)
+			t->mode = dd->dm_dev->mode;
+
 		refcount_set(&dd->count, 1);
 		list_add(&dd->list, &t->devices);
 		goto out;
 
-	} else if (dd->dm_dev->mode != (mode | dd->dm_dev->mode)) {
+	} else if (dd->dm_dev->mode != mode) {
 		r = upgrade_mode(dd, mode, t->md);
 		if (r)
 			return r;
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -301,16 +301,25 @@ int dm_deleting_md(struct mapped_device
 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;
 	}
 
@@ -319,7 +328,7 @@ static int dm_blk_open(struct block_devi
 out:
 	spin_unlock(&_minor_lock);
 
-	return md ? 0 : -ENXIO;
+	return retval;
 }
 
 static void dm_blk_close(struct gendisk *disk, fmode_t mode)
@@ -678,7 +687,12 @@ int dm_get_table_device(struct mapped_de
 		td->dm_dev.mode = mode;
 		td->dm_dev.bdev = NULL;
 
-		if ((r = open_table_device(td, dev, md))) {
+		r = open_table_device(td, dev, md);
+		if (r == -EROFS) {
+			td->dm_dev.mode &= ~FMODE_WRITE;
+			r = open_table_device(td, dev, md);
+		}
+		if (r) {
 			mutex_unlock(&md->table_devices_lock);
 			kfree(td);
 			return r;
@@ -1937,6 +1951,10 @@ static struct dm_table *__bind(struct ma
 	md->immutable_target_type = dm_table_get_immutable_target_type(t);
 
 	dm_table_set_restrictions(t, q, limits);
+	if (!(dm_table_get_mode(t) & FMODE_WRITE))
+		set_disk_ro(md->disk, 1);
+	else
+		set_disk_ro(md->disk, 0);
 	if (old_map)
 		dm_sync_table(md);