Skip to content

Commit 104655f

Browse files
jthornberkergon
authored andcommitted
dm thin: support discards
Support discards in the thin target. On discard the corresponding mapping(s) are removed from the thin device. If the associated block(s) are no longer shared the discard is passed to the underlying device. All bios other than discards now have an associated deferred_entry that is saved to the 'all_io_entry' in endio_hook. When non-discard IO completes and associated mappings are quiesced any discards that were deferred, via ds_add_work() in process_discard(), will be queued for processing by the worker thread. Signed-off-by: Joe Thornber <[email protected]> Signed-off-by: Mike Snitzer <[email protected]> Signed-off-by: Alasdair G Kergon <[email protected]> drivers/md/dm-thin.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++---- drivers/md/dm-thin.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 158 insertions(+), 14 deletions(-)
1 parent eb2aa48 commit 104655f

File tree

1 file changed

+158
-14
lines changed

1 file changed

+158
-14
lines changed

drivers/md/dm-thin.c

Lines changed: 158 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -520,10 +520,12 @@ struct pool {
520520
struct bio_list deferred_bios;
521521
struct bio_list deferred_flush_bios;
522522
struct list_head prepared_mappings;
523+
struct list_head prepared_discards;
523524

524525
struct bio_list retry_on_resume_list;
525526

526527
struct deferred_set shared_read_ds;
528+
struct deferred_set all_io_ds;
527529

528530
struct new_mapping *next_mapping;
529531
mempool_t *mapping_pool;
@@ -621,6 +623,7 @@ static struct pool *__pool_table_lookup_metadata_dev(struct block_device *md_dev
621623
struct endio_hook {
622624
struct thin_c *tc;
623625
struct deferred_entry *shared_read_entry;
626+
struct deferred_entry *all_io_entry;
624627
struct new_mapping *overwrite_mapping;
625628
};
626629

@@ -728,11 +731,12 @@ struct new_mapping {
728731

729732
unsigned quiesced:1;
730733
unsigned prepared:1;
734+
unsigned pass_discard:1;
731735

732736
struct thin_c *tc;
733737
dm_block_t virt_block;
734738
dm_block_t data_block;
735-
struct cell *cell;
739+
struct cell *cell, *cell2;
736740
int err;
737741

738742
/*
@@ -872,29 +876,58 @@ static void process_prepared_mapping(struct new_mapping *m)
872876
mempool_free(m, tc->pool->mapping_pool);
873877
}
874878

875-
static void process_prepared_mappings(struct pool *pool)
879+
static void process_prepared_discard(struct new_mapping *m)
880+
{
881+
int r;
882+
struct thin_c *tc = m->tc;
883+
884+
r = dm_thin_remove_block(tc->td, m->virt_block);
885+
if (r)
886+
DMERR("dm_thin_remove_block() failed");
887+
888+
/*
889+
* Pass the discard down to the underlying device?
890+
*/
891+
if (m->pass_discard)
892+
remap_and_issue(tc, m->bio, m->data_block);
893+
else
894+
bio_endio(m->bio, 0);
895+
896+
cell_defer_except(tc, m->cell);
897+
cell_defer_except(tc, m->cell2);
898+
mempool_free(m, tc->pool->mapping_pool);
899+
}
900+
901+
static void process_prepared(struct pool *pool, struct list_head *head,
902+
void (*fn)(struct new_mapping *))
876903
{
877904
unsigned long flags;
878905
struct list_head maps;
879906
struct new_mapping *m, *tmp;
880907

881908
INIT_LIST_HEAD(&maps);
882909
spin_lock_irqsave(&pool->lock, flags);
883-
list_splice_init(&pool->prepared_mappings, &maps);
910+
list_splice_init(head, &maps);
884911
spin_unlock_irqrestore(&pool->lock, flags);
885912

886913
list_for_each_entry_safe(m, tmp, &maps, list)
887-
process_prepared_mapping(m);
914+
fn(m);
888915
}
889916

890917
/*
891918
* Deferred bio jobs.
892919
*/
893-
static int io_overwrites_block(struct pool *pool, struct bio *bio)
920+
static int io_overlaps_block(struct pool *pool, struct bio *bio)
894921
{
895-
return ((bio_data_dir(bio) == WRITE) &&
896-
!(bio->bi_sector & pool->offset_mask)) &&
922+
return !(bio->bi_sector & pool->offset_mask) &&
897923
(bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT));
924+
925+
}
926+
927+
static int io_overwrites_block(struct pool *pool, struct bio *bio)
928+
{
929+
return (bio_data_dir(bio) == WRITE) &&
930+
io_overlaps_block(pool, bio);
898931
}
899932

900933
static void save_and_set_endio(struct bio *bio, bio_end_io_t **save,
@@ -1134,6 +1167,86 @@ static void no_space(struct cell *cell)
11341167
retry_on_resume(bio);
11351168
}
11361169

1170+
static void process_discard(struct thin_c *tc, struct bio *bio)
1171+
{
1172+
int r;
1173+
struct pool *pool = tc->pool;
1174+
struct cell *cell, *cell2;
1175+
struct cell_key key, key2;
1176+
dm_block_t block = get_bio_block(tc, bio);
1177+
struct dm_thin_lookup_result lookup_result;
1178+
struct new_mapping *m;
1179+
1180+
build_virtual_key(tc->td, block, &key);
1181+
if (bio_detain(tc->pool->prison, &key, bio, &cell))
1182+
return;
1183+
1184+
r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
1185+
switch (r) {
1186+
case 0:
1187+
/*
1188+
* Check nobody is fiddling with this pool block. This can
1189+
* happen if someone's in the process of breaking sharing
1190+
* on this block.
1191+
*/
1192+
build_data_key(tc->td, lookup_result.block, &key2);
1193+
if (bio_detain(tc->pool->prison, &key2, bio, &cell2)) {
1194+
cell_release_singleton(cell, bio);
1195+
break;
1196+
}
1197+
1198+
if (io_overlaps_block(pool, bio)) {
1199+
/*
1200+
* IO may still be going to the destination block. We must
1201+
* quiesce before we can do the removal.
1202+
*/
1203+
m = get_next_mapping(pool);
1204+
m->tc = tc;
1205+
m->pass_discard = !lookup_result.shared;
1206+
m->virt_block = block;
1207+
m->data_block = lookup_result.block;
1208+
m->cell = cell;
1209+
m->cell2 = cell2;
1210+
m->err = 0;
1211+
m->bio = bio;
1212+
1213+
if (!ds_add_work(&pool->all_io_ds, &m->list)) {
1214+
list_add(&m->list, &pool->prepared_discards);
1215+
wake_worker(pool);
1216+
}
1217+
} else {
1218+
/*
1219+
* This path is hit if people are ignoring
1220+
* limits->discard_granularity. It ignores any
1221+
* part of the discard that is in a subsequent
1222+
* block.
1223+
*/
1224+
sector_t offset = bio->bi_sector - (block << pool->block_shift);
1225+
unsigned remaining = (pool->sectors_per_block - offset) << 9;
1226+
bio->bi_size = min(bio->bi_size, remaining);
1227+
1228+
cell_release_singleton(cell, bio);
1229+
cell_release_singleton(cell2, bio);
1230+
remap_and_issue(tc, bio, lookup_result.block);
1231+
}
1232+
break;
1233+
1234+
case -ENODATA:
1235+
/*
1236+
* It isn't provisioned, just forget it.
1237+
*/
1238+
cell_release_singleton(cell, bio);
1239+
bio_endio(bio, 0);
1240+
break;
1241+
1242+
default:
1243+
DMERR("discard: find block unexpectedly returned %d", r);
1244+
cell_release_singleton(cell, bio);
1245+
bio_io_error(bio);
1246+
break;
1247+
}
1248+
}
1249+
11371250
static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
11381251
struct cell_key *key,
11391252
struct dm_thin_lookup_result *lookup_result,
@@ -1279,6 +1392,7 @@ static void process_bio(struct thin_c *tc, struct bio *bio)
12791392

12801393
default:
12811394
DMERR("dm_thin_find_block() failed, error = %d", r);
1395+
cell_release_singleton(cell, bio);
12821396
bio_io_error(bio);
12831397
break;
12841398
}
@@ -1320,7 +1434,11 @@ static void process_deferred_bios(struct pool *pool)
13201434

13211435
break;
13221436
}
1323-
process_bio(tc, bio);
1437+
1438+
if (bio->bi_rw & REQ_DISCARD)
1439+
process_discard(tc, bio);
1440+
else
1441+
process_bio(tc, bio);
13241442
}
13251443

13261444
/*
@@ -1354,7 +1472,8 @@ static void do_worker(struct work_struct *ws)
13541472
{
13551473
struct pool *pool = container_of(ws, struct pool, worker);
13561474

1357-
process_prepared_mappings(pool);
1475+
process_prepared(pool, &pool->prepared_mappings, process_prepared_mapping);
1476+
process_prepared(pool, &pool->prepared_discards, process_prepared_discard);
13581477
process_deferred_bios(pool);
13591478
}
13601479

@@ -1397,6 +1516,7 @@ static struct endio_hook *thin_hook_bio(struct thin_c *tc, struct bio *bio)
13971516

13981517
h->tc = tc;
13991518
h->shared_read_entry = NULL;
1519+
h->all_io_entry = bio->bi_rw & REQ_DISCARD ? NULL : ds_inc(&pool->all_io_ds);
14001520
h->overwrite_mapping = NULL;
14011521

14021522
return h;
@@ -1415,7 +1535,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio,
14151535
struct dm_thin_lookup_result result;
14161536

14171537
map_context->ptr = thin_hook_bio(tc, bio);
1418-
if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
1538+
if (bio->bi_rw & (REQ_DISCARD | REQ_FLUSH | REQ_FUA)) {
14191539
thin_defer_bio(tc, bio);
14201540
return DM_MAPIO_SUBMITTED;
14211541
}
@@ -1591,10 +1711,12 @@ static struct pool *pool_create(struct mapped_device *pool_md,
15911711
bio_list_init(&pool->deferred_bios);
15921712
bio_list_init(&pool->deferred_flush_bios);
15931713
INIT_LIST_HEAD(&pool->prepared_mappings);
1714+
INIT_LIST_HEAD(&pool->prepared_discards);
15941715
pool->low_water_triggered = 0;
15951716
pool->no_free_space = 0;
15961717
bio_list_init(&pool->retry_on_resume_list);
15971718
ds_init(&pool->shared_read_ds);
1719+
ds_init(&pool->all_io_ds);
15981720

15991721
pool->next_mapping = NULL;
16001722
pool->mapping_pool =
@@ -1834,7 +1956,8 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
18341956
pt->low_water_blocks = low_water_blocks;
18351957
pt->zero_new_blocks = pf.zero_new_blocks;
18361958
ti->num_flush_requests = 1;
1837-
ti->num_discard_requests = 0;
1959+
ti->num_discard_requests = 1;
1960+
ti->discards_supported = 1;
18381961
ti->private = pt;
18391962

18401963
pt->callbacks.congested_fn = pool_is_congested;
@@ -2227,13 +2350,25 @@ static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
22272350
return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
22282351
}
22292352

2353+
static void set_discard_limits(struct pool *pool, struct queue_limits *limits)
2354+
{
2355+
limits->max_discard_sectors = pool->sectors_per_block;
2356+
2357+
/*
2358+
* This is just a hint, and not enforced. We have to cope with
2359+
* bios that overlap 2 blocks.
2360+
*/
2361+
limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
2362+
}
2363+
22302364
static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
22312365
{
22322366
struct pool_c *pt = ti->private;
22332367
struct pool *pool = pt->pool;
22342368

22352369
blk_limits_io_min(limits, 0);
22362370
blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
2371+
set_discard_limits(pool, limits);
22372372
}
22382373

22392374
static struct target_type pool_target = {
@@ -2350,8 +2485,8 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
23502485

23512486
ti->split_io = tc->pool->sectors_per_block;
23522487
ti->num_flush_requests = 1;
2353-
ti->num_discard_requests = 0;
2354-
ti->discards_supported = 0;
2488+
ti->num_discard_requests = 1;
2489+
ti->discards_supported = 1;
23552490

23562491
dm_put(pool_md);
23572492

@@ -2407,6 +2542,13 @@ static int thin_endio(struct dm_target *ti,
24072542
spin_unlock_irqrestore(&pool->lock, flags);
24082543
}
24092544

2545+
if (h->all_io_entry) {
2546+
INIT_LIST_HEAD(&work);
2547+
ds_dec(h->all_io_entry, &work);
2548+
list_for_each_entry_safe(m, tmp, &work, list)
2549+
list_add(&m->list, &pool->prepared_discards);
2550+
}
2551+
24102552
mempool_free(h, pool->endio_hook_pool);
24112553

24122554
return 0;
@@ -2487,9 +2629,11 @@ static int thin_iterate_devices(struct dm_target *ti,
24872629
static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
24882630
{
24892631
struct thin_c *tc = ti->private;
2632+
struct pool *pool = tc->pool;
24902633

24912634
blk_limits_io_min(limits, 0);
2492-
blk_limits_io_opt(limits, tc->pool->sectors_per_block << SECTOR_SHIFT);
2635+
blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
2636+
set_discard_limits(pool, limits);
24932637
}
24942638

24952639
static struct target_type thin_target = {

0 commit comments

Comments
 (0)