Skip to content

Commit 0e30695

Browse files
committed
Merge tag 'for-6.4/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper fixes from Mike Snitzer: - Fix DM thinp discard performance regression introduced during this merge window where DM core was splitting large discards every 128K (max_sectors_kb) rather than every 64M (discard_max_bytes). - Extend DM core LOCKFS fix, made during 6.4 merge, to also fix race between do_mount and dm's do_suspend (in addition to the earlier fix's do_mount race with dm's do_resume). - Fix DM thin metadata operations to first check if the thin-pool is in "fail_io" mode; otherwise UAF can occur. - Fix DM thinp's call to __blkdev_issue_discard to use GFP_NOIO rather than GFP_NOWAIT (__blkdev_issue_discard cannot handle NULL return from bio_alloc). * tag 'for-6.4/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm: use op specific max_sectors when splitting abnormal io dm thin: fix issue_discard to pass GFP_NOIO to __blkdev_issue_discard dm thin metadata: check fail_io before using data_sm dm: don't lock fs when the map is NULL during suspend or resume
2 parents 93fd8eb + be04c14 commit 0e30695

File tree

4 files changed

+34
-23
lines changed

4 files changed

+34
-23
lines changed

drivers/md/dm-ioctl.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,13 +1168,10 @@ static int do_resume(struct dm_ioctl *param)
11681168
/* Do we need to load a new map ? */
11691169
if (new_map) {
11701170
sector_t old_size, new_size;
1171-
int srcu_idx;
11721171

11731172
/* Suspend if it isn't already suspended */
1174-
old_map = dm_get_live_table(md, &srcu_idx);
1175-
if ((param->flags & DM_SKIP_LOCKFS_FLAG) || !old_map)
1173+
if (param->flags & DM_SKIP_LOCKFS_FLAG)
11761174
suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
1177-
dm_put_live_table(md, srcu_idx);
11781175
if (param->flags & DM_NOFLUSH_FLAG)
11791176
suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
11801177
if (!dm_suspended_md(md))

drivers/md/dm-thin-metadata.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,35 +1756,39 @@ int dm_thin_remove_range(struct dm_thin_device *td,
17561756

17571757
int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
17581758
{
1759-
int r;
1759+
int r = -EINVAL;
17601760
uint32_t ref_count;
17611761

17621762
down_read(&pmd->root_lock);
1763-
r = dm_sm_get_count(pmd->data_sm, b, &ref_count);
1764-
if (!r)
1765-
*result = (ref_count > 1);
1763+
if (!pmd->fail_io) {
1764+
r = dm_sm_get_count(pmd->data_sm, b, &ref_count);
1765+
if (!r)
1766+
*result = (ref_count > 1);
1767+
}
17661768
up_read(&pmd->root_lock);
17671769

17681770
return r;
17691771
}
17701772

17711773
int dm_pool_inc_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e)
17721774
{
1773-
int r = 0;
1775+
int r = -EINVAL;
17741776

17751777
pmd_write_lock(pmd);
1776-
r = dm_sm_inc_blocks(pmd->data_sm, b, e);
1778+
if (!pmd->fail_io)
1779+
r = dm_sm_inc_blocks(pmd->data_sm, b, e);
17771780
pmd_write_unlock(pmd);
17781781

17791782
return r;
17801783
}
17811784

17821785
int dm_pool_dec_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e)
17831786
{
1784-
int r = 0;
1787+
int r = -EINVAL;
17851788

17861789
pmd_write_lock(pmd);
1787-
r = dm_sm_dec_blocks(pmd->data_sm, b, e);
1790+
if (!pmd->fail_io)
1791+
r = dm_sm_dec_blocks(pmd->data_sm, b, e);
17881792
pmd_write_unlock(pmd);
17891793

17901794
return r;

drivers/md/dm-thin.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,7 @@ static int issue_discard(struct discard_op *op, dm_block_t data_b, dm_block_t da
401401
sector_t s = block_to_sectors(tc->pool, data_b);
402402
sector_t len = block_to_sectors(tc->pool, data_e - data_b);
403403

404-
return __blkdev_issue_discard(tc->pool_dev->bdev, s, len, GFP_NOWAIT,
405-
&op->bio);
404+
return __blkdev_issue_discard(tc->pool_dev->bdev, s, len, GFP_NOIO, &op->bio);
406405
}
407406

408407
static void end_discard(struct discard_op *op, int r)

drivers/md/dm.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,7 +1172,8 @@ static inline sector_t max_io_len_target_boundary(struct dm_target *ti,
11721172
}
11731173

11741174
static sector_t __max_io_len(struct dm_target *ti, sector_t sector,
1175-
unsigned int max_granularity)
1175+
unsigned int max_granularity,
1176+
unsigned int max_sectors)
11761177
{
11771178
sector_t target_offset = dm_target_offset(ti, sector);
11781179
sector_t len = max_io_len_target_boundary(ti, target_offset);
@@ -1186,13 +1187,13 @@ static sector_t __max_io_len(struct dm_target *ti, sector_t sector,
11861187
if (!max_granularity)
11871188
return len;
11881189
return min_t(sector_t, len,
1189-
min(queue_max_sectors(ti->table->md->queue),
1190+
min(max_sectors ? : queue_max_sectors(ti->table->md->queue),
11901191
blk_chunk_sectors_left(target_offset, max_granularity)));
11911192
}
11921193

11931194
static inline sector_t max_io_len(struct dm_target *ti, sector_t sector)
11941195
{
1195-
return __max_io_len(ti, sector, ti->max_io_len);
1196+
return __max_io_len(ti, sector, ti->max_io_len, 0);
11961197
}
11971198

11981199
int dm_set_target_max_io_len(struct dm_target *ti, sector_t len)
@@ -1581,12 +1582,13 @@ static void __send_empty_flush(struct clone_info *ci)
15811582

15821583
static void __send_changing_extent_only(struct clone_info *ci, struct dm_target *ti,
15831584
unsigned int num_bios,
1584-
unsigned int max_granularity)
1585+
unsigned int max_granularity,
1586+
unsigned int max_sectors)
15851587
{
15861588
unsigned int len, bios;
15871589

15881590
len = min_t(sector_t, ci->sector_count,
1589-
__max_io_len(ti, ci->sector, max_granularity));
1591+
__max_io_len(ti, ci->sector, max_granularity, max_sectors));
15901592

15911593
atomic_add(num_bios, &ci->io->io_count);
15921594
bios = __send_duplicate_bios(ci, ti, num_bios, &len);
@@ -1623,23 +1625,27 @@ static blk_status_t __process_abnormal_io(struct clone_info *ci,
16231625
{
16241626
unsigned int num_bios = 0;
16251627
unsigned int max_granularity = 0;
1628+
unsigned int max_sectors = 0;
16261629
struct queue_limits *limits = dm_get_queue_limits(ti->table->md);
16271630

16281631
switch (bio_op(ci->bio)) {
16291632
case REQ_OP_DISCARD:
16301633
num_bios = ti->num_discard_bios;
1634+
max_sectors = limits->max_discard_sectors;
16311635
if (ti->max_discard_granularity)
1632-
max_granularity = limits->max_discard_sectors;
1636+
max_granularity = max_sectors;
16331637
break;
16341638
case REQ_OP_SECURE_ERASE:
16351639
num_bios = ti->num_secure_erase_bios;
1640+
max_sectors = limits->max_secure_erase_sectors;
16361641
if (ti->max_secure_erase_granularity)
1637-
max_granularity = limits->max_secure_erase_sectors;
1642+
max_granularity = max_sectors;
16381643
break;
16391644
case REQ_OP_WRITE_ZEROES:
16401645
num_bios = ti->num_write_zeroes_bios;
1646+
max_sectors = limits->max_write_zeroes_sectors;
16411647
if (ti->max_write_zeroes_granularity)
1642-
max_granularity = limits->max_write_zeroes_sectors;
1648+
max_granularity = max_sectors;
16431649
break;
16441650
default:
16451651
break;
@@ -1654,7 +1660,8 @@ static blk_status_t __process_abnormal_io(struct clone_info *ci,
16541660
if (unlikely(!num_bios))
16551661
return BLK_STS_NOTSUPP;
16561662

1657-
__send_changing_extent_only(ci, ti, num_bios, max_granularity);
1663+
__send_changing_extent_only(ci, ti, num_bios,
1664+
max_granularity, max_sectors);
16581665
return BLK_STS_OK;
16591666
}
16601667

@@ -2808,6 +2815,10 @@ int dm_suspend(struct mapped_device *md, unsigned int suspend_flags)
28082815
}
28092816

28102817
map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
2818+
if (!map) {
2819+
/* avoid deadlock with fs/namespace.c:do_mount() */
2820+
suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
2821+
}
28112822

28122823
r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE, DMF_SUSPENDED);
28132824
if (r)

0 commit comments

Comments
 (0)