Enhanced partition statistics: update partition statitics
authorJerome Marchand <jmarchan@redhat.com>
Fri, 8 Feb 2008 10:04:35 +0000 (11:04 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Fri, 8 Feb 2008 11:41:56 +0000 (12:41 +0100)
Updates the enhanced partition statistics in generic block layer
besides the disk statistics.

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
block/blk-core.c
block/blk-merge.c
fs/partitions/check.c
include/linux/genhd.h

index fba4ca7c608648069403c7256a63c38352a25a40..2358fc5de5a4d01de85456e5b6a1ff3cdc261da1 100644 (file)
@@ -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)
index 845ef81311081e719ed3ca9409fad05a0c890bf7..d3b84bbb776a5fd0b3ba3238c7de20e7df93eaeb 100644 (file)
@@ -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);
index 9a64045ff845976b5610609d2c37c86f5f9d1778..f2ec7f1b0ec59805c4c622be05b3c969d1a075da 100644 (file)
@@ -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;
index 589830aca99de75b6ac8a11030e20fd7d6856b41..4cf25a5f415968963ce2281853c2bc0409b68337 100644 (file)
@@ -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);