Commit f88fb981 authored by Kiyoshi Ueda's avatar Kiyoshi Ueda Committed by Alasdair G Kergon

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: default avatarKiyoshi Ueda <k-ueda@ct.jp.nec.com>
Signed-off-by: default avatarJun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 03022c54
...@@ -47,6 +47,7 @@ struct dm_io { ...@@ -47,6 +47,7 @@ struct dm_io {
atomic_t io_count; atomic_t io_count;
struct bio *bio; struct bio *bio;
unsigned long start_time; unsigned long start_time;
spinlock_t endio_lock;
}; };
/* /*
...@@ -578,8 +579,12 @@ static void dec_pending(struct dm_io *io, int error) ...@@ -578,8 +579,12 @@ static void dec_pending(struct dm_io *io, int error)
struct mapped_device *md = io->md; struct mapped_device *md = io->md;
/* Push-back supersedes any I/O errors */ /* Push-back supersedes any I/O errors */
if (error && !(io->error > 0 && __noflush_suspending(md))) if (unlikely(error)) {
io->error = error; spin_lock_irqsave(&io->endio_lock, flags);
if (!(io->error > 0 && __noflush_suspending(md)))
io->error = error;
spin_unlock_irqrestore(&io->endio_lock, flags);
}
if (atomic_dec_and_test(&io->io_count)) { if (atomic_dec_and_test(&io->io_count)) {
if (io->error == DM_ENDIO_REQUEUE) { if (io->error == DM_ENDIO_REQUEUE) {
...@@ -1226,6 +1231,7 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio) ...@@ -1226,6 +1231,7 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio)
atomic_set(&ci.io->io_count, 1); atomic_set(&ci.io->io_count, 1);
ci.io->bio = bio; ci.io->bio = bio;
ci.io->md = md; ci.io->md = md;
spin_lock_init(&ci.io->endio_lock);
ci.sector = bio->bi_sector; ci.sector = bio->bi_sector;
ci.sector_count = bio_sectors(bio); ci.sector_count = bio_sectors(bio);
if (unlikely(bio_empty_barrier(bio))) if (unlikely(bio_empty_barrier(bio)))
......
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