Merge tag 'libnvdimm-for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm...
[linux-2.6-block.git] / drivers / md / dm-thin.c
index 72d91f477683f2c1dfad5a3a9614aaf0b26992e1..92237b6fa8cd1550c8783550b8a3b2db56d6002a 100644 (file)
@@ -235,6 +235,7 @@ struct pool {
        struct pool_features pf;
        bool low_water_triggered:1;     /* A dm event has been sent */
        bool suspended:1;
+       bool out_of_data_space:1;
 
        struct dm_bio_prison *prison;
        struct dm_kcopyd_client *copier;
@@ -461,9 +462,16 @@ static void cell_error_with_code(struct pool *pool,
        dm_bio_prison_free_cell(pool->prison, cell);
 }
 
+static int get_pool_io_error_code(struct pool *pool)
+{
+       return pool->out_of_data_space ? -ENOSPC : -EIO;
+}
+
 static void cell_error(struct pool *pool, struct dm_bio_prison_cell *cell)
 {
-       cell_error_with_code(pool, cell, -EIO);
+       int error = get_pool_io_error_code(pool);
+
+       cell_error_with_code(pool, cell, error);
 }
 
 static void cell_success(struct pool *pool, struct dm_bio_prison_cell *cell)
@@ -622,7 +630,9 @@ static void error_retry_list_with_code(struct pool *pool, int error)
 
 static void error_retry_list(struct pool *pool)
 {
-       return error_retry_list_with_code(pool, -EIO);
+       int error = get_pool_io_error_code(pool);
+
+       return error_retry_list_with_code(pool, error);
 }
 
 /*
@@ -2419,6 +2429,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
                 */
                if (old_mode != new_mode)
                        notify_of_pool_mode_change_to_oods(pool);
+               pool->out_of_data_space = true;
                pool->process_bio = process_bio_read_only;
                pool->process_discard = process_discard_bio;
                pool->process_cell = process_cell_read_only;
@@ -2432,6 +2443,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
        case PM_WRITE:
                if (old_mode != new_mode)
                        notify_of_pool_mode_change(pool, "write");
+               pool->out_of_data_space = false;
                pool->pf.error_if_no_space = pt->requested_pf.error_if_no_space;
                dm_pool_metadata_read_write(pool->pmd);
                pool->process_bio = process_bio;
@@ -2832,6 +2844,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
        INIT_LIST_HEAD(&pool->active_thins);
        pool->low_water_triggered = false;
        pool->suspended = true;
+       pool->out_of_data_space = false;
 
        pool->shared_read_ds = dm_deferred_set_create();
        if (!pool->shared_read_ds) {
@@ -3886,7 +3899,7 @@ static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 17, 0},
+       .version = {1, 18, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
@@ -4037,7 +4050,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        ti->num_flush_bios = 1;
        ti->flush_supported = true;
-       ti->per_bio_data_size = sizeof(struct dm_thin_endio_hook);
+       ti->per_io_data_size = sizeof(struct dm_thin_endio_hook);
 
        /* In case the pool supports discards, pass them on. */
        ti->discard_zeroes_data_unsupported = true;
@@ -4260,7 +4273,7 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 17, 0},
+       .version = {1, 18, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,