dm table: fix dm_table_supports_poll to return false if no data devices
It was reported that the "generic/250" test in xfstests (which uses the dm-error target) demonstrates a regression where the kernel crashes in bioset_exit(). Since commitcfc97abcbe
("dm: conditionally enable BIOSET_PERCPU_CACHE for dm_io bioset") the bioset_init() for the dm_io bioset will setup the bioset's per-cpu alloc cache if all devices have QUEUE_FLAG_POLL set. But there was an bug where a target that doesn't have any data devices (and that doesn't even set the .iterate_devices dm target callback) will incorrectly return true from dm_table_supports_poll(). Fix this by updating dm_table_supports_poll() to follow dm-table.c's well-worn pattern for testing that _all_ targets in a DM table do in fact have underlying devices that set QUEUE_FLAG_POLL. NOTE: An additional block fix is still needed so that bio_alloc_cache_destroy() clears the bioset's ->cache member. Otherwise, a DM device's table reload that transitions the DM device's bioset from using a per-cpu alloc cache to _not_ using one will result in bioset_exit() crashing in bio_alloc_cache_destroy() because dm's dm_io bioset ("io_bs") was left with a stale ->cache member. Fixes:cfc97abcbe
("dm: conditionally enable BIOSET_PERCPU_CACHE for dm_io bioset") Reported-by: Matthew Wilcox <willy@infradead.org> Reported-by: Dave Chinner <david@fromorbit.com> Signed-off-by: Mike Snitzer <snitzer@kernel.org>
This commit is contained in:
parent
ca522482e3
commit
9571f829f3
|
@ -1005,7 +1005,7 @@ bool dm_table_request_based(struct dm_table *t)
|
|||
return __table_type_request_based(dm_table_get_type(t));
|
||||
}
|
||||
|
||||
static int dm_table_supports_poll(struct dm_table *t);
|
||||
static bool dm_table_supports_poll(struct dm_table *t);
|
||||
|
||||
static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device *md)
|
||||
{
|
||||
|
@ -1027,7 +1027,7 @@ static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device *
|
|||
per_io_data_size = max(per_io_data_size, ti->per_io_data_size);
|
||||
min_pool_size = max(min_pool_size, ti->num_flush_bios);
|
||||
}
|
||||
poll_supported = !!dm_table_supports_poll(t);
|
||||
poll_supported = dm_table_supports_poll(t);
|
||||
}
|
||||
|
||||
t->mempools = dm_alloc_md_mempools(md, type, per_io_data_size, min_pool_size,
|
||||
|
@ -1547,9 +1547,20 @@ static int count_device(struct dm_target *ti, struct dm_dev *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dm_table_supports_poll(struct dm_table *t)
|
||||
static bool dm_table_supports_poll(struct dm_table *t)
|
||||
{
|
||||
return !dm_table_any_dev_attr(t, device_not_poll_capable, NULL);
|
||||
struct dm_target *ti;
|
||||
unsigned i = 0;
|
||||
|
||||
while (i < dm_table_get_num_targets(t)) {
|
||||
ti = dm_table_get_target(t, i++);
|
||||
|
||||
if (!ti->type->iterate_devices ||
|
||||
ti->type->iterate_devices(ti, device_not_poll_capable, NULL))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue