aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2013-12-05 16:03:33 -0500
committerMike Snitzer <snitzer@redhat.com>2014-01-07 10:14:28 -0500
commit399caddfb16f5fa30c66056a32477cf95c947e2b (patch)
treec7afb7ccdaa87205419b3715bc18b5209efde61b
parent6f7f51d4344d530f725e9c932fa44f00ba363fa2 (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.c61
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
200static enum pool_mode get_pool_mode(struct pool *pool); 200static enum pool_mode get_pool_mode(struct pool *pool);
201static void out_of_data_space(struct pool *pool);
201static void metadata_operation_failed(struct pool *pool, const char *op, int r); 202static 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
1009static void no_space(struct pool *pool, struct dm_bio_prison_cell *cell) 985static 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
1425static 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 */
1438static 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
1453static void metadata_operation_failed(struct pool *pool, const char *op, int r) 1446static 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