diff options
Diffstat (limited to 'include/linux/genhd.h')
-rw-r--r-- | include/linux/genhd.h | 117 |
1 files changed, 103 insertions, 14 deletions
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 5f2f4c4d8fb0..300d7582006e 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
@@ -12,6 +12,7 @@ | |||
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 | #include <linux/rcupdate.h> |
15 | #include <linux/slab.h> | ||
15 | 16 | ||
16 | #ifdef CONFIG_BLOCK | 17 | #ifdef CONFIG_BLOCK |
17 | 18 | ||
@@ -86,7 +87,15 @@ struct disk_stats { | |||
86 | unsigned long io_ticks; | 87 | unsigned long io_ticks; |
87 | unsigned long time_in_queue; | 88 | unsigned long time_in_queue; |
88 | }; | 89 | }; |
89 | 90 | ||
91 | #define PARTITION_META_INFO_VOLNAMELTH 64 | ||
92 | #define PARTITION_META_INFO_UUIDLTH 16 | ||
93 | |||
94 | struct partition_meta_info { | ||
95 | u8 uuid[PARTITION_META_INFO_UUIDLTH]; /* always big endian */ | ||
96 | u8 volname[PARTITION_META_INFO_VOLNAMELTH]; | ||
97 | }; | ||
98 | |||
90 | struct hd_struct { | 99 | struct hd_struct { |
91 | sector_t start_sect; | 100 | sector_t start_sect; |
92 | sector_t nr_sects; | 101 | sector_t nr_sects; |
@@ -95,16 +104,18 @@ struct hd_struct { | |||
95 | struct device __dev; | 104 | struct device __dev; |
96 | struct kobject *holder_dir; | 105 | struct kobject *holder_dir; |
97 | int policy, partno; | 106 | int policy, partno; |
107 | struct partition_meta_info *info; | ||
98 | #ifdef CONFIG_FAIL_MAKE_REQUEST | 108 | #ifdef CONFIG_FAIL_MAKE_REQUEST |
99 | int make_it_fail; | 109 | int make_it_fail; |
100 | #endif | 110 | #endif |
101 | unsigned long stamp; | 111 | unsigned long stamp; |
102 | int in_flight[2]; | 112 | atomic_t in_flight[2]; |
103 | #ifdef CONFIG_SMP | 113 | #ifdef CONFIG_SMP |
104 | struct disk_stats __percpu *dkstats; | 114 | struct disk_stats __percpu *dkstats; |
105 | #else | 115 | #else |
106 | struct disk_stats dkstats; | 116 | struct disk_stats dkstats; |
107 | #endif | 117 | #endif |
118 | atomic_t ref; | ||
108 | struct rcu_head rcu_head; | 119 | struct rcu_head rcu_head; |
109 | }; | 120 | }; |
110 | 121 | ||
@@ -116,6 +127,12 @@ struct hd_struct { | |||
116 | #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 | 127 | #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 |
117 | #define GENHD_FL_EXT_DEVT 64 /* allow extended devt */ | 128 | #define GENHD_FL_EXT_DEVT 64 /* allow extended devt */ |
118 | #define GENHD_FL_NATIVE_CAPACITY 128 | 129 | #define GENHD_FL_NATIVE_CAPACITY 128 |
130 | #define GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE 256 | ||
131 | |||
132 | enum { | ||
133 | DISK_EVENT_MEDIA_CHANGE = 1 << 0, /* media changed */ | ||
134 | DISK_EVENT_EJECT_REQUEST = 1 << 1, /* eject requested */ | ||
135 | }; | ||
119 | 136 | ||
120 | #define BLK_SCSI_MAX_CMDS (256) | 137 | #define BLK_SCSI_MAX_CMDS (256) |
121 | #define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8)) | 138 | #define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8)) |
@@ -129,10 +146,12 @@ struct blk_scsi_cmd_filter { | |||
129 | struct disk_part_tbl { | 146 | struct disk_part_tbl { |
130 | struct rcu_head rcu_head; | 147 | struct rcu_head rcu_head; |
131 | int len; | 148 | int len; |
132 | struct hd_struct *last_lookup; | 149 | struct hd_struct __rcu *last_lookup; |
133 | struct hd_struct *part[]; | 150 | struct hd_struct __rcu *part[]; |
134 | }; | 151 | }; |
135 | 152 | ||
153 | struct disk_events; | ||
154 | |||
136 | struct gendisk { | 155 | struct gendisk { |
137 | /* major, first_minor and minors are input parameters only, | 156 | /* major, first_minor and minors are input parameters only, |
138 | * don't use directly. Use disk_devt() and disk_max_parts(). | 157 | * don't use directly. Use disk_devt() and disk_max_parts(). |
@@ -144,12 +163,16 @@ struct gendisk { | |||
144 | 163 | ||
145 | char disk_name[DISK_NAME_LEN]; /* name of major driver */ | 164 | char disk_name[DISK_NAME_LEN]; /* name of major driver */ |
146 | char *(*devnode)(struct gendisk *gd, mode_t *mode); | 165 | char *(*devnode)(struct gendisk *gd, mode_t *mode); |
166 | |||
167 | unsigned int events; /* supported events */ | ||
168 | unsigned int async_events; /* async events, subset of all */ | ||
169 | |||
147 | /* Array of pointers to partitions indexed by partno. | 170 | /* Array of pointers to partitions indexed by partno. |
148 | * Protected with matching bdev lock but stat and other | 171 | * Protected with matching bdev lock but stat and other |
149 | * non-critical accesses use RCU. Always access through | 172 | * non-critical accesses use RCU. Always access through |
150 | * helpers. | 173 | * helpers. |
151 | */ | 174 | */ |
152 | struct disk_part_tbl *part_tbl; | 175 | struct disk_part_tbl __rcu *part_tbl; |
153 | struct hd_struct part0; | 176 | struct hd_struct part0; |
154 | 177 | ||
155 | const struct block_device_operations *fops; | 178 | const struct block_device_operations *fops; |
@@ -161,9 +184,8 @@ struct gendisk { | |||
161 | struct kobject *slave_dir; | 184 | struct kobject *slave_dir; |
162 | 185 | ||
163 | struct timer_rand_state *random; | 186 | struct timer_rand_state *random; |
164 | |||
165 | atomic_t sync_io; /* RAID */ | 187 | atomic_t sync_io; /* RAID */ |
166 | struct work_struct async_notify; | 188 | struct disk_events *ev; |
167 | #ifdef CONFIG_BLK_DEV_INTEGRITY | 189 | #ifdef CONFIG_BLK_DEV_INTEGRITY |
168 | struct blk_integrity *integrity; | 190 | struct blk_integrity *integrity; |
169 | #endif | 191 | #endif |
@@ -181,6 +203,30 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part) | |||
181 | return NULL; | 203 | return NULL; |
182 | } | 204 | } |
183 | 205 | ||
206 | static inline void part_pack_uuid(const u8 *uuid_str, u8 *to) | ||
207 | { | ||
208 | int i; | ||
209 | for (i = 0; i < 16; ++i) { | ||
210 | *to++ = (hex_to_bin(*uuid_str) << 4) | | ||
211 | (hex_to_bin(*(uuid_str + 1))); | ||
212 | uuid_str += 2; | ||
213 | switch (i) { | ||
214 | case 3: | ||
215 | case 5: | ||
216 | case 7: | ||
217 | case 9: | ||
218 | uuid_str++; | ||
219 | continue; | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | |||
224 | static inline char *part_unpack_uuid(const u8 *uuid, char *out) | ||
225 | { | ||
226 | sprintf(out, "%pU", uuid); | ||
227 | return out; | ||
228 | } | ||
229 | |||
184 | static inline int disk_max_parts(struct gendisk *disk) | 230 | static inline int disk_max_parts(struct gendisk *disk) |
185 | { | 231 | { |
186 | if (disk->flags & GENHD_FL_EXT_DEVT) | 232 | if (disk->flags & GENHD_FL_EXT_DEVT) |
@@ -325,21 +371,34 @@ static inline void free_part_stats(struct hd_struct *part) | |||
325 | 371 | ||
326 | static inline void part_inc_in_flight(struct hd_struct *part, int rw) | 372 | static inline void part_inc_in_flight(struct hd_struct *part, int rw) |
327 | { | 373 | { |
328 | part->in_flight[rw]++; | 374 | atomic_inc(&part->in_flight[rw]); |
329 | if (part->partno) | 375 | if (part->partno) |
330 | part_to_disk(part)->part0.in_flight[rw]++; | 376 | atomic_inc(&part_to_disk(part)->part0.in_flight[rw]); |
331 | } | 377 | } |
332 | 378 | ||
333 | static inline void part_dec_in_flight(struct hd_struct *part, int rw) | 379 | static inline void part_dec_in_flight(struct hd_struct *part, int rw) |
334 | { | 380 | { |
335 | part->in_flight[rw]--; | 381 | atomic_dec(&part->in_flight[rw]); |
336 | if (part->partno) | 382 | if (part->partno) |
337 | part_to_disk(part)->part0.in_flight[rw]--; | 383 | atomic_dec(&part_to_disk(part)->part0.in_flight[rw]); |
338 | } | 384 | } |
339 | 385 | ||
340 | static inline int part_in_flight(struct hd_struct *part) | 386 | static inline int part_in_flight(struct hd_struct *part) |
341 | { | 387 | { |
342 | return part->in_flight[0] + part->in_flight[1]; | 388 | return atomic_read(&part->in_flight[0]) + atomic_read(&part->in_flight[1]); |
389 | } | ||
390 | |||
391 | static inline struct partition_meta_info *alloc_part_info(struct gendisk *disk) | ||
392 | { | ||
393 | if (disk) | ||
394 | return kzalloc_node(sizeof(struct partition_meta_info), | ||
395 | GFP_KERNEL, disk->node_id); | ||
396 | return kzalloc(sizeof(struct partition_meta_info), GFP_KERNEL); | ||
397 | } | ||
398 | |||
399 | static inline void free_part_info(struct hd_struct *part) | ||
400 | { | ||
401 | kfree(part->info); | ||
343 | } | 402 | } |
344 | 403 | ||
345 | /* block/blk-core.c */ | 404 | /* block/blk-core.c */ |
@@ -348,7 +407,6 @@ extern void part_round_stats(int cpu, struct hd_struct *part); | |||
348 | /* block/genhd.c */ | 407 | /* block/genhd.c */ |
349 | extern void add_disk(struct gendisk *disk); | 408 | extern void add_disk(struct gendisk *disk); |
350 | extern void del_gendisk(struct gendisk *gp); | 409 | extern void del_gendisk(struct gendisk *gp); |
351 | extern void unlink_gendisk(struct gendisk *gp); | ||
352 | extern struct gendisk *get_gendisk(dev_t dev, int *partno); | 410 | extern struct gendisk *get_gendisk(dev_t dev, int *partno); |
353 | extern struct block_device *bdget_disk(struct gendisk *disk, int partno); | 411 | extern struct block_device *bdget_disk(struct gendisk *disk, int partno); |
354 | 412 | ||
@@ -360,6 +418,11 @@ static inline int get_disk_ro(struct gendisk *disk) | |||
360 | return disk->part0.policy; | 418 | return disk->part0.policy; |
361 | } | 419 | } |
362 | 420 | ||
421 | extern void disk_block_events(struct gendisk *disk); | ||
422 | extern void disk_unblock_events(struct gendisk *disk); | ||
423 | extern void disk_check_events(struct gendisk *disk); | ||
424 | extern unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask); | ||
425 | |||
363 | /* drivers/char/random.c */ | 426 | /* drivers/char/random.c */ |
364 | extern void add_disk_randomness(struct gendisk *disk); | 427 | extern void add_disk_randomness(struct gendisk *disk); |
365 | extern void rand_initialize_disk(struct gendisk *disk); | 428 | extern void rand_initialize_disk(struct gendisk *disk); |
@@ -533,7 +596,10 @@ extern int disk_expand_part_tbl(struct gendisk *disk, int target); | |||
533 | extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); | 596 | extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); |
534 | extern struct hd_struct * __must_check add_partition(struct gendisk *disk, | 597 | extern struct hd_struct * __must_check add_partition(struct gendisk *disk, |
535 | int partno, sector_t start, | 598 | int partno, sector_t start, |
536 | sector_t len, int flags); | 599 | sector_t len, int flags, |
600 | struct partition_meta_info | ||
601 | *info); | ||
602 | extern void __delete_partition(struct hd_struct *); | ||
537 | extern void delete_partition(struct gendisk *, int); | 603 | extern void delete_partition(struct gendisk *, int); |
538 | extern void printk_all_partitions(void); | 604 | extern void printk_all_partitions(void); |
539 | 605 | ||
@@ -562,6 +628,29 @@ extern ssize_t part_fail_store(struct device *dev, | |||
562 | const char *buf, size_t count); | 628 | const char *buf, size_t count); |
563 | #endif /* CONFIG_FAIL_MAKE_REQUEST */ | 629 | #endif /* CONFIG_FAIL_MAKE_REQUEST */ |
564 | 630 | ||
631 | static inline void hd_ref_init(struct hd_struct *part) | ||
632 | { | ||
633 | atomic_set(&part->ref, 1); | ||
634 | smp_mb(); | ||
635 | } | ||
636 | |||
637 | static inline void hd_struct_get(struct hd_struct *part) | ||
638 | { | ||
639 | atomic_inc(&part->ref); | ||
640 | smp_mb__after_atomic_inc(); | ||
641 | } | ||
642 | |||
643 | static inline int hd_struct_try_get(struct hd_struct *part) | ||
644 | { | ||
645 | return atomic_inc_not_zero(&part->ref); | ||
646 | } | ||
647 | |||
648 | static inline void hd_struct_put(struct hd_struct *part) | ||
649 | { | ||
650 | if (atomic_dec_and_test(&part->ref)) | ||
651 | __delete_partition(part); | ||
652 | } | ||
653 | |||
565 | #else /* CONFIG_BLOCK */ | 654 | #else /* CONFIG_BLOCK */ |
566 | 655 | ||
567 | static inline void printk_all_partitions(void) { } | 656 | static inline void printk_all_partitions(void) { } |