Commit 220841906fccafaf4094e87bdb6d252e20cf8c7c

Authored by Vivek Goyal
Committed by Jens Axboe
1 parent 2868ef7b39

blkio: Export disk time and sectors used by a group to user space

o Export disk time and sector used by a group to user space through cgroup
  interface.

o Also export a "dequeue" interface to cgroup which keeps track of how many
  a times a group was deleted from service tree. Helps in debugging.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

Showing 3 changed files with 99 additions and 6 deletions Side-by-side Diff

... ... @@ -11,6 +11,8 @@
11 11 * Nauman Rafique <nauman@google.com>
12 12 */
13 13 #include <linux/ioprio.h>
  14 +#include <linux/seq_file.h>
  15 +#include <linux/kdev_t.h>
14 16 #include "blk-cgroup.h"
15 17  
16 18 extern void cfq_unlink_blkio_group(void *, struct blkio_group *);
17 19  
... ... @@ -23,8 +25,15 @@
23 25 struct blkio_cgroup, css);
24 26 }
25 27  
  28 +void blkiocg_update_blkio_group_stats(struct blkio_group *blkg,
  29 + unsigned long time, unsigned long sectors)
  30 +{
  31 + blkg->time += time;
  32 + blkg->sectors += sectors;
  33 +}
  34 +
26 35 void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
27   - struct blkio_group *blkg, void *key)
  36 + struct blkio_group *blkg, void *key, dev_t dev)
28 37 {
29 38 unsigned long flags;
30 39  
... ... @@ -37,6 +46,7 @@
37 46 /* Need to take css reference ? */
38 47 cgroup_path(blkcg->css.cgroup, blkg->path, sizeof(blkg->path));
39 48 #endif
  49 + blkg->dev = dev;
40 50 }
41 51  
42 52 static void __blkiocg_del_blkio_group(struct blkio_group *blkg)
43 53  
... ... @@ -115,12 +125,64 @@
115 125 return 0;
116 126 }
117 127  
  128 +#define SHOW_FUNCTION_PER_GROUP(__VAR) \
  129 +static int blkiocg_##__VAR##_read(struct cgroup *cgroup, \
  130 + struct cftype *cftype, struct seq_file *m) \
  131 +{ \
  132 + struct blkio_cgroup *blkcg; \
  133 + struct blkio_group *blkg; \
  134 + struct hlist_node *n; \
  135 + \
  136 + if (!cgroup_lock_live_group(cgroup)) \
  137 + return -ENODEV; \
  138 + \
  139 + blkcg = cgroup_to_blkio_cgroup(cgroup); \
  140 + rcu_read_lock(); \
  141 + hlist_for_each_entry_rcu(blkg, n, &blkcg->blkg_list, blkcg_node) {\
  142 + if (blkg->dev) \
  143 + seq_printf(m, "%u:%u %lu\n", MAJOR(blkg->dev), \
  144 + MINOR(blkg->dev), blkg->__VAR); \
  145 + } \
  146 + rcu_read_unlock(); \
  147 + cgroup_unlock(); \
  148 + return 0; \
  149 +}
  150 +
  151 +SHOW_FUNCTION_PER_GROUP(time);
  152 +SHOW_FUNCTION_PER_GROUP(sectors);
  153 +#ifdef CONFIG_DEBUG_BLK_CGROUP
  154 +SHOW_FUNCTION_PER_GROUP(dequeue);
  155 +#endif
  156 +#undef SHOW_FUNCTION_PER_GROUP
  157 +
  158 +#ifdef CONFIG_DEBUG_BLK_CGROUP
  159 +void blkiocg_update_blkio_group_dequeue_stats(struct blkio_group *blkg,
  160 + unsigned long dequeue)
  161 +{
  162 + blkg->dequeue += dequeue;
  163 +}
  164 +#endif
  165 +
118 166 struct cftype blkio_files[] = {
119 167 {
120 168 .name = "weight",
121 169 .read_u64 = blkiocg_weight_read,
122 170 .write_u64 = blkiocg_weight_write,
123 171 },
  172 + {
  173 + .name = "time",
  174 + .read_seq_string = blkiocg_time_read,
  175 + },
  176 + {
  177 + .name = "sectors",
  178 + .read_seq_string = blkiocg_sectors_read,
  179 + },
  180 +#ifdef CONFIG_DEBUG_BLK_CGROUP
  181 + {
  182 + .name = "dequeue",
  183 + .read_seq_string = blkiocg_dequeue_read,
  184 + },
  185 +#endif
124 186 };
125 187  
126 188 static int blkiocg_populate(struct cgroup_subsys *subsys, struct cgroup *cgroup)
... ... @@ -30,7 +30,15 @@
30 30 #ifdef CONFIG_DEBUG_BLK_CGROUP
31 31 /* Store cgroup path */
32 32 char path[128];
  33 + /* How many times this group has been removed from service tree */
  34 + unsigned long dequeue;
33 35 #endif
  36 + /* The device MKDEV(major, minor), this group has been created for */
  37 + dev_t dev;
  38 +
  39 + /* total disk time and nr sectors dispatched by this group */
  40 + unsigned long time;
  41 + unsigned long sectors;
34 42 };
35 43  
36 44 #define BLKIO_WEIGHT_MIN 100
37 45  
38 46  
39 47  
40 48  
... ... @@ -42,24 +50,30 @@
42 50 {
43 51 return blkg->path;
44 52 }
  53 +void blkiocg_update_blkio_group_dequeue_stats(struct blkio_group *blkg,
  54 + unsigned long dequeue);
45 55 #else
46 56 static inline char *blkg_path(struct blkio_group *blkg) { return NULL; }
  57 +static inline void blkiocg_update_blkio_group_dequeue_stats(
  58 + struct blkio_group *blkg, unsigned long dequeue) {}
47 59 #endif
48 60  
49 61 #ifdef CONFIG_BLK_CGROUP
50 62 extern struct blkio_cgroup blkio_root_cgroup;
51 63 extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup);
52 64 extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
53   - struct blkio_group *blkg, void *key);
  65 + struct blkio_group *blkg, void *key, dev_t dev);
54 66 extern int blkiocg_del_blkio_group(struct blkio_group *blkg);
55 67 extern struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg,
56 68 void *key);
  69 +void blkiocg_update_blkio_group_stats(struct blkio_group *blkg,
  70 + unsigned long time, unsigned long sectors);
57 71 #else
58 72 static inline struct blkio_cgroup *
59 73 cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; }
60 74  
61 75 static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
62   - struct blkio_group *blkg, void *key)
  76 + struct blkio_group *blkg, void *key, dev_t dev)
63 77 {
64 78 }
65 79  
... ... @@ -68,6 +82,10 @@
68 82  
69 83 static inline struct blkio_group *
70 84 blkiocg_lookup_group(struct blkio_cgroup *blkcg, void *key) { return NULL; }
  85 +static inline void blkiocg_update_blkio_group_stats(struct blkio_group *blkg,
  86 + unsigned long time, unsigned long sectors)
  87 +{
  88 +}
71 89 #endif
72 90 #endif /* _BLK_CGROUP_H */
... ... @@ -143,6 +143,8 @@
143 143 struct cfq_rb_root *service_tree;
144 144 struct cfq_queue *new_cfqq;
145 145 struct cfq_group *cfqg;
  146 + /* Sectors dispatched in current dispatch round */
  147 + unsigned long nr_sectors;
146 148 };
147 149  
148 150 /*
... ... @@ -852,6 +854,7 @@
852 854 if (!RB_EMPTY_NODE(&cfqg->rb_node))
853 855 cfq_rb_erase(&cfqg->rb_node, st);
854 856 cfqg->saved_workload_slice = 0;
  857 + blkiocg_update_blkio_group_dequeue_stats(&cfqg->blkg, 1);
855 858 }
856 859  
857 860 static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq)
... ... @@ -878,7 +881,8 @@
878 881 slice_used = allocated_slice;
879 882 }
880 883  
881   - cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u", slice_used);
  884 + cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u sect=%lu", slice_used,
  885 + cfqq->nr_sectors);
882 886 return slice_used;
883 887 }
884 888  
... ... @@ -906,6 +910,8 @@
906 910  
907 911 cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime,
908 912 st->min_vdisktime);
  913 + blkiocg_update_blkio_group_stats(&cfqg->blkg, used_sl,
  914 + cfqq->nr_sectors);
909 915 }
910 916  
911 917 #ifdef CONFIG_CFQ_GROUP_IOSCHED
... ... @@ -924,6 +930,8 @@
924 930 void *key = cfqd;
925 931 int i, j;
926 932 struct cfq_rb_root *st;
  933 + struct backing_dev_info *bdi = &cfqd->queue->backing_dev_info;
  934 + unsigned int major, minor;
927 935  
928 936 /* Do we need to take this reference */
929 937 if (!css_tryget(&blkcg->css))
... ... @@ -951,7 +959,9 @@
951 959 atomic_set(&cfqg->ref, 1);
952 960  
953 961 /* Add group onto cgroup list */
954   - blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd);
  962 + sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
  963 + blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd,
  964 + MKDEV(major, minor));
955 965  
956 966 /* Add group on cfqd list */
957 967 hlist_add_head(&cfqg->cfqd_node, &cfqd->cfqg_list);
... ... @@ -1478,6 +1488,7 @@
1478 1488 cfqq->dispatch_start = jiffies;
1479 1489 cfqq->slice_end = 0;
1480 1490 cfqq->slice_dispatch = 0;
  1491 + cfqq->nr_sectors = 0;
1481 1492  
1482 1493 cfq_clear_cfqq_wait_request(cfqq);
1483 1494 cfq_clear_cfqq_must_dispatch(cfqq);
... ... @@ -1801,6 +1812,7 @@
1801 1812  
1802 1813 if (cfq_cfqq_sync(cfqq))
1803 1814 cfqd->sync_flight++;
  1815 + cfqq->nr_sectors += blk_rq_sectors(rq);
1804 1816 }
1805 1817  
1806 1818 /*
... ... @@ -3513,7 +3525,8 @@
3513 3525 * to make sure that cfq_put_cfqg() does not try to kfree root group
3514 3526 */
3515 3527 atomic_set(&cfqg->ref, 1);
3516   - blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, (void *)cfqd);
  3528 + blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, (void *)cfqd,
  3529 + 0);
3517 3530 #endif
3518 3531 /*
3519 3532 * Not strictly needed (since RB_ROOT just clears the node and we