Commit dcd61984 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-5.15/dm-fixes' of...

Merge tag 'for-5.15/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 verity target to skip redundant processing on I/O errors.

 - Fix request-based DM so that it doesn't queue request to blk-mq when
   DM device is suspended.

 - Fix DM core mempool NULL pointer race when completing IO.

 - Make DM clone target's 'descs' array static.

* tag 'for-5.15/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm: fix mempool NULL pointer race when completing IO
  dm rq: don't queue request to blk-mq during DM suspend
  dm clone: make array 'descs' static
  dm verity: skip redundant verity_handle_err() on I/O errors
parents 304040fb d208b894
...@@ -161,7 +161,7 @@ static const char *clone_device_name(struct clone *clone) ...@@ -161,7 +161,7 @@ static const char *clone_device_name(struct clone *clone)
static void __set_clone_mode(struct clone *clone, enum clone_metadata_mode new_mode) static void __set_clone_mode(struct clone *clone, enum clone_metadata_mode new_mode)
{ {
const char *descs[] = { static const char * const descs[] = {
"read-write", "read-write",
"read-only", "read-only",
"fail" "fail"
......
...@@ -490,6 +490,14 @@ static blk_status_t dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx, ...@@ -490,6 +490,14 @@ static blk_status_t dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
struct mapped_device *md = tio->md; struct mapped_device *md = tio->md;
struct dm_target *ti = md->immutable_target; struct dm_target *ti = md->immutable_target;
/*
* blk-mq's unquiesce may come from outside events, such as
* elevator switch, updating nr_requests or others, and request may
* come during suspend, so simply ask for blk-mq to requeue it.
*/
if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)))
return BLK_STS_RESOURCE;
if (unlikely(!ti)) { if (unlikely(!ti)) {
int srcu_idx; int srcu_idx;
struct dm_table *map = dm_get_live_table(md, &srcu_idx); struct dm_table *map = dm_get_live_table(md, &srcu_idx);
......
...@@ -475,6 +475,7 @@ static int verity_verify_io(struct dm_verity_io *io) ...@@ -475,6 +475,7 @@ static int verity_verify_io(struct dm_verity_io *io)
struct bvec_iter start; struct bvec_iter start;
unsigned b; unsigned b;
struct crypto_wait wait; struct crypto_wait wait;
struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
for (b = 0; b < io->n_blocks; b++) { for (b = 0; b < io->n_blocks; b++) {
int r; int r;
...@@ -529,9 +530,17 @@ static int verity_verify_io(struct dm_verity_io *io) ...@@ -529,9 +530,17 @@ static int verity_verify_io(struct dm_verity_io *io)
else if (verity_fec_decode(v, io, DM_VERITY_BLOCK_TYPE_DATA, else if (verity_fec_decode(v, io, DM_VERITY_BLOCK_TYPE_DATA,
cur_block, NULL, &start) == 0) cur_block, NULL, &start) == 0)
continue; continue;
else if (verity_handle_err(v, DM_VERITY_BLOCK_TYPE_DATA, else {
cur_block)) if (bio->bi_status) {
return -EIO; /*
* Error correction failed; Just return error
*/
return -EIO;
}
if (verity_handle_err(v, DM_VERITY_BLOCK_TYPE_DATA,
cur_block))
return -EIO;
}
} }
return 0; return 0;
......
...@@ -496,18 +496,17 @@ static void start_io_acct(struct dm_io *io) ...@@ -496,18 +496,17 @@ static void start_io_acct(struct dm_io *io)
false, 0, &io->stats_aux); false, 0, &io->stats_aux);
} }
static void end_io_acct(struct dm_io *io) static void end_io_acct(struct mapped_device *md, struct bio *bio,
unsigned long start_time, struct dm_stats_aux *stats_aux)
{ {
struct mapped_device *md = io->md; unsigned long duration = jiffies - start_time;
struct bio *bio = io->orig_bio;
unsigned long duration = jiffies - io->start_time;
bio_end_io_acct(bio, io->start_time); bio_end_io_acct(bio, start_time);
if (unlikely(dm_stats_used(&md->stats))) if (unlikely(dm_stats_used(&md->stats)))
dm_stats_account_io(&md->stats, bio_data_dir(bio), dm_stats_account_io(&md->stats, bio_data_dir(bio),
bio->bi_iter.bi_sector, bio_sectors(bio), bio->bi_iter.bi_sector, bio_sectors(bio),
true, duration, &io->stats_aux); true, duration, stats_aux);
/* nudge anyone waiting on suspend queue */ /* nudge anyone waiting on suspend queue */
if (unlikely(wq_has_sleeper(&md->wait))) if (unlikely(wq_has_sleeper(&md->wait)))
...@@ -790,6 +789,8 @@ void dm_io_dec_pending(struct dm_io *io, blk_status_t error) ...@@ -790,6 +789,8 @@ void dm_io_dec_pending(struct dm_io *io, blk_status_t error)
blk_status_t io_error; blk_status_t io_error;
struct bio *bio; struct bio *bio;
struct mapped_device *md = io->md; struct mapped_device *md = io->md;
unsigned long start_time = 0;
struct dm_stats_aux stats_aux;
/* Push-back supersedes any I/O errors */ /* Push-back supersedes any I/O errors */
if (unlikely(error)) { if (unlikely(error)) {
...@@ -821,8 +822,10 @@ void dm_io_dec_pending(struct dm_io *io, blk_status_t error) ...@@ -821,8 +822,10 @@ void dm_io_dec_pending(struct dm_io *io, blk_status_t error)
} }
io_error = io->status; io_error = io->status;
end_io_acct(io); start_time = io->start_time;
stats_aux = io->stats_aux;
free_io(md, io); free_io(md, io);
end_io_acct(md, bio, start_time, &stats_aux);
if (io_error == BLK_STS_DM_REQUEUE) if (io_error == BLK_STS_DM_REQUEUE)
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment