diff options
author | Mike Snitzer <snitzer@redhat.com> | 2013-08-22 09:56:18 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2013-09-05 20:46:06 -0400 |
commit | 94563badaf41f9291ff0bad94a443a4319b9e312 (patch) | |
tree | 6c9bf7f6aba642dd4a08035fe93ec683c3fdf5bf /drivers/md | |
parent | f11c1c5693fac339d412b0b59b54693ddcb776ff (diff) |
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>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-thin.c | 56 |
1 files changed, 31 insertions, 25 deletions
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 3aff1c27e5b4..ed063427d676 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
@@ -918,6 +918,13 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) | |||
918 | unsigned long flags; | 918 | unsigned long flags; |
919 | struct pool *pool = tc->pool; | 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 | r = dm_pool_get_free_block_count(pool->pmd, &free_blocks); | 928 | r = dm_pool_get_free_block_count(pool->pmd, &free_blocks); |
922 | if (r) | 929 | if (r) |
923 | return r; | 930 | return r; |
@@ -932,31 +939,30 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) | |||
932 | } | 939 | } |
933 | 940 | ||
934 | if (!free_blocks) { | 941 | if (!free_blocks) { |
935 | if (pool->no_free_space) | 942 | /* |
936 | return -ENOSPC; | 943 | * Try to commit to see if that will free up some |
937 | else { | 944 | * more space. |
938 | /* | 945 | */ |
939 | * Try to commit to see if that will free up some | 946 | (void) commit_or_fallback(pool); |
940 | * more space. | ||
941 | */ | ||
942 | (void) commit_or_fallback(pool); | ||
943 | 947 | ||
944 | r = dm_pool_get_free_block_count(pool->pmd, &free_blocks); | 948 | r = dm_pool_get_free_block_count(pool->pmd, &free_blocks); |
945 | if (r) | 949 | if (r) |
946 | return r; | 950 | return r; |
947 | 951 | ||
948 | /* | 952 | /* |
949 | * If we still have no space we set a flag to avoid | 953 | * If we still have no space we set a flag to avoid |
950 | * doing all this checking and return -ENOSPC. | 954 | * doing all this checking and return -ENOSPC. This |
951 | */ | 955 | * flag serves as a latch that disallows allocations from |
952 | if (!free_blocks) { | 956 | * this pool until the admin takes action (e.g. resize or |
953 | DMWARN("%s: no free space available.", | 957 | * table reload). |
954 | dm_device_name(pool->pool_md)); | 958 | */ |
955 | spin_lock_irqsave(&pool->lock, flags); | 959 | if (!free_blocks) { |
956 | pool->no_free_space = 1; | 960 | DMWARN("%s: no free space available.", |
957 | spin_unlock_irqrestore(&pool->lock, flags); | 961 | dm_device_name(pool->pool_md)); |
958 | return -ENOSPC; | 962 | spin_lock_irqsave(&pool->lock, flags); |
959 | } | 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 @@ static struct target_type pool_target = { | |||
2695 | .name = "thin-pool", | 2701 | .name = "thin-pool", |
2696 | .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | | 2702 | .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | |
2697 | DM_TARGET_IMMUTABLE, | 2703 | DM_TARGET_IMMUTABLE, |
2698 | .version = {1, 8, 0}, | 2704 | .version = {1, 9, 0}, |
2699 | .module = THIS_MODULE, | 2705 | .module = THIS_MODULE, |
2700 | .ctr = pool_ctr, | 2706 | .ctr = pool_ctr, |
2701 | .dtr = pool_dtr, | 2707 | .dtr = pool_dtr, |
@@ -2982,7 +2988,7 @@ static int thin_iterate_devices(struct dm_target *ti, | |||
2982 | 2988 | ||
2983 | static struct target_type thin_target = { | 2989 | static struct target_type thin_target = { |
2984 | .name = "thin", | 2990 | .name = "thin", |
2985 | .version = {1, 8, 0}, | 2991 | .version = {1, 9, 0}, |
2986 | .module = THIS_MODULE, | 2992 | .module = THIS_MODULE, |
2987 | .ctr = thin_ctr, | 2993 | .ctr = thin_ctr, |
2988 | .dtr = thin_dtr, | 2994 | .dtr = thin_dtr, |