diff options
author | Jerome Marchand <jmarchan@redhat.com> | 2008-02-08 05:04:09 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-02-08 06:41:55 -0500 |
commit | ea5c48ab2a76559d4af39e1f7de137c0851ac0a5 (patch) | |
tree | 8bd6168cc7c0209b7ffae8da2e89c35ed50f89db | |
parent | 63a7138671c50a6f2c27bbd1a308dc75967062a3 (diff) |
Enhanced partition statistics: core statistics
This patch contain the core infrastructure of enhanced partition
statistics. It adds to struct hd_struct the same stats data as struct
gendisk and define basics function to manipulate them.
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | include/linux/genhd.h | 151 |
1 files changed, 141 insertions, 10 deletions
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 1dbea0ac5693..589830aca99d 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
@@ -91,6 +91,15 @@ struct partition { | |||
91 | __le32 nr_sects; /* nr of sectors in partition */ | 91 | __le32 nr_sects; /* nr of sectors in partition */ |
92 | } __attribute__((packed)); | 92 | } __attribute__((packed)); |
93 | 93 | ||
94 | struct disk_stats { | ||
95 | unsigned long sectors[2]; /* READs and WRITEs */ | ||
96 | unsigned long ios[2]; | ||
97 | unsigned long merges[2]; | ||
98 | unsigned long ticks[2]; | ||
99 | unsigned long io_ticks; | ||
100 | unsigned long time_in_queue; | ||
101 | }; | ||
102 | |||
94 | struct hd_struct { | 103 | struct hd_struct { |
95 | sector_t start_sect; | 104 | sector_t start_sect; |
96 | sector_t nr_sects; | 105 | sector_t nr_sects; |
@@ -101,6 +110,13 @@ struct hd_struct { | |||
101 | #ifdef CONFIG_FAIL_MAKE_REQUEST | 110 | #ifdef CONFIG_FAIL_MAKE_REQUEST |
102 | int make_it_fail; | 111 | int make_it_fail; |
103 | #endif | 112 | #endif |
113 | unsigned long stamp; | ||
114 | int in_flight; | ||
115 | #ifdef CONFIG_SMP | ||
116 | struct disk_stats *dkstats; | ||
117 | #else | ||
118 | struct disk_stats dkstats; | ||
119 | #endif | ||
104 | }; | 120 | }; |
105 | 121 | ||
106 | #define GENHD_FL_REMOVABLE 1 | 122 | #define GENHD_FL_REMOVABLE 1 |
@@ -111,15 +127,7 @@ struct hd_struct { | |||
111 | #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 | 127 | #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 |
112 | #define GENHD_FL_FAIL 64 | 128 | #define GENHD_FL_FAIL 64 |
113 | 129 | ||
114 | struct disk_stats { | 130 | |
115 | unsigned long sectors[2]; /* READs and WRITEs */ | ||
116 | unsigned long ios[2]; | ||
117 | unsigned long merges[2]; | ||
118 | unsigned long ticks[2]; | ||
119 | unsigned long io_ticks; | ||
120 | unsigned long time_in_queue; | ||
121 | }; | ||
122 | |||
123 | struct gendisk { | 131 | struct gendisk { |
124 | int major; /* major number of driver */ | 132 | int major; /* major number of driver */ |
125 | int first_minor; | 133 | int first_minor; |
@@ -158,6 +166,20 @@ struct gendisk { | |||
158 | * The __ variants should only be called in critical sections. The full | 166 | * The __ variants should only be called in critical sections. The full |
159 | * variants disable/enable preemption. | 167 | * variants disable/enable preemption. |
160 | */ | 168 | */ |
169 | static inline struct hd_struct *get_part(struct gendisk *gendiskp, | ||
170 | sector_t sector) | ||
171 | { | ||
172 | struct hd_struct *part; | ||
173 | int i; | ||
174 | for (i = 0; i < gendiskp->minors - 1; i++) { | ||
175 | part = gendiskp->part[i]; | ||
176 | if (part && part->start_sect <= sector | ||
177 | && sector < part->start_sect + part->nr_sects) | ||
178 | return part; | ||
179 | } | ||
180 | return NULL; | ||
181 | } | ||
182 | |||
161 | #ifdef CONFIG_SMP | 183 | #ifdef CONFIG_SMP |
162 | #define __disk_stat_add(gendiskp, field, addnd) \ | 184 | #define __disk_stat_add(gendiskp, field, addnd) \ |
163 | (per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd) | 185 | (per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd) |
@@ -177,15 +199,62 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { | |||
177 | memset(per_cpu_ptr(gendiskp->dkstats, i), value, | 199 | memset(per_cpu_ptr(gendiskp->dkstats, i), value, |
178 | sizeof (struct disk_stats)); | 200 | sizeof (struct disk_stats)); |
179 | } | 201 | } |
202 | |||
203 | #define __part_stat_add(part, field, addnd) \ | ||
204 | (per_cpu_ptr(part->dkstats, smp_processor_id())->field += addnd) | ||
205 | |||
206 | #define __all_stat_add(gendiskp, field, addnd, sector) \ | ||
207 | ({ \ | ||
208 | struct hd_struct *part = get_part(gendiskp, sector); \ | ||
209 | if (part) \ | ||
210 | __part_stat_add(part, field, addnd); \ | ||
211 | __disk_stat_add(gendiskp, field, addnd); \ | ||
212 | }) | ||
213 | |||
214 | #define part_stat_read(part, field) \ | ||
215 | ({ \ | ||
216 | typeof(part->dkstats->field) res = 0; \ | ||
217 | int i; \ | ||
218 | for_each_possible_cpu(i) \ | ||
219 | res += per_cpu_ptr(part->dkstats, i)->field; \ | ||
220 | res; \ | ||
221 | }) | ||
222 | |||
223 | static inline void part_stat_set_all(struct hd_struct *part, int value) { | ||
224 | int i; | ||
225 | for_each_possible_cpu(i) | ||
226 | memset(per_cpu_ptr(part->dkstats, i), value, | ||
227 | sizeof(struct disk_stats)); | ||
228 | } | ||
180 | 229 | ||
181 | #else | 230 | #else |
182 | #define __disk_stat_add(gendiskp, field, addnd) \ | 231 | #define __disk_stat_add(gendiskp, field, addnd) \ |
183 | (gendiskp->dkstats.field += addnd) | 232 | (gendiskp->dkstats.field += addnd) |
184 | #define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) | 233 | #define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) |
185 | 234 | ||
186 | static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { | 235 | static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) |
236 | { | ||
187 | memset(&gendiskp->dkstats, value, sizeof (struct disk_stats)); | 237 | memset(&gendiskp->dkstats, value, sizeof (struct disk_stats)); |
188 | } | 238 | } |
239 | |||
240 | #define __part_stat_add(part, field, addnd) \ | ||
241 | (part->dkstats.field += addnd) | ||
242 | |||
243 | #define __all_stat_add(gendiskp, field, addnd, sector) \ | ||
244 | ({ \ | ||
245 | struct hd_struct *part = get_part(gendiskp, sector); \ | ||
246 | if (part) \ | ||
247 | part->dkstats.field += addnd; \ | ||
248 | __disk_stat_add(gendiskp, field, addnd); \ | ||
249 | }) | ||
250 | |||
251 | #define part_stat_read(part, field) (part->dkstats.field) | ||
252 | |||
253 | static inline void part_stat_set_all(struct hd_struct *part, int value) | ||
254 | { | ||
255 | memset(&part->dkstats, value, sizeof(struct disk_stats)); | ||
256 | } | ||
257 | |||
189 | #endif | 258 | #endif |
190 | 259 | ||
191 | #define disk_stat_add(gendiskp, field, addnd) \ | 260 | #define disk_stat_add(gendiskp, field, addnd) \ |
@@ -206,6 +275,45 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { | |||
206 | #define disk_stat_sub(gendiskp, field, subnd) \ | 275 | #define disk_stat_sub(gendiskp, field, subnd) \ |
207 | disk_stat_add(gendiskp, field, -subnd) | 276 | disk_stat_add(gendiskp, field, -subnd) |
208 | 277 | ||
278 | #define part_stat_add(gendiskp, field, addnd) \ | ||
279 | do { \ | ||
280 | preempt_disable(); \ | ||
281 | __part_stat_add(gendiskp, field, addnd);\ | ||
282 | preempt_enable(); \ | ||
283 | } while (0) | ||
284 | |||
285 | #define __part_stat_dec(gendiskp, field) __part_stat_add(gendiskp, field, -1) | ||
286 | #define part_stat_dec(gendiskp, field) part_stat_add(gendiskp, field, -1) | ||
287 | |||
288 | #define __part_stat_inc(gendiskp, field) __part_stat_add(gendiskp, field, 1) | ||
289 | #define part_stat_inc(gendiskp, field) part_stat_add(gendiskp, field, 1) | ||
290 | |||
291 | #define __part_stat_sub(gendiskp, field, subnd) \ | ||
292 | __part_stat_add(gendiskp, field, -subnd) | ||
293 | #define part_stat_sub(gendiskp, field, subnd) \ | ||
294 | part_stat_add(gendiskp, field, -subnd) | ||
295 | |||
296 | #define all_stat_add(gendiskp, field, addnd, sector) \ | ||
297 | do { \ | ||
298 | preempt_disable(); \ | ||
299 | __all_stat_add(gendiskp, field, addnd, sector); \ | ||
300 | preempt_enable(); \ | ||
301 | } while (0) | ||
302 | |||
303 | #define __all_stat_dec(gendiskp, field, sector) \ | ||
304 | __all_stat_add(gendiskp, field, -1, sector) | ||
305 | #define all_stat_dec(gendiskp, field, sector) \ | ||
306 | all_stat_add(gendiskp, field, -1, sector) | ||
307 | |||
308 | #define __all_stat_inc(gendiskp, field, sector) \ | ||
309 | __all_stat_add(gendiskp, field, 1, sector) | ||
310 | #define all_stat_inc(gendiskp, field, sector) \ | ||
311 | all_stat_add(gendiskp, field, 1, sector) | ||
312 | |||
313 | #define __all_stat_sub(gendiskp, field, subnd, sector) \ | ||
314 | __all_stat_add(gendiskp, field, -subnd, sector) | ||
315 | #define all_stat_sub(gendiskp, field, subnd, sector) \ | ||
316 | all_stat_add(gendiskp, field, -subnd, sector) | ||
209 | 317 | ||
210 | /* Inlines to alloc and free disk stats in struct gendisk */ | 318 | /* Inlines to alloc and free disk stats in struct gendisk */ |
211 | #ifdef CONFIG_SMP | 319 | #ifdef CONFIG_SMP |
@@ -221,6 +329,20 @@ static inline void free_disk_stats(struct gendisk *disk) | |||
221 | { | 329 | { |
222 | free_percpu(disk->dkstats); | 330 | free_percpu(disk->dkstats); |
223 | } | 331 | } |
332 | |||
333 | static inline int init_part_stats(struct hd_struct *part) | ||
334 | { | ||
335 | part->dkstats = alloc_percpu(struct disk_stats); | ||
336 | if (!part->dkstats) | ||
337 | return 0; | ||
338 | return 1; | ||
339 | } | ||
340 | |||
341 | static inline void free_part_stats(struct hd_struct *part) | ||
342 | { | ||
343 | free_percpu(part->dkstats); | ||
344 | } | ||
345 | |||
224 | #else /* CONFIG_SMP */ | 346 | #else /* CONFIG_SMP */ |
225 | static inline int init_disk_stats(struct gendisk *disk) | 347 | static inline int init_disk_stats(struct gendisk *disk) |
226 | { | 348 | { |
@@ -230,6 +352,15 @@ static inline int init_disk_stats(struct gendisk *disk) | |||
230 | static inline void free_disk_stats(struct gendisk *disk) | 352 | static inline void free_disk_stats(struct gendisk *disk) |
231 | { | 353 | { |
232 | } | 354 | } |
355 | |||
356 | static inline int init_part_stats(struct hd_struct *part) | ||
357 | { | ||
358 | return 1; | ||
359 | } | ||
360 | |||
361 | static inline void free_part_stats(struct hd_struct *part) | ||
362 | { | ||
363 | } | ||
233 | #endif /* CONFIG_SMP */ | 364 | #endif /* CONFIG_SMP */ |
234 | 365 | ||
235 | /* drivers/block/ll_rw_blk.c */ | 366 | /* drivers/block/ll_rw_blk.c */ |