mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
dm stats: check for and propagate alloc_percpu failure
Check alloc_precpu()'s return value and return an error from
dm_stats_init() if it fails. Update alloc_dev() to fail if
dm_stats_init() does.
Otherwise, a NULL pointer dereference will occur in dm_stats_cleanup()
even if dm-stats isn't being actively used.
Fixes: fd2ed4d252
("dm: add statistics support")
Cc: stable@vger.kernel.org
Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
This commit is contained in:
parent
d9a02e016a
commit
d3aa3e060c
@ -188,7 +188,7 @@ static int dm_stat_in_flight(struct dm_stat_shared *shared)
|
|||||||
atomic_read(&shared->in_flight[WRITE]);
|
atomic_read(&shared->in_flight[WRITE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dm_stats_init(struct dm_stats *stats)
|
int dm_stats_init(struct dm_stats *stats)
|
||||||
{
|
{
|
||||||
int cpu;
|
int cpu;
|
||||||
struct dm_stats_last_position *last;
|
struct dm_stats_last_position *last;
|
||||||
@ -197,11 +197,16 @@ void dm_stats_init(struct dm_stats *stats)
|
|||||||
INIT_LIST_HEAD(&stats->list);
|
INIT_LIST_HEAD(&stats->list);
|
||||||
stats->precise_timestamps = false;
|
stats->precise_timestamps = false;
|
||||||
stats->last = alloc_percpu(struct dm_stats_last_position);
|
stats->last = alloc_percpu(struct dm_stats_last_position);
|
||||||
|
if (!stats->last)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
last = per_cpu_ptr(stats->last, cpu);
|
last = per_cpu_ptr(stats->last, cpu);
|
||||||
last->last_sector = (sector_t)ULLONG_MAX;
|
last->last_sector = (sector_t)ULLONG_MAX;
|
||||||
last->last_rw = UINT_MAX;
|
last->last_rw = UINT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dm_stats_cleanup(struct dm_stats *stats)
|
void dm_stats_cleanup(struct dm_stats *stats)
|
||||||
|
@ -21,7 +21,7 @@ struct dm_stats_aux {
|
|||||||
unsigned long long duration_ns;
|
unsigned long long duration_ns;
|
||||||
};
|
};
|
||||||
|
|
||||||
void dm_stats_init(struct dm_stats *st);
|
int dm_stats_init(struct dm_stats *st);
|
||||||
void dm_stats_cleanup(struct dm_stats *st);
|
void dm_stats_cleanup(struct dm_stats *st);
|
||||||
|
|
||||||
struct mapped_device;
|
struct mapped_device;
|
||||||
|
@ -2097,7 +2097,9 @@ static struct mapped_device *alloc_dev(int minor)
|
|||||||
if (!md->pending_io)
|
if (!md->pending_io)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
dm_stats_init(&md->stats);
|
r = dm_stats_init(&md->stats);
|
||||||
|
if (r < 0)
|
||||||
|
goto bad;
|
||||||
|
|
||||||
/* Populate the mapping, nobody knows we exist yet */
|
/* Populate the mapping, nobody knows we exist yet */
|
||||||
spin_lock(&_minor_lock);
|
spin_lock(&_minor_lock);
|
||||||
|
Loading…
Reference in New Issue
Block a user