Commit 94563badaf41f9291ff0bad94a443a4319b9e312

Authored by Mike Snitzer
1 parent f11c1c5693

dm thin: always return -ENOSPC if no_free_space is set

If pool has 'no_free_space' set it means a previous allocation already
determined the pool has no free space (and failed that allocation with
-ENOSPC).  By always returning -ENOSPC if 'no_free_space' is set, we do
not allow the pool to oscillate between allocating blocks and then not.

But a side-effect of this determinism is that if a user wants to be able
to allocate new blocks they'll need to reload the pool's table (to clear
the 'no_free_space' flag).  This reload will happen automatically if the
pool's data volume is resized.  But if the user takes action to free a
lot of space by deleting snapshot volumes, etc the pool will no longer
allow data allocations to continue without an intervening table reload.

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Acked-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

Showing 1 changed file with 31 additions and 25 deletions Side-by-side Diff

drivers/md/dm-thin.c
... ... @@ -918,6 +918,13 @@
918 918 unsigned long flags;
919 919 struct pool *pool = tc->pool;
920 920  
  921 + /*
  922 + * Once no_free_space is set we must not allow allocation to succeed.
  923 + * Otherwise it is difficult to explain, debug, test and support.
  924 + */
  925 + if (pool->no_free_space)
  926 + return -ENOSPC;
  927 +
921 928 r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
922 929 if (r)
923 930 return r;
924 931  
925 932  
... ... @@ -932,31 +939,30 @@
932 939 }
933 940  
934 941 if (!free_blocks) {
935   - if (pool->no_free_space)
936   - return -ENOSPC;
937   - else {
938   - /*
939   - * Try to commit to see if that will free up some
940   - * more space.
941   - */
942   - (void) commit_or_fallback(pool);
  942 + /*
  943 + * Try to commit to see if that will free up some
  944 + * more space.
  945 + */
  946 + (void) commit_or_fallback(pool);
943 947  
944   - r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
945   - if (r)
946   - return r;
  948 + r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
  949 + if (r)
  950 + return r;
947 951  
948   - /*
949   - * If we still have no space we set a flag to avoid
950   - * doing all this checking and return -ENOSPC.
951   - */
952   - if (!free_blocks) {
953   - DMWARN("%s: no free space available.",
954   - dm_device_name(pool->pool_md));
955   - spin_lock_irqsave(&pool->lock, flags);
956   - pool->no_free_space = 1;
957   - spin_unlock_irqrestore(&pool->lock, flags);
958   - return -ENOSPC;
959   - }
  952 + /*
  953 + * If we still have no space we set a flag to avoid
  954 + * doing all this checking and return -ENOSPC. This
  955 + * flag serves as a latch that disallows allocations from
  956 + * this pool until the admin takes action (e.g. resize or
  957 + * table reload).
  958 + */
  959 + if (!free_blocks) {
  960 + DMWARN("%s: no free space available.",
  961 + dm_device_name(pool->pool_md));
  962 + spin_lock_irqsave(&pool->lock, flags);
  963 + pool->no_free_space = 1;
  964 + spin_unlock_irqrestore(&pool->lock, flags);
  965 + return -ENOSPC;
960 966 }
961 967 }
962 968  
... ... @@ -2695,7 +2701,7 @@
2695 2701 .name = "thin-pool",
2696 2702 .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
2697 2703 DM_TARGET_IMMUTABLE,
2698   - .version = {1, 8, 0},
  2704 + .version = {1, 9, 0},
2699 2705 .module = THIS_MODULE,
2700 2706 .ctr = pool_ctr,
2701 2707 .dtr = pool_dtr,
... ... @@ -2982,7 +2988,7 @@
2982 2988  
2983 2989 static struct target_type thin_target = {
2984 2990 .name = "thin",
2985   - .version = {1, 8, 0},
  2991 + .version = {1, 9, 0},
2986 2992 .module = THIS_MODULE,
2987 2993 .ctr = thin_ctr,
2988 2994 .dtr = thin_dtr,