summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/blk-core.c34
-rw-r--r--block/blk-merge.c6
-rw-r--r--fs/partitions/check.c7
-rw-r--r--include/linux/genhd.h1
4 files changed, 44 insertions, 4 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index fba4ca7c6086..2358fc5de5a4 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 845ef8131108..d3b84bbb776a 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 9a64045ff845..f2ec7f1b0ec5 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 589830aca99d..4cf25a5f4159 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);