MD: hold mddev lock to change bitmap location
[cascardo/linux.git] / drivers / md / dm-table.c
index 88f0174..3e407a9 100644 (file)
@@ -827,6 +827,12 @@ void dm_consume_args(struct dm_arg_set *as, unsigned num_args)
 }
 EXPORT_SYMBOL(dm_consume_args);
 
+static bool __table_type_bio_based(unsigned table_type)
+{
+       return (table_type == DM_TYPE_BIO_BASED ||
+               table_type == DM_TYPE_DAX_BIO_BASED);
+}
+
 static bool __table_type_request_based(unsigned table_type)
 {
        return (table_type == DM_TYPE_REQUEST_BASED ||
@@ -839,6 +845,34 @@ void dm_table_set_type(struct dm_table *t, unsigned type)
 }
 EXPORT_SYMBOL_GPL(dm_table_set_type);
 
+static int device_supports_dax(struct dm_target *ti, struct dm_dev *dev,
+                              sector_t start, sector_t len, void *data)
+{
+       struct request_queue *q = bdev_get_queue(dev->bdev);
+
+       return q && blk_queue_dax(q);
+}
+
+static bool dm_table_supports_dax(struct dm_table *t)
+{
+       struct dm_target *ti;
+       unsigned i = 0;
+
+       /* Ensure that all targets support DAX. */
+       while (i < dm_table_get_num_targets(t)) {
+               ti = dm_table_get_target(t, i++);
+
+               if (!ti->type->direct_access)
+                       return false;
+
+               if (!ti->type->iterate_devices ||
+                   !ti->type->iterate_devices(ti, device_supports_dax, NULL))
+                       return false;
+       }
+
+       return true;
+}
+
 static int dm_table_determine_type(struct dm_table *t)
 {
        unsigned i;
@@ -853,6 +887,7 @@ static int dm_table_determine_type(struct dm_table *t)
                /* target already set the table's type */
                if (t->type == DM_TYPE_BIO_BASED)
                        return 0;
+               BUG_ON(t->type == DM_TYPE_DAX_BIO_BASED);
                goto verify_rq_based;
        }
 
@@ -887,6 +922,9 @@ static int dm_table_determine_type(struct dm_table *t)
        if (bio_based) {
                /* We must use this table as bio-based */
                t->type = DM_TYPE_BIO_BASED;
+               if (dm_table_supports_dax(t) ||
+                   (list_empty(devices) && live_md_type == DM_TYPE_DAX_BIO_BASED))
+                       t->type = DM_TYPE_DAX_BIO_BASED;
                return 0;
        }
 
@@ -979,6 +1017,11 @@ struct dm_target *dm_table_get_wildcard_target(struct dm_table *t)
        return NULL;
 }
 
+bool dm_table_bio_based(struct dm_table *t)
+{
+       return __table_type_bio_based(dm_table_get_type(t));
+}
+
 bool dm_table_request_based(struct dm_table *t)
 {
        return __table_type_request_based(dm_table_get_type(t));
@@ -1001,7 +1044,7 @@ static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device *
                return -EINVAL;
        }
 
-       if (type == DM_TYPE_BIO_BASED)
+       if (__table_type_bio_based(type))
                for (i = 0; i < t->num_targets; i++) {
                        tgt = t->targets + i;
                        per_io_data_size = max(per_io_data_size, tgt->per_io_data_size);