diff options
author | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-03-14 17:05:45 -0600 |
---|---|---|
committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-03-14 17:05:45 -0600 |
commit | c5111f504d2a9b0d258d7c4752b4093523315989 (patch) | |
tree | 6a52864aff79691689aea21cb0cb928327d5de5b /drivers/md/dm.c | |
parent | 69eb66d7da7dba2696281981347698e1693c2340 (diff) | |
parent | a488edc914aa1d766a4e2c982b5ae03d5657ec1b (diff) |
Merge with /home/shaggy/git/linus-clean/
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r-- | drivers/md/dm.c | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 8c16359f8b0..745ca1f67b1 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -31,6 +31,7 @@ struct dm_io { int error; struct bio *bio; atomic_t io_count; + unsigned long start_time; }; /* @@ -244,6 +245,36 @@ static inline void free_tio(struct mapped_device *md, struct target_io *tio) mempool_free(tio, md->tio_pool); } +static void start_io_acct(struct dm_io *io) +{ + struct mapped_device *md = io->md; + + io->start_time = jiffies; + + preempt_disable(); + disk_round_stats(dm_disk(md)); + preempt_enable(); + dm_disk(md)->in_flight = atomic_inc_return(&md->pending); +} + +static int end_io_acct(struct dm_io *io) +{ + struct mapped_device *md = io->md; + struct bio *bio = io->bio; + unsigned long duration = jiffies - io->start_time; + int pending; + int rw = bio_data_dir(bio); + + preempt_disable(); + disk_round_stats(dm_disk(md)); + preempt_enable(); + dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); + + disk_stat_add(dm_disk(md), ticks[rw], duration); + + return !pending; +} + /* * Add the bio to the list of deferred io. */ @@ -299,7 +330,7 @@ static void dec_pending(struct dm_io *io, int error) io->error = error; if (atomic_dec_and_test(&io->io_count)) { - if (atomic_dec_and_test(&io->md->pending)) + if (end_io_acct(io)) /* nudge anyone waiting on suspend queue */ wake_up(&io->md->wait); @@ -554,7 +585,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) ci.sector_count = bio_sectors(bio); ci.idx = bio->bi_idx; - atomic_inc(&md->pending); + start_io_acct(ci.io); while (ci.sector_count) __clone_and_map(&ci); @@ -573,10 +604,14 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) static int dm_request(request_queue_t *q, struct bio *bio) { int r; + int rw = bio_data_dir(bio); struct mapped_device *md = q->queuedata; down_read(&md->io_lock); + disk_stat_inc(dm_disk(md), ios[rw]); + disk_stat_add(dm_disk(md), sectors[rw], bio_sectors(bio)); + /* * If we're suspended we have to queue * this io for later. @@ -814,10 +849,16 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) static void free_dev(struct mapped_device *md) { - free_minor(md->disk->first_minor); + unsigned int minor = md->disk->first_minor; + + if (md->suspended_bdev) { + thaw_bdev(md->suspended_bdev, NULL); + bdput(md->suspended_bdev); + } mempool_destroy(md->tio_pool); mempool_destroy(md->io_pool); del_gendisk(md->disk); + free_minor(minor); put_disk(md->disk); blk_put_queue(md->queue); kfree(md); |