aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-thin.c
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2013-12-04 19:51:33 -0500
committerMike Snitzer <snitzer@redhat.com>2014-01-07 10:14:27 -0500
commitb53306558526a097a587774573b76d0d9903c5bf (patch)
treea9a22bb9eb5f272ac6f59b52fc3627a314e64dfd /drivers/md/dm-thin.c
parent88a6621bed65ce2d421a808a2f60e1b64914d777 (diff)
dm thin: handle metadata failures more consistently
Introduce metadata_operation_failed() wrappers, around set_pool_mode(), to assist with improving the consistency of how metadata failures are handled. Logging is improved and metadata operation failures trigger read-only mode immediately. Also, eliminate redundant set_pool_mode() calls in the two alloc_data_block() caller's error paths. Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-thin.c')
-rw-r--r--drivers/md/dm-thin.c48
1 files changed, 27 insertions, 21 deletions
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index e49c27c91a1f..35d2e41ef82f 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -198,7 +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 set_pool_mode(struct pool *pool, enum pool_mode mode); 201static void metadata_operation_failed(struct pool *pool, const char *op, int r);
202 202
203/* 203/*
204 * Target context for a pool. 204 * Target context for a pool.
@@ -641,9 +641,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
641 */ 641 */
642 r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block); 642 r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
643 if (r) { 643 if (r) {
644 DMERR_LIMIT("%s: dm_thin_insert_block() failed: error = %d", 644 metadata_operation_failed(pool, "dm_thin_insert_block", r);
645 dm_device_name(pool->pool_md), r);
646 set_pool_mode(pool, PM_READ_ONLY);
647 cell_error(pool, m->cell); 645 cell_error(pool, m->cell);
648 goto out; 646 goto out;
649 } 647 }
@@ -900,11 +898,8 @@ static int commit(struct pool *pool)
900 return -EINVAL; 898 return -EINVAL;
901 899
902 r = dm_pool_commit_metadata(pool->pmd); 900 r = dm_pool_commit_metadata(pool->pmd);
903 if (r) { 901 if (r)
904 DMERR_LIMIT("%s: dm_pool_commit_metadata failed: error = %d", 902 metadata_operation_failed(pool, "dm_pool_commit_metadata", r);
905 dm_device_name(pool->pool_md), r);
906 set_pool_mode(pool, PM_READ_ONLY);
907 }
908 903
909 return r; 904 return r;
910} 905}
@@ -941,8 +936,10 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
941 return -EINVAL; 936 return -EINVAL;
942 937
943 r = dm_pool_get_free_block_count(pool->pmd, &free_blocks); 938 r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
944 if (r) 939 if (r) {
940 metadata_operation_failed(pool, "dm_pool_get_free_block_count", r);
945 return r; 941 return r;
942 }
946 943
947 check_low_water_mark(pool, free_blocks); 944 check_low_water_mark(pool, free_blocks);
948 945
@@ -956,8 +953,10 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
956 return r; 953 return r;
957 954
958 r = dm_pool_get_free_block_count(pool->pmd, &free_blocks); 955 r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
959 if (r) 956 if (r) {
957 metadata_operation_failed(pool, "dm_pool_get_free_block_count", r);
960 return r; 958 return r;
959 }
961 960
962 /* 961 /*
963 * If we still have no space we set a flag to avoid 962 * If we still have no space we set a flag to avoid
@@ -980,11 +979,11 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
980 if (r) { 979 if (r) {
981 if (r == -ENOSPC && 980 if (r == -ENOSPC &&
982 !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) && 981 !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) &&
983 !free_blocks) { 982 !free_blocks)
984 DMWARN("%s: no free metadata space available.", 983 DMWARN("%s: no free metadata space available.",
985 dm_device_name(pool->pool_md)); 984 dm_device_name(pool->pool_md));
986 set_pool_mode(pool, PM_READ_ONLY); 985
987 } 986 metadata_operation_failed(pool, "dm_pool_alloc_data_block", r);
988 return r; 987 return r;
989 } 988 }
990 989
@@ -1126,7 +1125,6 @@ static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
1126 default: 1125 default:
1127 DMERR_LIMIT("%s: alloc_data_block() failed: error = %d", 1126 DMERR_LIMIT("%s: alloc_data_block() failed: error = %d",
1128 __func__, r); 1127 __func__, r);
1129 set_pool_mode(pool, PM_READ_ONLY);
1130 cell_error(pool, cell); 1128 cell_error(pool, cell);
1131 break; 1129 break;
1132 } 1130 }
@@ -1205,7 +1203,6 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
1205 default: 1203 default:
1206 DMERR_LIMIT("%s: alloc_data_block() failed: error = %d", 1204 DMERR_LIMIT("%s: alloc_data_block() failed: error = %d",
1207 __func__, r); 1205 __func__, r);
1208 set_pool_mode(pool, PM_READ_ONLY);
1209 cell_error(pool, cell); 1206 cell_error(pool, cell);
1210 break; 1207 break;
1211 } 1208 }
@@ -1449,6 +1446,18 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode)
1449 } 1446 }
1450} 1447}
1451 1448
1449/*
1450 * Rather than calling set_pool_mode directly, use these which describe the
1451 * reason for mode degradation.
1452 */
1453static void metadata_operation_failed(struct pool *pool, const char *op, int r)
1454{
1455 DMERR_LIMIT("%s: metadata operation '%s' failed: error = %d",
1456 dm_device_name(pool->pool_md), op, r);
1457
1458 set_pool_mode(pool, PM_READ_ONLY);
1459}
1460
1452/*----------------------------------------------------------------*/ 1461/*----------------------------------------------------------------*/
1453 1462
1454/* 1463/*
@@ -2209,9 +2218,7 @@ static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit)
2209 } else if (data_size > sb_data_size) { 2218 } else if (data_size > sb_data_size) {
2210 r = dm_pool_resize_data_dev(pool->pmd, data_size); 2219 r = dm_pool_resize_data_dev(pool->pmd, data_size);
2211 if (r) { 2220 if (r) {
2212 DMERR("%s: failed to resize data device", 2221 metadata_operation_failed(pool, "dm_pool_resize_data_dev", r);
2213 dm_device_name(pool->pool_md));
2214 set_pool_mode(pool, PM_READ_ONLY);
2215 return r; 2222 return r;
2216 } 2223 }
2217 2224
@@ -2248,8 +2255,7 @@ static int maybe_resize_metadata_dev(struct dm_target *ti, bool *need_commit)
2248 } else if (metadata_dev_size > sb_metadata_dev_size) { 2255 } else if (metadata_dev_size > sb_metadata_dev_size) {
2249 r = dm_pool_resize_metadata_dev(pool->pmd, metadata_dev_size); 2256 r = dm_pool_resize_metadata_dev(pool->pmd, metadata_dev_size);
2250 if (r) { 2257 if (r) {
2251 DMERR("%s: failed to resize metadata device", 2258 metadata_operation_failed(pool, "dm_pool_resize_metadata_dev", r);
2252 dm_device_name(pool->pool_md));
2253 return r; 2259 return r;
2254 } 2260 }
2255 2261