From 7e9524e9b73d62017ed7ed9379b3345937d46b21 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Wed, 4 Dec 2013 17:43:56 -0500 Subject: [PATCH 4/8] dm thin: only passdown discards when pool is in read-only mode FIXME: I'm not convinced this is needed... looking closer at process_discard(), it'll just add discards to prepared_discards list which will be processed by process_prepared_discard_passdown().. so no unmapping will happen. Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer --- drivers/md/dm-thin.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 55 insertions(+), 1 deletions(-) diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index ee29037..2a96178 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -1088,6 +1088,60 @@ static void process_discard(struct thin_c *tc, struct bio *bio) } } +static void process_discard_passdown_only(struct thin_c *tc, struct bio *bio) +{ + int r; + struct pool *pool = tc->pool; + struct dm_bio_prison_cell *cell, *cell2; + struct dm_cell_key key, key2; + dm_block_t block = get_bio_block(tc, bio); + struct dm_thin_lookup_result lookup_result; + + build_virtual_key(tc->td, block, &key); + if (bio_detain(tc->pool, &key, bio, &cell)) + return; + + r = dm_thin_find_block(tc->td, block, 1, &lookup_result); + switch (r) { + case 0: + /* + * Check nobody is fiddling with this pool block. This can + * happen if someone's in the process of breaking sharing + * on this block. + */ + build_data_key(tc->td, lookup_result.block, &key2); + if (bio_detain(tc->pool, &key2, bio, &cell2)) { + cell_defer_no_holder(tc, cell); + break; + } + + inc_all_io_entry(pool, bio); + cell_defer_no_holder(tc, cell); + cell_defer_no_holder(tc, cell2); + + if ((!lookup_result.shared) && pool->pf.discard_passdown) + remap_and_issue(tc, bio, lookup_result.block); + else + bio_endio(bio, 0); + break; + + case -ENODATA: + /* + * It isn't provisioned, just forget it. + */ + cell_defer_no_holder(tc, cell); + bio_endio(bio, 0); + break; + + default: + DMERR_LIMIT("%s: dm_thin_find_block() failed: error = %d", + __func__, r); + cell_defer_no_holder(tc, cell); + bio_io_error(bio); + break; + } +} + static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block, struct dm_cell_key *key, struct dm_thin_lookup_result *lookup_result, @@ -1418,7 +1472,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode) } else { dm_pool_metadata_read_only(pool->pmd); pool->process_bio = process_bio_read_only; - pool->process_discard = process_discard; + pool->process_discard = process_discard_passdown_only; pool->process_prepared_mapping = process_prepared_mapping_fail; pool->process_prepared_discard = process_prepared_discard_passdown; } -- 1.7.1