diff options
author | Mike Snitzer <snitzer@redhat.com> | 2013-12-05 16:03:33 -0500 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2014-01-07 10:14:28 -0500 |
commit | 399caddfb16f5fa30c66056a32477cf95c947e2b (patch) | |
tree | c7afb7ccdaa87205419b3715bc18b5209efde61b | |
parent | 6f7f51d4344d530f725e9c932fa44f00ba363fa2 (diff) |
dm thin: cleanup and improve no space handling
Factor out_of_data_space() out of alloc_data_block(). Eliminate the use
of 'no_free_space' as a latch in alloc_data_block() -- this is no longer
needed now that we switch to read-only mode when we run out of data or
metadata space. In a later patch, the 'no_free_space' flag will be
eliminated entirely (in favor of checking metadata rather than relying
on a transient flag).
Move no metdata space handling into metdata_operation_failed(). Set
no_free_space when metadata space is exhausted too. This is useful,
because it offers consistency, for the following patch that will requeue
data IOs if no_free_space.
Also, rename no_space() to retry_bios_on_resume().
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Acked-by: Joe Thornber <ejt@redhat.com>
-rw-r--r-- | drivers/md/dm-thin.c | 61 |
1 files changed, 32 insertions, 29 deletions
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 234696009d7b..96ce36a1a764 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
@@ -198,6 +198,7 @@ struct pool { | |||
198 | }; | 198 | }; |
199 | 199 | ||
200 | static enum pool_mode get_pool_mode(struct pool *pool); | 200 | static enum pool_mode get_pool_mode(struct pool *pool); |
201 | static void out_of_data_space(struct pool *pool); | ||
201 | static void metadata_operation_failed(struct pool *pool, const char *op, int r); | 202 | static void metadata_operation_failed(struct pool *pool, const char *op, int r); |
202 | 203 | ||
203 | /* | 204 | /* |
@@ -922,16 +923,8 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) | |||
922 | { | 923 | { |
923 | int r; | 924 | int r; |
924 | dm_block_t free_blocks; | 925 | dm_block_t free_blocks; |
925 | unsigned long flags; | ||
926 | struct pool *pool = tc->pool; | 926 | struct pool *pool = tc->pool; |
927 | 927 | ||
928 | /* | ||
929 | * Once no_free_space is set we must not allow allocation to succeed. | ||
930 | * Otherwise it is difficult to explain, debug, test and support. | ||
931 | */ | ||
932 | if (pool->no_free_space) | ||
933 | return -ENOSPC; | ||
934 | |||
935 | if (get_pool_mode(pool) != PM_WRITE) | 928 | if (get_pool_mode(pool) != PM_WRITE) |
936 | return -EINVAL; | 929 | return -EINVAL; |
937 | 930 | ||
@@ -958,31 +951,14 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) | |||
958 | return r; | 951 | return r; |
959 | } | 952 | } |
960 | 953 | ||
961 | /* | ||
962 | * If we still have no space we set a flag to avoid | ||
963 | * doing all this checking and return -ENOSPC. This | ||
964 | * flag serves as a latch that disallows allocations from | ||
965 | * this pool until the admin takes action (e.g. resize or | ||
966 | * table reload). | ||
967 | */ | ||
968 | if (!free_blocks) { | 954 | if (!free_blocks) { |
969 | DMWARN("%s: no free data space available.", | 955 | out_of_data_space(pool); |
970 | dm_device_name(pool->pool_md)); | ||
971 | spin_lock_irqsave(&pool->lock, flags); | ||
972 | pool->no_free_space = true; | ||
973 | spin_unlock_irqrestore(&pool->lock, flags); | ||
974 | return -ENOSPC; | 956 | return -ENOSPC; |
975 | } | 957 | } |
976 | } | 958 | } |
977 | 959 | ||
978 | r = dm_pool_alloc_data_block(pool->pmd, result); | 960 | r = dm_pool_alloc_data_block(pool->pmd, result); |
979 | if (r) { | 961 | if (r) { |
980 | if (r == -ENOSPC && | ||
981 | !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) && | ||
982 | !free_blocks) | ||
983 | DMWARN("%s: no free metadata space available.", | ||
984 | dm_device_name(pool->pool_md)); | ||
985 | |||
986 | metadata_operation_failed(pool, "dm_pool_alloc_data_block", r); | 962 | metadata_operation_failed(pool, "dm_pool_alloc_data_block", r); |
987 | return r; | 963 | return r; |
988 | } | 964 | } |
@@ -1006,7 +982,7 @@ static void retry_on_resume(struct bio *bio) | |||
1006 | spin_unlock_irqrestore(&pool->lock, flags); | 982 | spin_unlock_irqrestore(&pool->lock, flags); |
1007 | } | 983 | } |
1008 | 984 | ||
1009 | static void no_space(struct pool *pool, struct dm_bio_prison_cell *cell) | 985 | static void retry_bios_on_resume(struct pool *pool, struct dm_bio_prison_cell *cell) |
1010 | { | 986 | { |
1011 | struct bio *bio; | 987 | struct bio *bio; |
1012 | struct bio_list bios; | 988 | struct bio_list bios; |
@@ -1119,7 +1095,7 @@ static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block, | |||
1119 | break; | 1095 | break; |
1120 | 1096 | ||
1121 | case -ENOSPC: | 1097 | case -ENOSPC: |
1122 | no_space(pool, cell); | 1098 | retry_bios_on_resume(pool, cell); |
1123 | break; | 1099 | break; |
1124 | 1100 | ||
1125 | default: | 1101 | default: |
@@ -1197,7 +1173,7 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block | |||
1197 | break; | 1173 | break; |
1198 | 1174 | ||
1199 | case -ENOSPC: | 1175 | case -ENOSPC: |
1200 | no_space(pool, cell); | 1176 | retry_bios_on_resume(pool, cell); |
1201 | break; | 1177 | break; |
1202 | 1178 | ||
1203 | default: | 1179 | default: |
@@ -1446,15 +1422,42 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode) | |||
1446 | } | 1422 | } |
1447 | } | 1423 | } |
1448 | 1424 | ||
1425 | static void set_no_free_space(struct pool *pool) | ||
1426 | { | ||
1427 | unsigned long flags; | ||
1428 | |||
1429 | spin_lock_irqsave(&pool->lock, flags); | ||
1430 | pool->no_free_space = true; | ||
1431 | spin_unlock_irqrestore(&pool->lock, flags); | ||
1432 | } | ||
1433 | |||
1449 | /* | 1434 | /* |
1450 | * Rather than calling set_pool_mode directly, use these which describe the | 1435 | * Rather than calling set_pool_mode directly, use these which describe the |
1451 | * reason for mode degradation. | 1436 | * reason for mode degradation. |
1452 | */ | 1437 | */ |
1438 | static void out_of_data_space(struct pool *pool) | ||
1439 | { | ||
1440 | DMERR_LIMIT("%s: no free data space available.", | ||
1441 | dm_device_name(pool->pool_md)); | ||
1442 | set_no_free_space(pool); | ||
1443 | set_pool_mode(pool, PM_READ_ONLY); | ||
1444 | } | ||
1445 | |||
1453 | static void metadata_operation_failed(struct pool *pool, const char *op, int r) | 1446 | static void metadata_operation_failed(struct pool *pool, const char *op, int r) |
1454 | { | 1447 | { |
1448 | dm_block_t free_blocks; | ||
1449 | |||
1455 | DMERR_LIMIT("%s: metadata operation '%s' failed: error = %d", | 1450 | DMERR_LIMIT("%s: metadata operation '%s' failed: error = %d", |
1456 | dm_device_name(pool->pool_md), op, r); | 1451 | dm_device_name(pool->pool_md), op, r); |
1457 | 1452 | ||
1453 | if (r == -ENOSPC && | ||
1454 | !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) && | ||
1455 | !free_blocks) { | ||
1456 | DMERR_LIMIT("%s: no free metadata space available.", | ||
1457 | dm_device_name(pool->pool_md)); | ||
1458 | set_no_free_space(pool); | ||
1459 | } | ||
1460 | |||
1458 | set_pool_mode(pool, PM_READ_ONLY); | 1461 | set_pool_mode(pool, PM_READ_ONLY); |
1459 | } | 1462 | } |
1460 | 1463 | ||