]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/md/dm-thin.c
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / drivers / md / dm-thin.c
index c151cbf80b10cdf963f2be5775e0fd7199134098..ed063427d676f64b53f3d9569449fc0daaf174b0 100644 (file)
@@ -918,6 +918,13 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
        unsigned long flags;
        struct pool *pool = tc->pool;
 
+       /*
+        * Once no_free_space is set we must not allow allocation to succeed.
+        * Otherwise it is difficult to explain, debug, test and support.
+        */
+       if (pool->no_free_space)
+               return -ENOSPC;
+
        r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
        if (r)
                return r;
@@ -932,31 +939,30 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
        }
 
        if (!free_blocks) {
-               if (pool->no_free_space)
-                       return -ENOSPC;
-               else {
-                       /*
-                        * Try to commit to see if that will free up some
-                        * more space.
-                        */
-                       (void) commit_or_fallback(pool);
+               /*
+                * Try to commit to see if that will free up some
+                * more space.
+                */
+               (void) commit_or_fallback(pool);
 
-                       r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
-                       if (r)
-                               return r;
+               r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
+               if (r)
+                       return r;
 
-                       /*
-                        * If we still have no space we set a flag to avoid
-                        * doing all this checking and return -ENOSPC.
-                        */
-                       if (!free_blocks) {
-                               DMWARN("%s: no free space available.",
-                                      dm_device_name(pool->pool_md));
-                               spin_lock_irqsave(&pool->lock, flags);
-                               pool->no_free_space = 1;
-                               spin_unlock_irqrestore(&pool->lock, flags);
-                               return -ENOSPC;
-                       }
+               /*
+                * If we still have no space we set a flag to avoid
+                * doing all this checking and return -ENOSPC.  This
+                * flag serves as a latch that disallows allocations from
+                * this pool until the admin takes action (e.g. resize or
+                * table reload).
+                */
+               if (!free_blocks) {
+                       DMWARN("%s: no free space available.",
+                              dm_device_name(pool->pool_md));
+                       spin_lock_irqsave(&pool->lock, flags);
+                       pool->no_free_space = 1;
+                       spin_unlock_irqrestore(&pool->lock, flags);
+                       return -ENOSPC;
                }
        }
 
@@ -1086,6 +1092,7 @@ static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
 {
        int r;
        dm_block_t data_block;
+       struct pool *pool = tc->pool;
 
        r = alloc_data_block(tc, &data_block);
        switch (r) {
@@ -1095,13 +1102,14 @@ static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
                break;
 
        case -ENOSPC:
-               no_space(tc->pool, cell);
+               no_space(pool, cell);
                break;
 
        default:
                DMERR_LIMIT("%s: alloc_data_block() failed: error = %d",
                            __func__, r);
-               cell_error(tc->pool, cell);
+               set_pool_mode(pool, PM_READ_ONLY);
+               cell_error(pool, cell);
                break;
        }
 }
@@ -2693,7 +2701,7 @@ static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 8, 0},
+       .version = {1, 9, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
@@ -2980,7 +2988,7 @@ static int thin_iterate_devices(struct dm_target *ti,
 
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 8, 0},
+       .version = {1, 9, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,