diff options
-rw-r--r-- | block/blk-core.c | 34 | ||||
-rw-r--r-- | block/blk-merge.c | 6 | ||||
-rw-r--r-- | fs/partitions/check.c | 7 | ||||
-rw-r--r-- | include/linux/genhd.h | 1 |
4 files changed, 44 insertions, 4 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index fba4ca7..2358fc5d 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -60,10 +60,15 @@ static void drive_stat_acct(struct request *rq, int new_io) return; if (!new_io) { - __disk_stat_inc(rq->rq_disk, merges[rw]); + __all_stat_inc(rq->rq_disk, merges[rw], rq->sector); } else { + struct hd_struct *part = get_part(rq->rq_disk, rq->sector); disk_round_stats(rq->rq_disk); rq->rq_disk->in_flight++; + if (part) { + part_round_stats(part); + part->in_flight++; + } } } @@ -997,6 +1002,21 @@ void disk_round_stats(struct gendisk *disk) } EXPORT_SYMBOL_GPL(disk_round_stats); +void part_round_stats(struct hd_struct *part) +{ + unsigned long now = jiffies; + + if (now == part->stamp) + return; + + if (part->in_flight) { + __part_stat_add(part, time_in_queue, + part->in_flight * (now - part->stamp)); + __part_stat_add(part, io_ticks, (now - part->stamp)); + } + part->stamp = now; +} + /* * queue lock must be held */ @@ -1530,7 +1550,8 @@ static int __end_that_request_first(struct request *req, int error, if (blk_fs_request(req) && req->rq_disk) { const int rw = rq_data_dir(req); - disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9); + all_stat_add(req->rq_disk, sectors[rw], + nr_bytes >> 9, req->sector); } total_bytes = bio_nbytes = 0; @@ -1715,11 +1736,16 @@ static void end_that_request_last(struct request *req, int error) if (disk && blk_fs_request(req) && req != &req->q->bar_rq) { unsigned long duration = jiffies - req->start_time; const int rw = rq_data_dir(req); + struct hd_struct *part = get_part(disk, req->sector); - __disk_stat_inc(disk, ios[rw]); - __disk_stat_add(disk, ticks[rw], duration); + __all_stat_inc(disk, ios[rw], req->sector); + __all_stat_add(disk, ticks[rw], duration, req->sector); disk_round_stats(disk); disk->in_flight--; + if (part) { + part_round_stats(part); + part->in_flight--; + } } if (req->end_io) diff --git a/block/blk-merge.c b/block/blk-merge.c index 845ef81..d3b84bb 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -454,8 +454,14 @@ static int attempt_merge(struct request_queue *q, struct request *req, elv_merge_requests(q, req, next); if (req->rq_disk) { + struct hd_struct *part + = get_part(req->rq_disk, req->sector); disk_round_stats(req->rq_disk); req->rq_disk->in_flight--; + if (part) { + part_round_stats(part); + part->in_flight--; + } } req->ioprio = ioprio_best(req->ioprio, next->ioprio); diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 9a64045..f2ec7f1 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -18,6 +18,7 @@ #include <linux/fs.h> #include <linux/kmod.h> #include <linux/ctype.h> +#include <linux/genhd.h> #include "check.h" @@ -273,6 +274,7 @@ static struct attribute_group *part_attr_groups[] = { static void part_release(struct device *dev) { struct hd_struct *p = dev_to_part(dev); + free_part_stats(p); kfree(p); } @@ -314,6 +316,7 @@ void delete_partition(struct gendisk *disk, int part) p->nr_sects = 0; p->ios[0] = p->ios[1] = 0; p->sectors[0] = p->sectors[1] = 0; + part_stat_set_all(p, 0); kobject_put(p->holder_dir); device_del(&p->dev); put_device(&p->dev); @@ -336,6 +339,10 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, if (!p) return; + if (!init_part_stats(p)) { + kfree(p); + return; + } p->start_sect = start; p->nr_sects = len; p->partno = part; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 589830a..4cf25a5 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -365,6 +365,7 @@ static inline void free_part_stats(struct hd_struct *part) /* drivers/block/ll_rw_blk.c */ extern void disk_round_stats(struct gendisk *disk); +extern void part_round_stats(struct hd_struct *part); /* drivers/block/genhd.c */ extern int get_blkdev_list(char *, int); |