diff options
Diffstat (limited to 'drivers')
| -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, |
