|
@@ -399,28 +399,30 @@ static int check_device_area(struct dm_dev_internal *dd, sector_t start,
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * This upgrades the mode on an already open dm_dev. Being
|
|
|
|
|
|
+ * This upgrades the mode on an already open dm_dev, being
|
|
* careful to leave things as they were if we fail to reopen the
|
|
* careful to leave things as they were if we fail to reopen the
|
|
- * device.
|
|
|
|
|
|
+ * device and not to touch the existing bdev field in case
|
|
|
|
+ * it is accessed concurrently inside dm_table_any_congested().
|
|
*/
|
|
*/
|
|
static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode,
|
|
static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode,
|
|
struct mapped_device *md)
|
|
struct mapped_device *md)
|
|
{
|
|
{
|
|
int r;
|
|
int r;
|
|
- struct dm_dev_internal dd_copy;
|
|
|
|
- dev_t dev = dd->dm_dev.bdev->bd_dev;
|
|
|
|
|
|
+ struct dm_dev_internal dd_new, dd_old;
|
|
|
|
|
|
- dd_copy = *dd;
|
|
|
|
|
|
+ dd_new = dd_old = *dd;
|
|
|
|
+
|
|
|
|
+ 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)
|
|
|
|
+ return r;
|
|
|
|
|
|
dd->dm_dev.mode |= new_mode;
|
|
dd->dm_dev.mode |= new_mode;
|
|
- dd->dm_dev.bdev = NULL;
|
|
|
|
- r = open_dev(dd, dev, md);
|
|
|
|
- if (!r)
|
|
|
|
- close_dev(&dd_copy, md);
|
|
|
|
- else
|
|
|
|
- *dd = dd_copy;
|
|
|
|
|
|
+ close_dev(&dd_old, md);
|
|
|
|
|
|
- return r;
|
|
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|