@@ -40,6 +40,7 @@ struct mapped_device {
* dereference.
*/
void __rcu *map;
+ struct dm_table *hc_map;
unsigned long flags;
@@ -1365,6 +1365,7 @@ static int table_load(struct file *filp, struct dm_ioctl *param, size_t param_si
if (hc->new_map)
old_map = hc->new_map;
hc->new_map = t;
+ hc->md->hc_map = hc->new_map;
up_write(&_hash_lock);
param->flags |= DM_INACTIVE_PRESENT_FLAG;
@@ -1080,6 +1080,21 @@ static struct dm_target *dm_dax_get_live_target(struct mapped_device *md,
struct dm_target *ti;
map = dm_get_live_table(md, srcu_idx);
+ if (!map) {
+ /* Sometimes dm_swap_table couldn't be used in time.
+ *
+ * For example, during the origin construction of
+ * dm-snapshot, the sys_ioctl table_load will try to
+ * detect the lower device origin-real whether support
+ * direct access or not. But origin-real device md's struct
+ * dm-table pointer has not yet been assigned real address.
+ * So hc_map has been used for get the address from
+ * struct hash_cell directly.
+ */
+ DMINFO("failed to get map, use hc_map insteadly");
+ map = md->hc_map;
+ }
+
if (!map)
return NULL;