diff options
-rw-r--r-- | drivers/md/dm.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index c5f9918dab24..724efc63904d 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -47,6 +47,7 @@ struct dm_io { | |||
47 | atomic_t io_count; | 47 | atomic_t io_count; |
48 | struct bio *bio; | 48 | struct bio *bio; |
49 | unsigned long start_time; | 49 | unsigned long start_time; |
50 | spinlock_t endio_lock; | ||
50 | }; | 51 | }; |
51 | 52 | ||
52 | /* | 53 | /* |
@@ -578,8 +579,12 @@ static void dec_pending(struct dm_io *io, int error) | |||
578 | struct mapped_device *md = io->md; | 579 | struct mapped_device *md = io->md; |
579 | 580 | ||
580 | /* Push-back supersedes any I/O errors */ | 581 | /* Push-back supersedes any I/O errors */ |
581 | if (error && !(io->error > 0 && __noflush_suspending(md))) | 582 | if (unlikely(error)) { |
582 | io->error = 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 | if (atomic_dec_and_test(&io->io_count)) { | 589 | if (atomic_dec_and_test(&io->io_count)) { |
585 | if (io->error == DM_ENDIO_REQUEUE) { | 590 | if (io->error == DM_ENDIO_REQUEUE) { |
@@ -1226,6 +1231,7 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio) | |||
1226 | atomic_set(&ci.io->io_count, 1); | 1231 | atomic_set(&ci.io->io_count, 1); |
1227 | ci.io->bio = bio; | 1232 | ci.io->bio = bio; |
1228 | ci.io->md = md; | 1233 | ci.io->md = md; |
1234 | spin_lock_init(&ci.io->endio_lock); | ||
1229 | ci.sector = bio->bi_sector; | 1235 | ci.sector = bio->bi_sector; |
1230 | ci.sector_count = bio_sectors(bio); | 1236 | ci.sector_count = bio_sectors(bio); |
1231 | if (unlikely(bio_empty_barrier(bio))) | 1237 | if (unlikely(bio_empty_barrier(bio))) |