Commit f88fb981183e71daf40bbd84bc8251bbf7b59e19
Committed by
Alasdair G Kergon
1 parent
03022c54b9
Exists in
master
and in
7 other branches
dm: dec_pending needs locking to save error value
Multiple instances of dec_pending() can run concurrently so a lock is needed when it saves the first error code. I have never experienced actual problem without locking and just found this during code inspection while implementing the barrier support patch for request-based dm. This patch adds the locking. I've done compile, boot and basic I/O testings. Cc: stable@kernel.org Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com> Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Showing 1 changed file with 8 additions and 2 deletions Side-by-side Diff
drivers/md/dm.c
... | ... | @@ -47,6 +47,7 @@ |
47 | 47 | atomic_t io_count; |
48 | 48 | struct bio *bio; |
49 | 49 | unsigned long start_time; |
50 | + spinlock_t endio_lock; | |
50 | 51 | }; |
51 | 52 | |
52 | 53 | /* |
... | ... | @@ -578,8 +579,12 @@ |
578 | 579 | struct mapped_device *md = io->md; |
579 | 580 | |
580 | 581 | /* Push-back supersedes any I/O errors */ |
581 | - if (error && !(io->error > 0 && __noflush_suspending(md))) | |
582 | - io->error = error; | |
582 | + if (unlikely(error)) { | |
583 | + spin_lock_irqsave(&io->endio_lock, flags); | |
584 | + if (!(io->error > 0 && __noflush_suspending(md))) | |
585 | + io->error = error; | |
586 | + spin_unlock_irqrestore(&io->endio_lock, flags); | |
587 | + } | |
583 | 588 | |
584 | 589 | if (atomic_dec_and_test(&io->io_count)) { |
585 | 590 | if (io->error == DM_ENDIO_REQUEUE) { |
... | ... | @@ -1226,6 +1231,7 @@ |
1226 | 1231 | atomic_set(&ci.io->io_count, 1); |
1227 | 1232 | ci.io->bio = bio; |
1228 | 1233 | ci.io->md = md; |
1234 | + spin_lock_init(&ci.io->endio_lock); | |
1229 | 1235 | ci.sector = bio->bi_sector; |
1230 | 1236 | ci.sector_count = bio_sectors(bio); |
1231 | 1237 | if (unlikely(bio_empty_barrier(bio))) |