aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-thin.c
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2015-07-15 16:52:04 -0400
committerMike Snitzer <snitzer@redhat.com>2015-07-16 10:23:49 -0400
commitbcc696fac11fe13e59dda5aaec6322a25b7c9a3a (patch)
tree956a9236835e48e108c0547eca1da8b0e8a1e2e9 /drivers/md/dm-thin.c
parentb06075a98d595b761881fb2d7b8a557ea2f8b7ac (diff)
dm thin: stay in out-of-data-space mode once no_space_timeout expires
This fixes an issue where running out of data space would cause the thin-pool's metadata to become read-only. There was no reason to make metadata read-only -- calling set_pool_mode() with PM_READ_ONLY was a misguided way to error all queued and future write IOs. We can accomplish the same by degrading from PM_OUT_OF_DATA_SPACE to PM_OUT_OF_DATA_SPACE with error_if_no_space enabled. Otherwise, the use of PM_READ_ONLY could cause a race where commit() was started before the PM_READ_ONLY transition but dm_pool_commit_metadata() would go on to fail because the block manager had transitioned to read-only. The return of -EPERM from dm_pool_commit_metadata(), due to attempting to commit while in read-only mode, caused the thin-pool to set 'needs_check' because a metadata_operation_failed(). This needless cascade of failures makes life for users more difficult than needed. Reported-by: Vivek Goyal <vgoyal@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.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 8f015d924a24..34e79531ea3f 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -2282,18 +2282,23 @@ static void do_waker(struct work_struct *ws)
2282 queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD); 2282 queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD);
2283} 2283}
2284 2284
2285static void notify_of_pool_mode_change_to_oods(struct pool *pool);
2286
2285/* 2287/*
2286 * We're holding onto IO to allow userland time to react. After the 2288 * We're holding onto IO to allow userland time to react. After the
2287 * timeout either the pool will have been resized (and thus back in 2289 * timeout either the pool will have been resized (and thus back in
2288 * PM_WRITE mode), or we degrade to PM_READ_ONLY and start erroring IO. 2290 * PM_WRITE mode), or we degrade to PM_OUT_OF_DATA_SPACE w/ error_if_no_space.
2289 */ 2291 */
2290static void do_no_space_timeout(struct work_struct *ws) 2292static void do_no_space_timeout(struct work_struct *ws)
2291{ 2293{
2292 struct pool *pool = container_of(to_delayed_work(ws), struct pool, 2294 struct pool *pool = container_of(to_delayed_work(ws), struct pool,
2293 no_space_timeout); 2295 no_space_timeout);
2294 2296
2295 if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) 2297 if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) {
2296 set_pool_mode(pool, PM_READ_ONLY); 2298 pool->pf.error_if_no_space = true;
2299 notify_of_pool_mode_change_to_oods(pool);
2300 error_retry_list(pool);
2301 }
2297} 2302}
2298 2303
2299/*----------------------------------------------------------------*/ 2304/*----------------------------------------------------------------*/
@@ -2371,6 +2376,14 @@ static void notify_of_pool_mode_change(struct pool *pool, const char *new_mode)
2371 dm_device_name(pool->pool_md), new_mode); 2376 dm_device_name(pool->pool_md), new_mode);
2372} 2377}
2373 2378
2379static void notify_of_pool_mode_change_to_oods(struct pool *pool)
2380{
2381 if (!pool->pf.error_if_no_space)
2382 notify_of_pool_mode_change(pool, "out-of-data-space (queue IO)");
2383 else
2384 notify_of_pool_mode_change(pool, "out-of-data-space (error IO)");
2385}
2386
2374static bool passdown_enabled(struct pool_c *pt) 2387static bool passdown_enabled(struct pool_c *pt)
2375{ 2388{
2376 return pt->adjusted_pf.discard_passdown; 2389 return pt->adjusted_pf.discard_passdown;
@@ -2455,7 +2468,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
2455 * frequently seeing this mode. 2468 * frequently seeing this mode.
2456 */ 2469 */
2457 if (old_mode != new_mode) 2470 if (old_mode != new_mode)
2458 notify_of_pool_mode_change(pool, "out-of-data-space"); 2471 notify_of_pool_mode_change_to_oods(pool);
2459 pool->process_bio = process_bio_read_only; 2472 pool->process_bio = process_bio_read_only;
2460 pool->process_discard = process_discard_bio; 2473 pool->process_discard = process_discard_bio;
2461 pool->process_cell = process_cell_read_only; 2474 pool->process_cell = process_cell_read_only;