aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/linux/blkdev.h4
-rw-r--r--include/linux/genhd.h153
2 files changed, 145 insertions, 12 deletions
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 90392a9d7a9c..e1888cc5b8ae 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -137,7 +137,9 @@ enum rq_flag_bits {
137#define BLK_MAX_CDB 16 137#define BLK_MAX_CDB 16
138 138
139/* 139/*
140 * try to put the fields that are referenced together in the same cacheline 140 * try to put the fields that are referenced together in the same cacheline.
141 * if you modify this structure, be sure to check block/blk-core.c:rq_init()
142 * as well!
141 */ 143 */
142struct request { 144struct request {
143 struct list_head queuelist; 145 struct list_head queuelist;
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 1dbea0ac5693..09a3b18918c7 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -91,16 +91,31 @@ 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;
97 struct device dev; 106 struct device dev;
98 struct kobject *holder_dir; 107 struct kobject *holder_dir;
99 unsigned ios[2], sectors[2]; /* READs and WRITEs */
100 int policy, partno; 108 int policy, partno;
101#ifdef CONFIG_FAIL_MAKE_REQUEST 109#ifdef CONFIG_FAIL_MAKE_REQUEST
102 int make_it_fail; 110 int make_it_fail;
103#endif 111#endif
112 unsigned long stamp;
113 int in_flight;
114#ifdef CONFIG_SMP
115 struct disk_stats *dkstats;
116#else
117 struct disk_stats dkstats;
118#endif
104}; 119};
105 120
106#define GENHD_FL_REMOVABLE 1 121#define GENHD_FL_REMOVABLE 1
@@ -111,15 +126,7 @@ struct hd_struct {
111#define GENHD_FL_SUPPRESS_PARTITION_INFO 32 126#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
112#define GENHD_FL_FAIL 64 127#define GENHD_FL_FAIL 64
113 128
114struct disk_stats { 129
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 { 130struct gendisk {
124 int major; /* major number of driver */ 131 int major; /* major number of driver */
125 int first_minor; 132 int first_minor;
@@ -158,6 +165,20 @@ struct gendisk {
158 * The __ variants should only be called in critical sections. The full 165 * The __ variants should only be called in critical sections. The full
159 * variants disable/enable preemption. 166 * variants disable/enable preemption.
160 */ 167 */
168static inline struct hd_struct *get_part(struct gendisk *gendiskp,
169 sector_t sector)
170{
171 struct hd_struct *part;
172 int i;
173 for (i = 0; i < gendiskp->minors - 1; i++) {
174 part = gendiskp->part[i];
175 if (part && part->start_sect <= sector
176 && sector < part->start_sect + part->nr_sects)
177 return part;
178 }
179 return NULL;
180}
181
161#ifdef CONFIG_SMP 182#ifdef CONFIG_SMP
162#define __disk_stat_add(gendiskp, field, addnd) \ 183#define __disk_stat_add(gendiskp, field, addnd) \
163 (per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd) 184 (per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd)
@@ -177,15 +198,62 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) {
177 memset(per_cpu_ptr(gendiskp->dkstats, i), value, 198 memset(per_cpu_ptr(gendiskp->dkstats, i), value,
178 sizeof (struct disk_stats)); 199 sizeof (struct disk_stats));
179} 200}
201
202#define __part_stat_add(part, field, addnd) \
203 (per_cpu_ptr(part->dkstats, smp_processor_id())->field += addnd)
204
205#define __all_stat_add(gendiskp, field, addnd, sector) \
206({ \
207 struct hd_struct *part = get_part(gendiskp, sector); \
208 if (part) \
209 __part_stat_add(part, field, addnd); \
210 __disk_stat_add(gendiskp, field, addnd); \
211})
212
213#define part_stat_read(part, field) \
214({ \
215 typeof(part->dkstats->field) res = 0; \
216 int i; \
217 for_each_possible_cpu(i) \
218 res += per_cpu_ptr(part->dkstats, i)->field; \
219 res; \
220})
221
222static inline void part_stat_set_all(struct hd_struct *part, int value) {
223 int i;
224 for_each_possible_cpu(i)
225 memset(per_cpu_ptr(part->dkstats, i), value,
226 sizeof(struct disk_stats));
227}
180 228
181#else 229#else
182#define __disk_stat_add(gendiskp, field, addnd) \ 230#define __disk_stat_add(gendiskp, field, addnd) \
183 (gendiskp->dkstats.field += addnd) 231 (gendiskp->dkstats.field += addnd)
184#define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) 232#define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field)
185 233
186static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { 234static inline void disk_stat_set_all(struct gendisk *gendiskp, int value)
235{
187 memset(&gendiskp->dkstats, value, sizeof (struct disk_stats)); 236 memset(&gendiskp->dkstats, value, sizeof (struct disk_stats));
188} 237}
238
239#define __part_stat_add(part, field, addnd) \
240 (part->dkstats.field += addnd)
241
242#define __all_stat_add(gendiskp, field, addnd, sector) \
243({ \
244 struct hd_struct *part = get_part(gendiskp, sector); \
245 if (part) \
246 part->dkstats.field += addnd; \
247 __disk_stat_add(gendiskp, field, addnd); \
248})
249
250#define part_stat_read(part, field) (part->dkstats.field)
251
252static inline void part_stat_set_all(struct hd_struct *part, int value)
253{
254 memset(&part->dkstats, value, sizeof(struct disk_stats));
255}
256
189#endif 257#endif
190 258
191#define disk_stat_add(gendiskp, field, addnd) \ 259#define disk_stat_add(gendiskp, field, addnd) \
@@ -206,6 +274,45 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) {
206#define disk_stat_sub(gendiskp, field, subnd) \ 274#define disk_stat_sub(gendiskp, field, subnd) \
207 disk_stat_add(gendiskp, field, -subnd) 275 disk_stat_add(gendiskp, field, -subnd)
208 276
277#define part_stat_add(gendiskp, field, addnd) \
278 do { \
279 preempt_disable(); \
280 __part_stat_add(gendiskp, field, addnd);\
281 preempt_enable(); \
282 } while (0)
283
284#define __part_stat_dec(gendiskp, field) __part_stat_add(gendiskp, field, -1)
285#define part_stat_dec(gendiskp, field) part_stat_add(gendiskp, field, -1)
286
287#define __part_stat_inc(gendiskp, field) __part_stat_add(gendiskp, field, 1)
288#define part_stat_inc(gendiskp, field) part_stat_add(gendiskp, field, 1)
289
290#define __part_stat_sub(gendiskp, field, subnd) \
291 __part_stat_add(gendiskp, field, -subnd)
292#define part_stat_sub(gendiskp, field, subnd) \
293 part_stat_add(gendiskp, field, -subnd)
294
295#define all_stat_add(gendiskp, field, addnd, sector) \
296 do { \
297 preempt_disable(); \
298 __all_stat_add(gendiskp, field, addnd, sector); \
299 preempt_enable(); \
300 } while (0)
301
302#define __all_stat_dec(gendiskp, field, sector) \
303 __all_stat_add(gendiskp, field, -1, sector)
304#define all_stat_dec(gendiskp, field, sector) \
305 all_stat_add(gendiskp, field, -1, sector)
306
307#define __all_stat_inc(gendiskp, field, sector) \
308 __all_stat_add(gendiskp, field, 1, sector)
309#define all_stat_inc(gendiskp, field, sector) \
310 all_stat_add(gendiskp, field, 1, sector)
311
312#define __all_stat_sub(gendiskp, field, subnd, sector) \
313 __all_stat_add(gendiskp, field, -subnd, sector)
314#define all_stat_sub(gendiskp, field, subnd, sector) \
315 all_stat_add(gendiskp, field, -subnd, sector)
209 316
210/* Inlines to alloc and free disk stats in struct gendisk */ 317/* Inlines to alloc and free disk stats in struct gendisk */
211#ifdef CONFIG_SMP 318#ifdef CONFIG_SMP
@@ -221,6 +328,20 @@ static inline void free_disk_stats(struct gendisk *disk)
221{ 328{
222 free_percpu(disk->dkstats); 329 free_percpu(disk->dkstats);
223} 330}
331
332static inline int init_part_stats(struct hd_struct *part)
333{
334 part->dkstats = alloc_percpu(struct disk_stats);
335 if (!part->dkstats)
336 return 0;
337 return 1;
338}
339
340static inline void free_part_stats(struct hd_struct *part)
341{
342 free_percpu(part->dkstats);
343}
344
224#else /* CONFIG_SMP */ 345#else /* CONFIG_SMP */
225static inline int init_disk_stats(struct gendisk *disk) 346static inline int init_disk_stats(struct gendisk *disk)
226{ 347{
@@ -230,10 +351,20 @@ static inline int init_disk_stats(struct gendisk *disk)
230static inline void free_disk_stats(struct gendisk *disk) 351static inline void free_disk_stats(struct gendisk *disk)
231{ 352{
232} 353}
354
355static inline int init_part_stats(struct hd_struct *part)
356{
357 return 1;
358}
359
360static inline void free_part_stats(struct hd_struct *part)
361{
362}
233#endif /* CONFIG_SMP */ 363#endif /* CONFIG_SMP */
234 364
235/* drivers/block/ll_rw_blk.c */ 365/* drivers/block/ll_rw_blk.c */
236extern void disk_round_stats(struct gendisk *disk); 366extern void disk_round_stats(struct gendisk *disk);
367extern void part_round_stats(struct hd_struct *part);
237 368
238/* drivers/block/genhd.c */ 369/* drivers/block/genhd.c */
239extern int get_blkdev_list(char *, int); 370extern int get_blkdev_list(char *, int);