aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/genhd.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/genhd.h')
-rw-r--r--include/linux/genhd.h355
1 files changed, 173 insertions, 182 deletions
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 118216f1bd3c..206cdf96c3a7 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -11,12 +11,15 @@
11 11
12#include <linux/types.h> 12#include <linux/types.h>
13#include <linux/kdev_t.h> 13#include <linux/kdev_t.h>
14#include <linux/rcupdate.h>
14 15
15#ifdef CONFIG_BLOCK 16#ifdef CONFIG_BLOCK
16 17
17#define kobj_to_dev(k) container_of(k, struct device, kobj) 18#define kobj_to_dev(k) container_of((k), struct device, kobj)
18#define dev_to_disk(device) container_of(device, struct gendisk, dev) 19#define dev_to_disk(device) container_of((device), struct gendisk, part0.__dev)
19#define dev_to_part(device) container_of(device, struct hd_struct, dev) 20#define dev_to_part(device) container_of((device), struct hd_struct, __dev)
21#define disk_to_dev(disk) (&(disk)->part0.__dev)
22#define part_to_dev(part) (&((part)->__dev))
20 23
21extern struct device_type part_type; 24extern struct device_type part_type;
22extern struct kobject *block_depr; 25extern struct kobject *block_depr;
@@ -55,6 +58,9 @@ enum {
55 UNIXWARE_PARTITION = 0x63, /* Same as GNU_HURD and SCO Unix */ 58 UNIXWARE_PARTITION = 0x63, /* Same as GNU_HURD and SCO Unix */
56}; 59};
57 60
61#define DISK_MAX_PARTS 256
62#define DISK_NAME_LEN 32
63
58#include <linux/major.h> 64#include <linux/major.h>
59#include <linux/device.h> 65#include <linux/device.h>
60#include <linux/smp.h> 66#include <linux/smp.h>
@@ -87,7 +93,7 @@ struct disk_stats {
87struct hd_struct { 93struct hd_struct {
88 sector_t start_sect; 94 sector_t start_sect;
89 sector_t nr_sects; 95 sector_t nr_sects;
90 struct device dev; 96 struct device __dev;
91 struct kobject *holder_dir; 97 struct kobject *holder_dir;
92 int policy, partno; 98 int policy, partno;
93#ifdef CONFIG_FAIL_MAKE_REQUEST 99#ifdef CONFIG_FAIL_MAKE_REQUEST
@@ -100,6 +106,7 @@ struct hd_struct {
100#else 106#else
101 struct disk_stats dkstats; 107 struct disk_stats dkstats;
102#endif 108#endif
109 struct rcu_head rcu_head;
103}; 110};
104 111
105#define GENHD_FL_REMOVABLE 1 112#define GENHD_FL_REMOVABLE 1
@@ -108,7 +115,7 @@ struct hd_struct {
108#define GENHD_FL_CD 8 115#define GENHD_FL_CD 8
109#define GENHD_FL_UP 16 116#define GENHD_FL_UP 16
110#define GENHD_FL_SUPPRESS_PARTITION_INFO 32 117#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
111#define GENHD_FL_FAIL 64 118#define GENHD_FL_EXT_DEVT 64 /* allow extended devt */
112 119
113#define BLK_SCSI_MAX_CMDS (256) 120#define BLK_SCSI_MAX_CMDS (256)
114#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8)) 121#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))
@@ -119,99 +126,137 @@ struct blk_scsi_cmd_filter {
119 struct kobject kobj; 126 struct kobject kobj;
120}; 127};
121 128
129struct disk_part_tbl {
130 struct rcu_head rcu_head;
131 int len;
132 struct hd_struct *part[];
133};
134
122struct gendisk { 135struct gendisk {
136 /* major, first_minor and minors are input parameters only,
137 * don't use directly. Use disk_devt() and disk_max_parts().
138 */
123 int major; /* major number of driver */ 139 int major; /* major number of driver */
124 int first_minor; 140 int first_minor;
125 int minors; /* maximum number of minors, =1 for 141 int minors; /* maximum number of minors, =1 for
126 * disks that can't be partitioned. */ 142 * disks that can't be partitioned. */
127 char disk_name[32]; /* name of major driver */ 143
128 struct hd_struct **part; /* [indexed by minor] */ 144 char disk_name[DISK_NAME_LEN]; /* name of major driver */
145
146 /* Array of pointers to partitions indexed by partno.
147 * Protected with matching bdev lock but stat and other
148 * non-critical accesses use RCU. Always access through
149 * helpers.
150 */
151 struct disk_part_tbl *part_tbl;
152 struct hd_struct part0;
153
129 struct block_device_operations *fops; 154 struct block_device_operations *fops;
130 struct request_queue *queue; 155 struct request_queue *queue;
131 struct blk_scsi_cmd_filter cmd_filter;
132 void *private_data; 156 void *private_data;
133 sector_t capacity;
134 157
135 int flags; 158 int flags;
136 struct device *driverfs_dev; // FIXME: remove 159 struct device *driverfs_dev; // FIXME: remove
137 struct device dev;
138 struct kobject *holder_dir;
139 struct kobject *slave_dir; 160 struct kobject *slave_dir;
140 161
141 struct timer_rand_state *random; 162 struct timer_rand_state *random;
142 int policy;
143 163
144 atomic_t sync_io; /* RAID */ 164 atomic_t sync_io; /* RAID */
145 unsigned long stamp;
146 int in_flight;
147#ifdef CONFIG_SMP
148 struct disk_stats *dkstats;
149#else
150 struct disk_stats dkstats;
151#endif
152 struct work_struct async_notify; 165 struct work_struct async_notify;
153#ifdef CONFIG_BLK_DEV_INTEGRITY 166#ifdef CONFIG_BLK_DEV_INTEGRITY
154 struct blk_integrity *integrity; 167 struct blk_integrity *integrity;
155#endif 168#endif
169 int node_id;
156}; 170};
157 171
158/* 172static inline struct gendisk *part_to_disk(struct hd_struct *part)
159 * Macros to operate on percpu disk statistics:
160 *
161 * The __ variants should only be called in critical sections. The full
162 * variants disable/enable preemption.
163 */
164static inline struct hd_struct *get_part(struct gendisk *gendiskp,
165 sector_t sector)
166{ 173{
167 struct hd_struct *part; 174 if (likely(part)) {
168 int i; 175 if (part->partno)
169 for (i = 0; i < gendiskp->minors - 1; i++) { 176 return dev_to_disk(part_to_dev(part)->parent);
170 part = gendiskp->part[i]; 177 else
171 if (part && part->start_sect <= sector 178 return dev_to_disk(part_to_dev(part));
172 && sector < part->start_sect + part->nr_sects)
173 return part;
174 } 179 }
175 return NULL; 180 return NULL;
176} 181}
177 182
178#ifdef CONFIG_SMP 183static inline int disk_max_parts(struct gendisk *disk)
179#define __disk_stat_add(gendiskp, field, addnd) \ 184{
180 (per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd) 185 if (disk->flags & GENHD_FL_EXT_DEVT)
186 return DISK_MAX_PARTS;
187 return disk->minors;
188}
181 189
182#define disk_stat_read(gendiskp, field) \ 190static inline bool disk_partitionable(struct gendisk *disk)
183({ \ 191{
184 typeof(gendiskp->dkstats->field) res = 0; \ 192 return disk_max_parts(disk) > 1;
185 int i; \ 193}
186 for_each_possible_cpu(i) \
187 res += per_cpu_ptr(gendiskp->dkstats, i)->field; \
188 res; \
189})
190 194
191static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { 195static inline dev_t disk_devt(struct gendisk *disk)
192 int i; 196{
197 return disk_to_dev(disk)->devt;
198}
193 199
194 for_each_possible_cpu(i) 200static inline dev_t part_devt(struct hd_struct *part)
195 memset(per_cpu_ptr(gendiskp->dkstats, i), value, 201{
196 sizeof(struct disk_stats)); 202 return part_to_dev(part)->devt;
197} 203}
198 204
199#define __part_stat_add(part, field, addnd) \ 205extern struct hd_struct *disk_get_part(struct gendisk *disk, int partno);
200 (per_cpu_ptr(part->dkstats, smp_processor_id())->field += addnd)
201 206
202#define __all_stat_add(gendiskp, part, field, addnd, sector) \ 207static inline void disk_put_part(struct hd_struct *part)
203({ \ 208{
204 if (part) \ 209 if (likely(part))
205 __part_stat_add(part, field, addnd); \ 210 put_device(part_to_dev(part));
206 __disk_stat_add(gendiskp, field, addnd); \ 211}
207}) 212
213/*
214 * Smarter partition iterator without context limits.
215 */
216#define DISK_PITER_REVERSE (1 << 0) /* iterate in the reverse direction */
217#define DISK_PITER_INCL_EMPTY (1 << 1) /* include 0-sized parts */
218#define DISK_PITER_INCL_PART0 (1 << 2) /* include partition 0 */
219
220struct disk_part_iter {
221 struct gendisk *disk;
222 struct hd_struct *part;
223 int idx;
224 unsigned int flags;
225};
226
227extern void disk_part_iter_init(struct disk_part_iter *piter,
228 struct gendisk *disk, unsigned int flags);
229extern struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter);
230extern void disk_part_iter_exit(struct disk_part_iter *piter);
231
232extern struct hd_struct *disk_map_sector_rcu(struct gendisk *disk,
233 sector_t sector);
234
235/*
236 * Macros to operate on percpu disk statistics:
237 *
238 * {disk|part|all}_stat_{add|sub|inc|dec}() modify the stat counters
239 * and should be called between disk_stat_lock() and
240 * disk_stat_unlock().
241 *
242 * part_stat_read() can be called at any time.
243 *
244 * part_stat_{add|set_all}() and {init|free}_part_stats are for
245 * internal use only.
246 */
247#ifdef CONFIG_SMP
248#define part_stat_lock() ({ rcu_read_lock(); get_cpu(); })
249#define part_stat_unlock() do { put_cpu(); rcu_read_unlock(); } while (0)
250
251#define __part_stat_add(cpu, part, field, addnd) \
252 (per_cpu_ptr((part)->dkstats, (cpu))->field += (addnd))
208 253
209#define part_stat_read(part, field) \ 254#define part_stat_read(part, field) \
210({ \ 255({ \
211 typeof(part->dkstats->field) res = 0; \ 256 typeof((part)->dkstats->field) res = 0; \
212 int i; \ 257 int i; \
213 for_each_possible_cpu(i) \ 258 for_each_possible_cpu(i) \
214 res += per_cpu_ptr(part->dkstats, i)->field; \ 259 res += per_cpu_ptr((part)->dkstats, i)->field; \
215 res; \ 260 res; \
216}) 261})
217 262
@@ -223,171 +268,107 @@ static inline void part_stat_set_all(struct hd_struct *part, int value)
223 memset(per_cpu_ptr(part->dkstats, i), value, 268 memset(per_cpu_ptr(part->dkstats, i), value,
224 sizeof(struct disk_stats)); 269 sizeof(struct disk_stats));
225} 270}
226
227#else /* !CONFIG_SMP */
228#define __disk_stat_add(gendiskp, field, addnd) \
229 (gendiskp->dkstats.field += addnd)
230#define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field)
231 271
232static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) 272static inline int init_part_stats(struct hd_struct *part)
233{ 273{
234 memset(&gendiskp->dkstats, value, sizeof (struct disk_stats)); 274 part->dkstats = alloc_percpu(struct disk_stats);
275 if (!part->dkstats)
276 return 0;
277 return 1;
235} 278}
236 279
237#define __part_stat_add(part, field, addnd) \ 280static inline void free_part_stats(struct hd_struct *part)
238 (part->dkstats.field += addnd)
239
240#define __all_stat_add(gendiskp, part, field, addnd, sector) \
241({ \
242 if (part) \
243 part->dkstats.field += addnd; \
244 __disk_stat_add(gendiskp, field, addnd); \
245})
246
247#define part_stat_read(part, field) (part->dkstats.field)
248
249static inline void part_stat_set_all(struct hd_struct *part, int value)
250{ 281{
251 memset(&part->dkstats, value, sizeof(struct disk_stats)); 282 free_percpu(part->dkstats);
252} 283}
253 284
254#endif /* CONFIG_SMP */ 285#else /* !CONFIG_SMP */
286#define part_stat_lock() ({ rcu_read_lock(); 0; })
287#define part_stat_unlock() rcu_read_unlock()
255 288
256#define disk_stat_add(gendiskp, field, addnd) \ 289#define __part_stat_add(cpu, part, field, addnd) \
257 do { \ 290 ((part)->dkstats.field += addnd)
258 preempt_disable(); \ 291
259 __disk_stat_add(gendiskp, field, addnd); \ 292#define part_stat_read(part, field) ((part)->dkstats.field)
260 preempt_enable(); \
261 } while (0)
262
263#define __disk_stat_dec(gendiskp, field) __disk_stat_add(gendiskp, field, -1)
264#define disk_stat_dec(gendiskp, field) disk_stat_add(gendiskp, field, -1)
265
266#define __disk_stat_inc(gendiskp, field) __disk_stat_add(gendiskp, field, 1)
267#define disk_stat_inc(gendiskp, field) disk_stat_add(gendiskp, field, 1)
268
269#define __disk_stat_sub(gendiskp, field, subnd) \
270 __disk_stat_add(gendiskp, field, -subnd)
271#define disk_stat_sub(gendiskp, field, subnd) \
272 disk_stat_add(gendiskp, field, -subnd)
273
274#define part_stat_add(gendiskp, field, addnd) \
275 do { \
276 preempt_disable(); \
277 __part_stat_add(gendiskp, field, addnd);\
278 preempt_enable(); \
279 } while (0)
280
281#define __part_stat_dec(gendiskp, field) __part_stat_add(gendiskp, field, -1)
282#define part_stat_dec(gendiskp, field) part_stat_add(gendiskp, field, -1)
283
284#define __part_stat_inc(gendiskp, field) __part_stat_add(gendiskp, field, 1)
285#define part_stat_inc(gendiskp, field) part_stat_add(gendiskp, field, 1)
286
287#define __part_stat_sub(gendiskp, field, subnd) \
288 __part_stat_add(gendiskp, field, -subnd)
289#define part_stat_sub(gendiskp, field, subnd) \
290 part_stat_add(gendiskp, field, -subnd)
291
292#define all_stat_add(gendiskp, part, field, addnd, sector) \
293 do { \
294 preempt_disable(); \
295 __all_stat_add(gendiskp, part, field, addnd, sector); \
296 preempt_enable(); \
297 } while (0)
298
299#define __all_stat_dec(gendiskp, field, sector) \
300 __all_stat_add(gendiskp, field, -1, sector)
301#define all_stat_dec(gendiskp, field, sector) \
302 all_stat_add(gendiskp, field, -1, sector)
303
304#define __all_stat_inc(gendiskp, part, field, sector) \
305 __all_stat_add(gendiskp, part, field, 1, sector)
306#define all_stat_inc(gendiskp, part, field, sector) \
307 all_stat_add(gendiskp, part, field, 1, sector)
308
309#define __all_stat_sub(gendiskp, part, field, subnd, sector) \
310 __all_stat_add(gendiskp, part, field, -subnd, sector)
311#define all_stat_sub(gendiskp, part, field, subnd, sector) \
312 all_stat_add(gendiskp, part, field, -subnd, sector)
313
314/* Inlines to alloc and free disk stats in struct gendisk */
315#ifdef CONFIG_SMP
316static inline int init_disk_stats(struct gendisk *disk)
317{
318 disk->dkstats = alloc_percpu(struct disk_stats);
319 if (!disk->dkstats)
320 return 0;
321 return 1;
322}
323 293
324static inline void free_disk_stats(struct gendisk *disk) 294static inline void part_stat_set_all(struct hd_struct *part, int value)
325{ 295{
326 free_percpu(disk->dkstats); 296 memset(&part->dkstats, value, sizeof(struct disk_stats));
327} 297}
328 298
329static inline int init_part_stats(struct hd_struct *part) 299static inline int init_part_stats(struct hd_struct *part)
330{ 300{
331 part->dkstats = alloc_percpu(struct disk_stats);
332 if (!part->dkstats)
333 return 0;
334 return 1; 301 return 1;
335} 302}
336 303
337static inline void free_part_stats(struct hd_struct *part) 304static inline void free_part_stats(struct hd_struct *part)
338{ 305{
339 free_percpu(part->dkstats);
340}
341
342#else /* CONFIG_SMP */
343static inline int init_disk_stats(struct gendisk *disk)
344{
345 return 1;
346} 306}
347 307
348static inline void free_disk_stats(struct gendisk *disk) 308#endif /* CONFIG_SMP */
349{
350}
351 309
352static inline int init_part_stats(struct hd_struct *part) 310#define part_stat_add(cpu, part, field, addnd) do { \
311 __part_stat_add((cpu), (part), field, addnd); \
312 if ((part)->partno) \
313 __part_stat_add((cpu), &part_to_disk((part))->part0, \
314 field, addnd); \
315} while (0)
316
317#define part_stat_dec(cpu, gendiskp, field) \
318 part_stat_add(cpu, gendiskp, field, -1)
319#define part_stat_inc(cpu, gendiskp, field) \
320 part_stat_add(cpu, gendiskp, field, 1)
321#define part_stat_sub(cpu, gendiskp, field, subnd) \
322 part_stat_add(cpu, gendiskp, field, -subnd)
323
324static inline void part_inc_in_flight(struct hd_struct *part)
353{ 325{
354 return 1; 326 part->in_flight++;
327 if (part->partno)
328 part_to_disk(part)->part0.in_flight++;
355} 329}
356 330
357static inline void free_part_stats(struct hd_struct *part) 331static inline void part_dec_in_flight(struct hd_struct *part)
358{ 332{
333 part->in_flight--;
334 if (part->partno)
335 part_to_disk(part)->part0.in_flight--;
359} 336}
360#endif /* CONFIG_SMP */
361 337
362/* drivers/block/ll_rw_blk.c */ 338/* drivers/block/ll_rw_blk.c */
363extern void disk_round_stats(struct gendisk *disk); 339extern void part_round_stats(int cpu, struct hd_struct *part);
364extern void part_round_stats(struct hd_struct *part);
365 340
366/* drivers/block/genhd.c */ 341/* drivers/block/genhd.c */
367extern int get_blkdev_list(char *, int); 342extern int get_blkdev_list(char *, int);
368extern void add_disk(struct gendisk *disk); 343extern void add_disk(struct gendisk *disk);
369extern void del_gendisk(struct gendisk *gp); 344extern void del_gendisk(struct gendisk *gp);
370extern void unlink_gendisk(struct gendisk *gp); 345extern void unlink_gendisk(struct gendisk *gp);
371extern struct gendisk *get_gendisk(dev_t dev, int *part); 346extern struct gendisk *get_gendisk(dev_t dev, int *partno);
347extern struct block_device *bdget_disk(struct gendisk *disk, int partno);
372 348
373extern void set_device_ro(struct block_device *bdev, int flag); 349extern void set_device_ro(struct block_device *bdev, int flag);
374extern void set_disk_ro(struct gendisk *disk, int flag); 350extern void set_disk_ro(struct gendisk *disk, int flag);
375 351
352static inline int get_disk_ro(struct gendisk *disk)
353{
354 return disk->part0.policy;
355}
356
376/* drivers/char/random.c */ 357/* drivers/char/random.c */
377extern void add_disk_randomness(struct gendisk *disk); 358extern void add_disk_randomness(struct gendisk *disk);
378extern void rand_initialize_disk(struct gendisk *disk); 359extern void rand_initialize_disk(struct gendisk *disk);
379 360
380static inline sector_t get_start_sect(struct block_device *bdev) 361static inline sector_t get_start_sect(struct block_device *bdev)
381{ 362{
382 return bdev->bd_contains == bdev ? 0 : bdev->bd_part->start_sect; 363 return bdev->bd_part->start_sect;
383} 364}
384static inline sector_t get_capacity(struct gendisk *disk) 365static inline sector_t get_capacity(struct gendisk *disk)
385{ 366{
386 return disk->capacity; 367 return disk->part0.nr_sects;
387} 368}
388static inline void set_capacity(struct gendisk *disk, sector_t size) 369static inline void set_capacity(struct gendisk *disk, sector_t size)
389{ 370{
390 disk->capacity = size; 371 disk->part0.nr_sects = size;
391} 372}
392 373
393#ifdef CONFIG_SOLARIS_X86_PARTITION 374#ifdef CONFIG_SOLARIS_X86_PARTITION
@@ -537,9 +518,12 @@ struct unixware_disklabel {
537#define ADDPART_FLAG_RAID 1 518#define ADDPART_FLAG_RAID 1
538#define ADDPART_FLAG_WHOLEDISK 2 519#define ADDPART_FLAG_WHOLEDISK 2
539 520
540extern dev_t blk_lookup_devt(const char *name, int part); 521extern int blk_alloc_devt(struct hd_struct *part, dev_t *devt);
541extern char *disk_name (struct gendisk *hd, int part, char *buf); 522extern void blk_free_devt(dev_t devt);
523extern dev_t blk_lookup_devt(const char *name, int partno);
524extern char *disk_name (struct gendisk *hd, int partno, char *buf);
542 525
526extern int disk_expand_part_tbl(struct gendisk *disk, int target);
543extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); 527extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
544extern int __must_check add_partition(struct gendisk *, int, sector_t, sector_t, int); 528extern int __must_check add_partition(struct gendisk *, int, sector_t, sector_t, int);
545extern void delete_partition(struct gendisk *, int); 529extern void delete_partition(struct gendisk *, int);
@@ -556,16 +540,23 @@ extern void blk_register_region(dev_t devt, unsigned long range,
556 void *data); 540 void *data);
557extern void blk_unregister_region(dev_t devt, unsigned long range); 541extern void blk_unregister_region(dev_t devt, unsigned long range);
558 542
559static inline struct block_device *bdget_disk(struct gendisk *disk, int index) 543extern ssize_t part_size_show(struct device *dev,
560{ 544 struct device_attribute *attr, char *buf);
561 return bdget(MKDEV(disk->major, disk->first_minor) + index); 545extern ssize_t part_stat_show(struct device *dev,
562} 546 struct device_attribute *attr, char *buf);
547#ifdef CONFIG_FAIL_MAKE_REQUEST
548extern ssize_t part_fail_show(struct device *dev,
549 struct device_attribute *attr, char *buf);
550extern ssize_t part_fail_store(struct device *dev,
551 struct device_attribute *attr,
552 const char *buf, size_t count);
553#endif /* CONFIG_FAIL_MAKE_REQUEST */
563 554
564#else /* CONFIG_BLOCK */ 555#else /* CONFIG_BLOCK */
565 556
566static inline void printk_all_partitions(void) { } 557static inline void printk_all_partitions(void) { }
567 558
568static inline dev_t blk_lookup_devt(const char *name, int part) 559static inline dev_t blk_lookup_devt(const char *name, int partno)
569{ 560{
570 dev_t devt = MKDEV(0, 0); 561 dev_t devt = MKDEV(0, 0);
571 return devt; 562 return devt;