aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/genhd.h151
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
94struct 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
94struct hd_struct { 103struct 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
114struct 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
123struct gendisk { 131struct 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 */
169static 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
223static 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
186static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { 235static 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
253static 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
333static 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
341static 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 */
225static inline int init_disk_stats(struct gendisk *disk) 347static inline int init_disk_stats(struct gendisk *disk)
226{ 348{
@@ -230,6 +352,15 @@ static inline int init_disk_stats(struct gendisk *disk)
230static inline void free_disk_stats(struct gendisk *disk) 352static inline void free_disk_stats(struct gendisk *disk)
231{ 353{
232} 354}
355
356static inline int init_part_stats(struct hd_struct *part)
357{
358 return 1;
359}
360
361static 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 */