Skip to content

Commit 0f14d60

Browse files
Ming LeiMike Snitzer
authored andcommitted
dm: improve dm_io reference counting
Currently each dm_io's reference counter is grabbed before calling __map_bio(), this way isn't efficient since we can move this grabbing to initialization time inside alloc_io(). Meantime it becomes typical async io reference counter model: one is for submission side, the other is for completion side, and the io won't be completed until both sides are done. Signed-off-by: Ming Lei <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent 2e803cd commit 0f14d60

File tree

1 file changed

+39
-14
lines changed

1 file changed

+39
-14
lines changed

drivers/md/dm.c

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,9 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio)
590590
io = container_of(tio, struct dm_io, tio);
591591
io->magic = DM_IO_MAGIC;
592592
io->status = BLK_STS_OK;
593-
atomic_set(&io->io_count, 1);
593+
594+
/* one ref is for submission, the other is for completion */
595+
atomic_set(&io->io_count, 2);
594596
this_cpu_inc(*md->pending_io);
595597
io->orig_bio = bio;
596598
io->md = md;
@@ -955,11 +957,6 @@ static void dm_io_complete(struct dm_io *io)
955957
}
956958
}
957959

958-
static void dm_io_inc_pending(struct dm_io *io)
959-
{
960-
atomic_inc(&io->io_count);
961-
}
962-
963960
/*
964961
* Decrements the number of outstanding ios that a bio has been
965962
* cloned into, completing the original io if necc.
@@ -1316,7 +1313,6 @@ static void __map_bio(struct bio *clone)
13161313
/*
13171314
* Map the clone.
13181315
*/
1319-
dm_io_inc_pending(io);
13201316
tio->old_sector = clone->bi_iter.bi_sector;
13211317

13221318
if (static_branch_unlikely(&swap_bios_enabled) &&
@@ -1426,11 +1422,12 @@ static void alloc_multiple_bios(struct bio_list *blist, struct clone_info *ci,
14261422
}
14271423
}
14281424

1429-
static void __send_duplicate_bios(struct clone_info *ci, struct dm_target *ti,
1425+
static int __send_duplicate_bios(struct clone_info *ci, struct dm_target *ti,
14301426
unsigned num_bios, unsigned *len)
14311427
{
14321428
struct bio_list blist = BIO_EMPTY_LIST;
14331429
struct bio *clone;
1430+
int ret = 0;
14341431

14351432
switch (num_bios) {
14361433
case 0:
@@ -1440,16 +1437,20 @@ static void __send_duplicate_bios(struct clone_info *ci, struct dm_target *ti,
14401437
setup_split_accounting(ci, *len);
14411438
clone = alloc_tio(ci, ti, 0, len, GFP_NOIO);
14421439
__map_bio(clone);
1440+
ret = 1;
14431441
break;
14441442
default:
14451443
/* dm_accept_partial_bio() is not supported with shared tio->len_ptr */
14461444
alloc_multiple_bios(&blist, ci, ti, num_bios);
14471445
while ((clone = bio_list_pop(&blist))) {
14481446
dm_tio_set_flag(clone_to_tio(clone), DM_TIO_IS_DUPLICATE_BIO);
14491447
__map_bio(clone);
1448+
ret += 1;
14501449
}
14511450
break;
14521451
}
1452+
1453+
return ret;
14531454
}
14541455

14551456
static void __send_empty_flush(struct clone_info *ci)
@@ -1470,8 +1471,19 @@ static void __send_empty_flush(struct clone_info *ci)
14701471
ci->sector_count = 0;
14711472
ci->io->tio.clone.bi_iter.bi_size = 0;
14721473

1473-
while ((ti = dm_table_get_target(ci->map, target_nr++)))
1474-
__send_duplicate_bios(ci, ti, ti->num_flush_bios, NULL);
1474+
while ((ti = dm_table_get_target(ci->map, target_nr++))) {
1475+
int bios;
1476+
1477+
atomic_add(ti->num_flush_bios, &ci->io->io_count);
1478+
bios = __send_duplicate_bios(ci, ti, ti->num_flush_bios, NULL);
1479+
atomic_sub(ti->num_flush_bios - bios, &ci->io->io_count);
1480+
}
1481+
1482+
/*
1483+
* alloc_io() takes one extra reference for submission, so the
1484+
* reference won't reach 0 without the following subtraction
1485+
*/
1486+
atomic_sub(1, &ci->io->io_count);
14751487

14761488
bio_uninit(ci->bio);
14771489
}
@@ -1480,11 +1492,18 @@ static void __send_changing_extent_only(struct clone_info *ci, struct dm_target
14801492
unsigned num_bios)
14811493
{
14821494
unsigned len;
1495+
int bios;
14831496

14841497
len = min_t(sector_t, ci->sector_count,
14851498
max_io_len_target_boundary(ti, dm_target_offset(ti, ci->sector)));
14861499

1487-
__send_duplicate_bios(ci, ti, num_bios, &len);
1500+
atomic_add(num_bios, &ci->io->io_count);
1501+
bios = __send_duplicate_bios(ci, ti, num_bios, &len);
1502+
/*
1503+
* alloc_io() takes one extra reference for submission, so the
1504+
* reference won't reach 0 without the following (+1) subtraction
1505+
*/
1506+
atomic_sub(num_bios - bios + 1, &ci->io->io_count);
14881507

14891508
ci->sector += len;
14901509
ci->sector_count -= len;
@@ -1669,9 +1688,15 @@ static void dm_split_and_process_bio(struct mapped_device *md,
16691688
* Add every dm_io instance into the hlist_head which is stored in
16701689
* bio->bi_private, so that dm_poll_bio can poll them all.
16711690
*/
1672-
if (error || !ci.submit_as_polled)
1673-
dm_io_dec_pending(ci.io, error);
1674-
else
1691+
if (error || !ci.submit_as_polled) {
1692+
/*
1693+
* In case of submission failure, the extra reference for
1694+
* submitting io isn't consumed yet
1695+
*/
1696+
if (error)
1697+
atomic_dec(&io->io_count);
1698+
dm_io_dec_pending(io, error);
1699+
} else
16751700
dm_queue_poll_io(bio, io);
16761701
}
16771702

0 commit comments

Comments
 (0)