diff -pNaur md-org/dm-table.c md/dm-table.c --- md-org/dm-table.c 2008-03-17 23:23:31.000000000 +0530 +++ md/dm-table.c 2008-04-30 09:58:09.000000000 +0530 @@ -461,11 +461,19 @@ static int __table_get_device(struct dm_ dd->mode = mode; dd->bdev = NULL; - if ((r = open_dev(dd, dev))) { + r = open_dev(dd, dev); + if (r == -EROFS) { + dd->mode &= ~FMODE_WRITE; + r = open_dev(dd, dev); + } + if (r) { kfree(dd); return r; } + if (dd->mode != mode) + t->mode = dd->mode; + format_dev_t(dd->name, dev); atomic_set(&dd->count, 0); diff -pNaur md-org/dm.c md/dm.c --- md-org/dm.c 2008-03-17 23:23:31.000000000 +0530 +++ md/dm.c 2008-04-30 09:58:46.000000000 +0530 @@ -221,16 +221,26 @@ static void __exit dm_exit(void) static int dm_blk_open(struct inode *inode, struct file *file) { struct mapped_device *md; + struct gendisk *disk = inode->i_bdev->bd_disk; + int retval = 0; spin_lock(&_minor_lock); md = inode->i_bdev->bd_disk->private_data; - if (!md) + if (!md) { + retval = -ENXIO; goto out; + } if (test_bit(DMF_FREEING, &md->flags) || test_bit(DMF_DELETING, &md->flags)) { md = NULL; + retval = -ENXIO; + goto out; + } + if (disk->policy && (file->f_mode & FMODE_WRITE)) { + md = NULL; + retval = -EROFS; goto out; } @@ -240,7 +250,7 @@ static int dm_blk_open(struct inode *ino out: spin_unlock(&_minor_lock); - return md ? 0 : -ENXIO; + return retval; } static int dm_blk_close(struct inode *inode, struct file *file) @@ -1089,6 +1099,10 @@ static int __bind(struct mapped_device * write_lock(&md->map_lock); md->map = t; dm_table_set_restrictions(t, q); + if (!(dm_table_get_mode(t) & FMODE_WRITE)) + { + set_disk_ro(md->disk, 1); + } write_unlock(&md->map_lock); return 0; @@ -1104,6 +1118,10 @@ static void __unbind(struct mapped_devic dm_table_event_callback(map, NULL, NULL); write_lock(&md->map_lock); md->map = NULL; + if (!(dm_table_get_mode(map) & FMODE_WRITE)) + { + set_disk_ro(md->disk, 0); + } write_unlock(&md->map_lock); dm_table_put(map); }