dd_new = dd_old = *dd;
- dd_new.dm_dev.mode |= new_mode;
+ dd_new.dm_dev.mode = new_mode;
dd_new.dm_dev.bdev = NULL;
r = open_dev(&dd_new, dd->dm_dev.bdev->bd_dev, md);
- if (r)
+ if (r == -EROFS) {
+ dd_new.dm_dev.mode &= ~FMODE_WRITE;
+ r = open_dev(&dd_new, dd->dm_dev.bdev->bd_dev, md);
+ }
+ if (!r)
return r;
- dd->dm_dev.mode |= new_mode;
+ dd->dm_dev.mode = new_mode;
close_dev(&dd_old, md);
return 0;
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;
}
+ 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);
list_add(&dd->list, &t->devices);
- } 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;
*/
void dm_put_device(struct dm_target *ti, struct dm_dev *d)
{
- struct dm_dev_internal *dd = container_of(d, struct dm_dev_internal,
- dm_dev);
+ struct dm_dev_internal *dd;
+
+ if (!d)
+ return;
+ dd = container_of(d, struct dm_dev_internal, dm_dev);
if (atomic_dec_and_test(&dd->count)) {
close_dev(dd, ti->table->md);
list_del(&dd->list);