Skip to content

Commit ae3fa8b

Browse files
committed
Merge tag 'for-5.0/dm-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper fixes from Mike Snitzer: - Fix bug in DM crypt's sizing of its block integrity tag space, resulting in less memory use when DM crypt layers on DM integrity. - Fix a long-standing DM thinp crash consistency bug that was due to improper handling of FUA. This issue is specific to writes that fill an entire thinp block which needs to be allocated. * tag 'for-5.0/dm-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm thin: fix bug where bio that overwrites thin block ignores FUA dm crypt: don't overallocate the integrity tag space
2 parents dfeae33 + 4ae280b commit ae3fa8b

File tree

2 files changed

+51
-6
lines changed

2 files changed

+51
-6
lines changed

drivers/md/dm-crypt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,7 @@ static int dm_crypt_integrity_io_alloc(struct dm_crypt_io *io, struct bio *bio)
932932
if (IS_ERR(bip))
933933
return PTR_ERR(bip);
934934

935-
tag_len = io->cc->on_disk_tag_size * bio_sectors(bio);
935+
tag_len = io->cc->on_disk_tag_size * (bio_sectors(bio) >> io->cc->sector_shift);
936936

937937
bip->bip_iter.bi_size = tag_len;
938938
bip->bip_iter.bi_sector = io->cc->start + io->sector;

drivers/md/dm-thin.c

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ struct pool {
257257

258258
spinlock_t lock;
259259
struct bio_list deferred_flush_bios;
260+
struct bio_list deferred_flush_completions;
260261
struct list_head prepared_mappings;
261262
struct list_head prepared_discards;
262263
struct list_head prepared_discards_pt2;
@@ -956,6 +957,39 @@ static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m)
956957
mempool_free(m, &m->tc->pool->mapping_pool);
957958
}
958959

960+
static void complete_overwrite_bio(struct thin_c *tc, struct bio *bio)
961+
{
962+
struct pool *pool = tc->pool;
963+
unsigned long flags;
964+
965+
/*
966+
* If the bio has the REQ_FUA flag set we must commit the metadata
967+
* before signaling its completion.
968+
*/
969+
if (!bio_triggers_commit(tc, bio)) {
970+
bio_endio(bio);
971+
return;
972+
}
973+
974+
/*
975+
* Complete bio with an error if earlier I/O caused changes to the
976+
* metadata that can't be committed, e.g, due to I/O errors on the
977+
* metadata device.
978+
*/
979+
if (dm_thin_aborted_changes(tc->td)) {
980+
bio_io_error(bio);
981+
return;
982+
}
983+
984+
/*
985+
* Batch together any bios that trigger commits and then issue a
986+
* single commit for them in process_deferred_bios().
987+
*/
988+
spin_lock_irqsave(&pool->lock, flags);
989+
bio_list_add(&pool->deferred_flush_completions, bio);
990+
spin_unlock_irqrestore(&pool->lock, flags);
991+
}
992+
959993
static void process_prepared_mapping(struct dm_thin_new_mapping *m)
960994
{
961995
struct thin_c *tc = m->tc;
@@ -988,7 +1022,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
9881022
*/
9891023
if (bio) {
9901024
inc_remap_and_issue_cell(tc, m->cell, m->data_block);
991-
bio_endio(bio);
1025+
complete_overwrite_bio(tc, bio);
9921026
} else {
9931027
inc_all_io_entry(tc->pool, m->cell->holder);
9941028
remap_and_issue(tc, m->cell->holder, m->data_block);
@@ -2317,7 +2351,7 @@ static void process_deferred_bios(struct pool *pool)
23172351
{
23182352
unsigned long flags;
23192353
struct bio *bio;
2320-
struct bio_list bios;
2354+
struct bio_list bios, bio_completions;
23212355
struct thin_c *tc;
23222356

23232357
tc = get_first_thin(pool);
@@ -2328,26 +2362,36 @@ static void process_deferred_bios(struct pool *pool)
23282362
}
23292363

23302364
/*
2331-
* If there are any deferred flush bios, we must commit
2332-
* the metadata before issuing them.
2365+
* If there are any deferred flush bios, we must commit the metadata
2366+
* before issuing them or signaling their completion.
23332367
*/
23342368
bio_list_init(&bios);
2369+
bio_list_init(&bio_completions);
2370+
23352371
spin_lock_irqsave(&pool->lock, flags);
23362372
bio_list_merge(&bios, &pool->deferred_flush_bios);
23372373
bio_list_init(&pool->deferred_flush_bios);
2374+
2375+
bio_list_merge(&bio_completions, &pool->deferred_flush_completions);
2376+
bio_list_init(&pool->deferred_flush_completions);
23382377
spin_unlock_irqrestore(&pool->lock, flags);
23392378

2340-
if (bio_list_empty(&bios) &&
2379+
if (bio_list_empty(&bios) && bio_list_empty(&bio_completions) &&
23412380
!(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool)))
23422381
return;
23432382

23442383
if (commit(pool)) {
2384+
bio_list_merge(&bios, &bio_completions);
2385+
23452386
while ((bio = bio_list_pop(&bios)))
23462387
bio_io_error(bio);
23472388
return;
23482389
}
23492390
pool->last_commit_jiffies = jiffies;
23502391

2392+
while ((bio = bio_list_pop(&bio_completions)))
2393+
bio_endio(bio);
2394+
23512395
while ((bio = bio_list_pop(&bios)))
23522396
generic_make_request(bio);
23532397
}
@@ -2954,6 +2998,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
29542998
INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout);
29552999
spin_lock_init(&pool->lock);
29563000
bio_list_init(&pool->deferred_flush_bios);
3001+
bio_list_init(&pool->deferred_flush_completions);
29573002
INIT_LIST_HEAD(&pool->prepared_mappings);
29583003
INIT_LIST_HEAD(&pool->prepared_discards);
29593004
INIT_LIST_HEAD(&pool->prepared_discards_pt2);

0 commit comments

Comments
 (0)