diff options
author | Shaohua Li <shaohua.li@intel.com> | 2011-03-22 08:35:35 +0100 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2011-03-22 08:35:35 +0100 |
commit | 1e9bb8808ac11094d711d20d580e7b45a4992d0c (patch) | |
tree | d0e228b619664b7f507e37e5eba4a5ebeef103a0 | |
parent | block: attempt to merge with existing requests on plug flush (diff) | |
download | linux-1e9bb8808ac11094d711d20d580e7b45a4992d0c.tar.xz linux-1e9bb8808ac11094d711d20d580e7b45a4992d0c.zip |
block: fix non-atomic access to genhd inflight structures
After the stack plugging introduction, these are called lockless.
Ensure that the counters are updated atomically.
Signed-off-by: Shaohua Li<shaohua.li@intel.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
-rw-r--r-- | drivers/md/dm.c | 7 | ||||
-rw-r--r-- | fs/partitions/check.c | 3 | ||||
-rw-r--r-- | include/linux/genhd.h | 12 |
3 files changed, 12 insertions, 10 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 88820704a191..0cf68b478878 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -477,7 +477,8 @@ static void start_io_acct(struct dm_io *io) cpu = part_stat_lock(); part_round_stats(cpu, &dm_disk(md)->part0); part_stat_unlock(); - dm_disk(md)->part0.in_flight[rw] = atomic_inc_return(&md->pending[rw]); + atomic_set(&dm_disk(md)->part0.in_flight[rw], + atomic_inc_return(&md->pending[rw])); } static void end_io_acct(struct dm_io *io) @@ -497,8 +498,8 @@ static void end_io_acct(struct dm_io *io) * After this is decremented the bio must not be touched if it is * a flush. */ - dm_disk(md)->part0.in_flight[rw] = pending = - atomic_dec_return(&md->pending[rw]); + pending = atomic_dec_return(&md->pending[rw]); + atomic_set(&dm_disk(md)->part0.in_flight[rw], pending); pending += atomic_read(&md->pending[rw^0x1]); /* nudge anyone waiting on suspend queue */ diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 9c21119512b9..ac546975031f 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -290,7 +290,8 @@ ssize_t part_inflight_show(struct device *dev, { struct hd_struct *p = dev_to_part(dev); - return sprintf(buf, "%8u %8u\n", p->in_flight[0], p->in_flight[1]); + return sprintf(buf, "%8u %8u\n", atomic_read(&p->in_flight[0]), + atomic_read(&p->in_flight[1])); } #ifdef CONFIG_FAIL_MAKE_REQUEST diff --git a/include/linux/genhd.h b/include/linux/genhd.h index c0d5f6945c1e..d764a426e9fd 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -109,7 +109,7 @@ struct hd_struct { int make_it_fail; #endif unsigned long stamp; - int in_flight[2]; + atomic_t in_flight[2]; #ifdef CONFIG_SMP struct disk_stats __percpu *dkstats; #else @@ -370,21 +370,21 @@ static inline void free_part_stats(struct hd_struct *part) static inline void part_inc_in_flight(struct hd_struct *part, int rw) { - part->in_flight[rw]++; + atomic_inc(&part->in_flight[rw]); if (part->partno) - part_to_disk(part)->part0.in_flight[rw]++; + atomic_inc(&part_to_disk(part)->part0.in_flight[rw]); } static inline void part_dec_in_flight(struct hd_struct *part, int rw) { - part->in_flight[rw]--; + atomic_dec(&part->in_flight[rw]); if (part->partno) - part_to_disk(part)->part0.in_flight[rw]--; + atomic_dec(&part_to_disk(part)->part0.in_flight[rw]); } static inline int part_in_flight(struct hd_struct *part) { - return part->in_flight[0] + part->in_flight[1]; + return atomic_read(&part->in_flight[0]) + atomic_read(&part->in_flight[1]); } static inline struct partition_meta_info *alloc_part_info(struct gendisk *disk) |