diff options
Diffstat (limited to 'drivers/md/dm-thin.c')
-rw-r--r-- | drivers/md/dm-thin.c | 72 |
1 files changed, 37 insertions, 35 deletions
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 0bd8d498b3b9..dadd9696340c 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
@@ -195,7 +195,7 @@ static void throttle_unlock(struct throttle *t) | |||
195 | struct dm_thin_new_mapping; | 195 | struct dm_thin_new_mapping; |
196 | 196 | ||
197 | /* | 197 | /* |
198 | * The pool runs in 4 modes. Ordered in degraded order for comparisons. | 198 | * The pool runs in various modes. Ordered in degraded order for comparisons. |
199 | */ | 199 | */ |
200 | enum pool_mode { | 200 | enum pool_mode { |
201 | PM_WRITE, /* metadata may be changed */ | 201 | PM_WRITE, /* metadata may be changed */ |
@@ -282,9 +282,38 @@ struct pool { | |||
282 | mempool_t mapping_pool; | 282 | mempool_t mapping_pool; |
283 | }; | 283 | }; |
284 | 284 | ||
285 | static enum pool_mode get_pool_mode(struct pool *pool); | ||
286 | static void metadata_operation_failed(struct pool *pool, const char *op, int r); | 285 | static void metadata_operation_failed(struct pool *pool, const char *op, int r); |
287 | 286 | ||
287 | static enum pool_mode get_pool_mode(struct pool *pool) | ||
288 | { | ||
289 | return pool->pf.mode; | ||
290 | } | ||
291 | |||
292 | static void notify_of_pool_mode_change(struct pool *pool) | ||
293 | { | ||
294 | const char *descs[] = { | ||
295 | "write", | ||
296 | "out-of-data-space", | ||
297 | "read-only", | ||
298 | "read-only", | ||
299 | "fail" | ||
300 | }; | ||
301 | const char *extra_desc = NULL; | ||
302 | enum pool_mode mode = get_pool_mode(pool); | ||
303 | |||
304 | if (mode == PM_OUT_OF_DATA_SPACE) { | ||
305 | if (!pool->pf.error_if_no_space) | ||
306 | extra_desc = " (queue IO)"; | ||
307 | else | ||
308 | extra_desc = " (error IO)"; | ||
309 | } | ||
310 | |||
311 | dm_table_event(pool->ti->table); | ||
312 | DMINFO("%s: switching pool to %s%s mode", | ||
313 | dm_device_name(pool->pool_md), | ||
314 | descs[(int)mode], extra_desc ? : ""); | ||
315 | } | ||
316 | |||
288 | /* | 317 | /* |
289 | * Target context for a pool. | 318 | * Target context for a pool. |
290 | */ | 319 | */ |
@@ -2351,8 +2380,6 @@ static void do_waker(struct work_struct *ws) | |||
2351 | queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD); | 2380 | queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD); |
2352 | } | 2381 | } |
2353 | 2382 | ||
2354 | static void notify_of_pool_mode_change_to_oods(struct pool *pool); | ||
2355 | |||
2356 | /* | 2383 | /* |
2357 | * We're holding onto IO to allow userland time to react. After the | 2384 | * We're holding onto IO to allow userland time to react. After the |
2358 | * timeout either the pool will have been resized (and thus back in | 2385 | * timeout either the pool will have been resized (and thus back in |
@@ -2365,7 +2392,7 @@ static void do_no_space_timeout(struct work_struct *ws) | |||
2365 | 2392 | ||
2366 | if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) { | 2393 | if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) { |
2367 | pool->pf.error_if_no_space = true; | 2394 | pool->pf.error_if_no_space = true; |
2368 | notify_of_pool_mode_change_to_oods(pool); | 2395 | notify_of_pool_mode_change(pool); |
2369 | error_retry_list_with_code(pool, BLK_STS_NOSPC); | 2396 | error_retry_list_with_code(pool, BLK_STS_NOSPC); |
2370 | } | 2397 | } |
2371 | } | 2398 | } |
@@ -2433,26 +2460,6 @@ static void noflush_work(struct thin_c *tc, void (*fn)(struct work_struct *)) | |||
2433 | 2460 | ||
2434 | /*----------------------------------------------------------------*/ | 2461 | /*----------------------------------------------------------------*/ |
2435 | 2462 | ||
2436 | static enum pool_mode get_pool_mode(struct pool *pool) | ||
2437 | { | ||
2438 | return pool->pf.mode; | ||
2439 | } | ||
2440 | |||
2441 | static void notify_of_pool_mode_change(struct pool *pool, const char *new_mode) | ||
2442 | { | ||
2443 | dm_table_event(pool->ti->table); | ||
2444 | DMINFO("%s: switching pool to %s mode", | ||
2445 | dm_device_name(pool->pool_md), new_mode); | ||
2446 | } | ||
2447 | |||
2448 | static void notify_of_pool_mode_change_to_oods(struct pool *pool) | ||
2449 | { | ||
2450 | if (!pool->pf.error_if_no_space) | ||
2451 | notify_of_pool_mode_change(pool, "out-of-data-space (queue IO)"); | ||
2452 | else | ||
2453 | notify_of_pool_mode_change(pool, "out-of-data-space (error IO)"); | ||
2454 | } | ||
2455 | |||
2456 | static bool passdown_enabled(struct pool_c *pt) | 2463 | static bool passdown_enabled(struct pool_c *pt) |
2457 | { | 2464 | { |
2458 | return pt->adjusted_pf.discard_passdown; | 2465 | return pt->adjusted_pf.discard_passdown; |
@@ -2501,8 +2508,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) | |||
2501 | 2508 | ||
2502 | switch (new_mode) { | 2509 | switch (new_mode) { |
2503 | case PM_FAIL: | 2510 | case PM_FAIL: |
2504 | if (old_mode != new_mode) | ||
2505 | notify_of_pool_mode_change(pool, "failure"); | ||
2506 | dm_pool_metadata_read_only(pool->pmd); | 2511 | dm_pool_metadata_read_only(pool->pmd); |
2507 | pool->process_bio = process_bio_fail; | 2512 | pool->process_bio = process_bio_fail; |
2508 | pool->process_discard = process_bio_fail; | 2513 | pool->process_discard = process_bio_fail; |
@@ -2516,8 +2521,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) | |||
2516 | 2521 | ||
2517 | case PM_OUT_OF_METADATA_SPACE: | 2522 | case PM_OUT_OF_METADATA_SPACE: |
2518 | case PM_READ_ONLY: | 2523 | case PM_READ_ONLY: |
2519 | if (!is_read_only_pool_mode(old_mode)) | ||
2520 | notify_of_pool_mode_change(pool, "read-only"); | ||
2521 | dm_pool_metadata_read_only(pool->pmd); | 2524 | dm_pool_metadata_read_only(pool->pmd); |
2522 | pool->process_bio = process_bio_read_only; | 2525 | pool->process_bio = process_bio_read_only; |
2523 | pool->process_discard = process_bio_success; | 2526 | pool->process_discard = process_bio_success; |
@@ -2538,8 +2541,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) | |||
2538 | * alarming rate. Adjust your low water mark if you're | 2541 | * alarming rate. Adjust your low water mark if you're |
2539 | * frequently seeing this mode. | 2542 | * frequently seeing this mode. |
2540 | */ | 2543 | */ |
2541 | if (old_mode != new_mode) | ||
2542 | notify_of_pool_mode_change_to_oods(pool); | ||
2543 | pool->out_of_data_space = true; | 2544 | pool->out_of_data_space = true; |
2544 | pool->process_bio = process_bio_read_only; | 2545 | pool->process_bio = process_bio_read_only; |
2545 | pool->process_discard = process_discard_bio; | 2546 | pool->process_discard = process_discard_bio; |
@@ -2552,8 +2553,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) | |||
2552 | break; | 2553 | break; |
2553 | 2554 | ||
2554 | case PM_WRITE: | 2555 | case PM_WRITE: |
2555 | if (old_mode != new_mode) | ||
2556 | notify_of_pool_mode_change(pool, "write"); | ||
2557 | if (old_mode == PM_OUT_OF_DATA_SPACE) | 2556 | if (old_mode == PM_OUT_OF_DATA_SPACE) |
2558 | cancel_delayed_work_sync(&pool->no_space_timeout); | 2557 | cancel_delayed_work_sync(&pool->no_space_timeout); |
2559 | pool->out_of_data_space = false; | 2558 | pool->out_of_data_space = false; |
@@ -2573,6 +2572,9 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) | |||
2573 | * doesn't cause an unexpected mode transition on resume. | 2572 | * doesn't cause an unexpected mode transition on resume. |
2574 | */ | 2573 | */ |
2575 | pt->adjusted_pf.mode = new_mode; | 2574 | pt->adjusted_pf.mode = new_mode; |
2575 | |||
2576 | if (old_mode != new_mode) | ||
2577 | notify_of_pool_mode_change(pool); | ||
2576 | } | 2578 | } |
2577 | 2579 | ||
2578 | static void abort_transaction(struct pool *pool) | 2580 | static void abort_transaction(struct pool *pool) |
@@ -4023,7 +4025,7 @@ static struct target_type pool_target = { | |||
4023 | .name = "thin-pool", | 4025 | .name = "thin-pool", |
4024 | .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | | 4026 | .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | |
4025 | DM_TARGET_IMMUTABLE, | 4027 | DM_TARGET_IMMUTABLE, |
4026 | .version = {1, 20, 0}, | 4028 | .version = {1, 21, 0}, |
4027 | .module = THIS_MODULE, | 4029 | .module = THIS_MODULE, |
4028 | .ctr = pool_ctr, | 4030 | .ctr = pool_ctr, |
4029 | .dtr = pool_dtr, | 4031 | .dtr = pool_dtr, |
@@ -4397,7 +4399,7 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) | |||
4397 | 4399 | ||
4398 | static struct target_type thin_target = { | 4400 | static struct target_type thin_target = { |
4399 | .name = "thin", | 4401 | .name = "thin", |
4400 | .version = {1, 20, 0}, | 4402 | .version = {1, 21, 0}, |
4401 | .module = THIS_MODULE, | 4403 | .module = THIS_MODULE, |
4402 | .ctr = thin_ctr, | 4404 | .ctr = thin_ctr, |
4403 | .dtr = thin_dtr, | 4405 | .dtr = thin_dtr, |