]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
1da177e4 LT |
2 | #ifndef _LINUX_GENHD_H |
3 | #define _LINUX_GENHD_H | |
4 | ||
5 | /* | |
6 | * genhd.h Copyright (C) 1992 Drew Eckhardt | |
7 | * Generic hard disk header file by | |
8 | * Drew Eckhardt | |
9 | * | |
10 | * <drew@colorado.edu> | |
11 | */ | |
12 | ||
1da177e4 | 13 | #include <linux/types.h> |
edfaa7c3 | 14 | #include <linux/kdev_t.h> |
e71bf0d0 | 15 | #include <linux/rcupdate.h> |
6d1d8050 | 16 | #include <linux/slab.h> |
6c71013e | 17 | #include <linux/percpu-refcount.h> |
63579785 | 18 | #include <linux/uuid.h> |
dbae2c55 | 19 | #include <linux/blk_types.h> |
1226b8dd | 20 | #include <asm/local.h> |
1da177e4 | 21 | |
9361401e DH |
22 | #ifdef CONFIG_BLOCK |
23 | ||
548b10eb | 24 | #define dev_to_disk(device) container_of((device), struct gendisk, part0.__dev) |
ed9e1982 | 25 | #define dev_to_part(device) container_of((device), struct hd_struct, __dev) |
548b10eb | 26 | #define disk_to_dev(disk) (&(disk)->part0.__dev) |
ed9e1982 | 27 | #define part_to_dev(part) (&((part)->__dev)) |
edfaa7c3 | 28 | |
edfaa7c3 | 29 | extern struct device_type part_type; |
edfaa7c3 KS |
30 | extern struct class block_class; |
31 | ||
689d6fac | 32 | #define DISK_MAX_PARTS 256 |
3e1a7ff8 | 33 | #define DISK_NAME_LEN 32 |
689d6fac | 34 | |
34186efc DW |
35 | #include <linux/major.h> |
36 | #include <linux/device.h> | |
37 | #include <linux/smp.h> | |
38 | #include <linux/string.h> | |
39 | #include <linux/fs.h> | |
8ce7ad7b | 40 | #include <linux/workqueue.h> |
34186efc | 41 | |
ea5c48ab | 42 | struct disk_stats { |
b57e99b4 | 43 | u64 nsecs[NR_STAT_GROUPS]; |
dbae2c55 MC |
44 | unsigned long sectors[NR_STAT_GROUPS]; |
45 | unsigned long ios[NR_STAT_GROUPS]; | |
46 | unsigned long merges[NR_STAT_GROUPS]; | |
ea5c48ab | 47 | unsigned long io_ticks; |
1226b8dd | 48 | local_t in_flight[2]; |
ea5c48ab | 49 | }; |
6d1d8050 WD |
50 | |
51 | #define PARTITION_META_INFO_VOLNAMELTH 64 | |
1ad7e899 SW |
52 | /* |
53 | * Enough for the string representation of any kind of UUID plus NULL. | |
54 | * EFI UUID is 36 characters. MSDOS UUID is 11 characters. | |
55 | */ | |
63579785 | 56 | #define PARTITION_META_INFO_UUIDLTH (UUID_STRING_LEN + 1) |
6d1d8050 WD |
57 | |
58 | struct partition_meta_info { | |
1ad7e899 | 59 | char uuid[PARTITION_META_INFO_UUIDLTH]; |
6d1d8050 WD |
60 | u8 volname[PARTITION_META_INFO_VOLNAMELTH]; |
61 | }; | |
62 | ||
1da177e4 LT |
63 | struct hd_struct { |
64 | sector_t start_sect; | |
c83f6bf9 VG |
65 | /* |
66 | * nr_sects is protected by sequence counter. One might extend a | |
67 | * partition while IO is happening to it and update of nr_sects | |
68 | * can be non-atomic on 32bit machines with 64bit sector_t. | |
69 | */ | |
1da177e4 | 70 | sector_t nr_sects; |
c83f6bf9 | 71 | seqcount_t nr_sects_seq; |
c72758f3 | 72 | sector_t alignment_offset; |
a1706ac4 | 73 | unsigned int discard_alignment; |
ed9e1982 | 74 | struct device __dev; |
6a4d44c1 | 75 | struct kobject *holder_dir; |
1da177e4 | 76 | int policy, partno; |
6d1d8050 | 77 | struct partition_meta_info *info; |
c17bb495 AM |
78 | #ifdef CONFIG_FAIL_MAKE_REQUEST |
79 | int make_it_fail; | |
ea5c48ab JM |
80 | #endif |
81 | unsigned long stamp; | |
ea5c48ab | 82 | #ifdef CONFIG_SMP |
43cf38eb | 83 | struct disk_stats __percpu *dkstats; |
ea5c48ab JM |
84 | #else |
85 | struct disk_stats dkstats; | |
c17bb495 | 86 | #endif |
6c71013e | 87 | struct percpu_ref ref; |
94a2c3a3 | 88 | struct rcu_work rcu_work; |
1da177e4 LT |
89 | }; |
90 | ||
9243c6f3 SK |
91 | /** |
92 | * DOC: genhd capability flags | |
93 | * | |
94 | * ``GENHD_FL_REMOVABLE`` (0x0001): indicates that the block device | |
95 | * gives access to removable media. | |
96 | * When set, the device remains present even when media is not | |
97 | * inserted. | |
98 | * Must not be set for devices which are removed entirely when the | |
99 | * media is removed. | |
100 | * | |
101 | * ``GENHD_FL_CD`` (0x0008): the block device is a CD-ROM-style | |
102 | * device. | |
103 | * Affects responses to the ``CDROM_GET_CAPABILITY`` ioctl. | |
104 | * | |
105 | * ``GENHD_FL_UP`` (0x0010): indicates that the block device is "up", | |
106 | * with a similar meaning to network interfaces. | |
107 | * | |
108 | * ``GENHD_FL_SUPPRESS_PARTITION_INFO`` (0x0020): don't include | |
109 | * partition information in ``/proc/partitions`` or in the output of | |
110 | * printk_all_partitions(). | |
111 | * Used for the null block device and some MMC devices. | |
112 | * | |
113 | * ``GENHD_FL_EXT_DEVT`` (0x0040): the driver supports extended | |
114 | * dynamic ``dev_t``, i.e. it wants extended device numbers | |
115 | * (``BLOCK_EXT_MAJOR``). | |
116 | * This affects the maximum number of partitions. | |
117 | * | |
118 | * ``GENHD_FL_NATIVE_CAPACITY`` (0x0080): based on information in the | |
119 | * partition table, the device's capacity has been extended to its | |
120 | * native capacity; i.e. the device has hidden capacity used by one | |
121 | * of the partitions (this is a flag used so that native capacity is | |
122 | * only ever unlocked once). | |
123 | * | |
124 | * ``GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE`` (0x0100): event polling is | |
125 | * blocked whenever a writer holds an exclusive lock. | |
126 | * | |
127 | * ``GENHD_FL_NO_PART_SCAN`` (0x0200): partition scanning is disabled. | |
128 | * Used for loop devices in their default settings and some MMC | |
129 | * devices. | |
130 | * | |
131 | * ``GENHD_FL_HIDDEN`` (0x0400): the block device is hidden; it | |
132 | * doesn't produce events, doesn't appear in sysfs, and doesn't have | |
133 | * an associated ``bdev``. | |
134 | * Implies ``GENHD_FL_SUPPRESS_PARTITION_INFO`` and | |
135 | * ``GENHD_FL_NO_PART_SCAN``. | |
136 | * Used for multipath devices. | |
137 | */ | |
138 | #define GENHD_FL_REMOVABLE 0x0001 | |
139 | /* 2 is unused (used to be GENHD_FL_DRIVERFS) */ | |
140 | /* 4 is unused (used to be GENHD_FL_MEDIA_CHANGE_NOTIFY) */ | |
141 | #define GENHD_FL_CD 0x0008 | |
142 | #define GENHD_FL_UP 0x0010 | |
143 | #define GENHD_FL_SUPPRESS_PARTITION_INFO 0x0020 | |
144 | #define GENHD_FL_EXT_DEVT 0x0040 | |
145 | #define GENHD_FL_NATIVE_CAPACITY 0x0080 | |
146 | #define GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE 0x0100 | |
147 | #define GENHD_FL_NO_PART_SCAN 0x0200 | |
148 | #define GENHD_FL_HIDDEN 0x0400 | |
1da177e4 | 149 | |
77ea887e TH |
150 | enum { |
151 | DISK_EVENT_MEDIA_CHANGE = 1 << 0, /* media changed */ | |
152 | DISK_EVENT_EJECT_REQUEST = 1 << 1, /* eject requested */ | |
153 | }; | |
154 | ||
c92e2f04 MW |
155 | enum { |
156 | /* Poll even if events_poll_msecs is unset */ | |
157 | DISK_EVENT_FLAG_POLL = 1 << 0, | |
158 | /* Forward events to udev */ | |
159 | DISK_EVENT_FLAG_UEVENT = 1 << 1, | |
160 | }; | |
161 | ||
540eed56 TH |
162 | struct disk_part_tbl { |
163 | struct rcu_head rcu_head; | |
164 | int len; | |
4d2deb40 AB |
165 | struct hd_struct __rcu *last_lookup; |
166 | struct hd_struct __rcu *part[]; | |
540eed56 TH |
167 | }; |
168 | ||
77ea887e | 169 | struct disk_events; |
99e6608c | 170 | struct badblocks; |
77ea887e | 171 | |
25520d55 MP |
172 | #if defined(CONFIG_BLK_DEV_INTEGRITY) |
173 | ||
174 | struct blk_integrity { | |
869ab90f EB |
175 | const struct blk_integrity_profile *profile; |
176 | unsigned char flags; | |
177 | unsigned char tuple_size; | |
178 | unsigned char interval_exp; | |
179 | unsigned char tag_size; | |
25520d55 MP |
180 | }; |
181 | ||
182 | #endif /* CONFIG_BLK_DEV_INTEGRITY */ | |
183 | ||
1da177e4 | 184 | struct gendisk { |
689d6fac TH |
185 | /* major, first_minor and minors are input parameters only, |
186 | * don't use directly. Use disk_devt() and disk_max_parts(). | |
f331c029 | 187 | */ |
1da177e4 LT |
188 | int major; /* major number of driver */ |
189 | int first_minor; | |
190 | int minors; /* maximum number of minors, =1 for | |
191 | * disks that can't be partitioned. */ | |
f331c029 | 192 | |
3e1a7ff8 | 193 | char disk_name[DISK_NAME_LEN]; /* name of major driver */ |
77ea887e | 194 | |
c92e2f04 MW |
195 | unsigned short events; /* supported events */ |
196 | unsigned short event_flags; /* flags related to event processing */ | |
77ea887e | 197 | |
b5d0b9df | 198 | /* Array of pointers to partitions indexed by partno. |
e71bf0d0 TH |
199 | * Protected with matching bdev lock but stat and other |
200 | * non-critical accesses use RCU. Always access through | |
201 | * helpers. | |
202 | */ | |
4d2deb40 | 203 | struct disk_part_tbl __rcu *part_tbl; |
b5d0b9df | 204 | struct hd_struct part0; |
e71bf0d0 | 205 | |
83d5cde4 | 206 | const struct block_device_operations *fops; |
1da177e4 LT |
207 | struct request_queue *queue; |
208 | void *private_data; | |
1da177e4 LT |
209 | |
210 | int flags; | |
56c0908c | 211 | struct rw_semaphore lookup_sem; |
6a4d44c1 | 212 | struct kobject *slave_dir; |
1da177e4 LT |
213 | |
214 | struct timer_rand_state *random; | |
1da177e4 | 215 | atomic_t sync_io; /* RAID */ |
77ea887e | 216 | struct disk_events *ev; |
7ba1ba12 | 217 | #ifdef CONFIG_BLK_DEV_INTEGRITY |
aff34e19 | 218 | struct kobject integrity_kobj; |
25520d55 | 219 | #endif /* CONFIG_BLK_DEV_INTEGRITY */ |
540eed56 | 220 | int node_id; |
99e6608c | 221 | struct badblocks *bb; |
e319e1fb | 222 | struct lockdep_map lockdep_map; |
1da177e4 LT |
223 | }; |
224 | ||
310a2c10 TH |
225 | static inline struct gendisk *part_to_disk(struct hd_struct *part) |
226 | { | |
548b10eb TH |
227 | if (likely(part)) { |
228 | if (part->partno) | |
229 | return dev_to_disk(part_to_dev(part)->parent); | |
230 | else | |
231 | return dev_to_disk(part_to_dev(part)); | |
232 | } | |
310a2c10 TH |
233 | return NULL; |
234 | } | |
235 | ||
f331c029 TH |
236 | static inline int disk_max_parts(struct gendisk *disk) |
237 | { | |
689d6fac TH |
238 | if (disk->flags & GENHD_FL_EXT_DEVT) |
239 | return DISK_MAX_PARTS; | |
240 | return disk->minors; | |
b5d0b9df TH |
241 | } |
242 | ||
d27769ec | 243 | static inline bool disk_part_scan_enabled(struct gendisk *disk) |
b5d0b9df | 244 | { |
d27769ec TH |
245 | return disk_max_parts(disk) > 1 && |
246 | !(disk->flags & GENHD_FL_NO_PART_SCAN); | |
f331c029 TH |
247 | } |
248 | ||
249 | static inline dev_t disk_devt(struct gendisk *disk) | |
250 | { | |
517bf3c3 | 251 | return MKDEV(disk->major, disk->first_minor); |
f331c029 TH |
252 | } |
253 | ||
254 | static inline dev_t part_devt(struct hd_struct *part) | |
255 | { | |
ed9e1982 | 256 | return part_to_dev(part)->devt; |
f331c029 TH |
257 | } |
258 | ||
67f2519f | 259 | extern struct hd_struct *__disk_get_part(struct gendisk *disk, int partno); |
e71bf0d0 TH |
260 | extern struct hd_struct *disk_get_part(struct gendisk *disk, int partno); |
261 | ||
262 | static inline void disk_put_part(struct hd_struct *part) | |
263 | { | |
264 | if (likely(part)) | |
ed9e1982 | 265 | put_device(part_to_dev(part)); |
e71bf0d0 TH |
266 | } |
267 | ||
268 | /* | |
269 | * Smarter partition iterator without context limits. | |
270 | */ | |
271 | #define DISK_PITER_REVERSE (1 << 0) /* iterate in the reverse direction */ | |
272 | #define DISK_PITER_INCL_EMPTY (1 << 1) /* include 0-sized parts */ | |
b5d0b9df | 273 | #define DISK_PITER_INCL_PART0 (1 << 2) /* include partition 0 */ |
71982a40 | 274 | #define DISK_PITER_INCL_EMPTY_PART0 (1 << 3) /* include empty partition 0 */ |
e71bf0d0 TH |
275 | |
276 | struct disk_part_iter { | |
277 | struct gendisk *disk; | |
278 | struct hd_struct *part; | |
279 | int idx; | |
280 | unsigned int flags; | |
281 | }; | |
282 | ||
283 | extern void disk_part_iter_init(struct disk_part_iter *piter, | |
284 | struct gendisk *disk, unsigned int flags); | |
285 | extern struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter); | |
286 | extern void disk_part_iter_exit(struct disk_part_iter *piter); | |
10f36b1e | 287 | extern bool disk_has_partitions(struct gendisk *disk); |
1da177e4 | 288 | |
32ca163c | 289 | /* block/genhd.c */ |
fef912bf HR |
290 | extern void device_add_disk(struct device *parent, struct gendisk *disk, |
291 | const struct attribute_group **groups); | |
e63a46be DW |
292 | static inline void add_disk(struct gendisk *disk) |
293 | { | |
fef912bf | 294 | device_add_disk(NULL, disk, NULL); |
e63a46be | 295 | } |
fa70d2e2 MS |
296 | extern void device_add_disk_no_queue_reg(struct device *parent, struct gendisk *disk); |
297 | static inline void add_disk_no_queue_reg(struct gendisk *disk) | |
298 | { | |
299 | device_add_disk_no_queue_reg(NULL, disk); | |
300 | } | |
e63a46be | 301 | |
1da177e4 | 302 | extern void del_gendisk(struct gendisk *gp); |
cf771cb5 | 303 | extern struct gendisk *get_gendisk(dev_t dev, int *partno); |
f331c029 | 304 | extern struct block_device *bdget_disk(struct gendisk *disk, int partno); |
1da177e4 LT |
305 | |
306 | extern void set_device_ro(struct block_device *bdev, int flag); | |
307 | extern void set_disk_ro(struct gendisk *disk, int flag); | |
308 | ||
b7db9956 TH |
309 | static inline int get_disk_ro(struct gendisk *disk) |
310 | { | |
311 | return disk->part0.policy; | |
312 | } | |
313 | ||
77ea887e TH |
314 | extern void disk_block_events(struct gendisk *disk); |
315 | extern void disk_unblock_events(struct gendisk *disk); | |
85ef06d1 | 316 | extern void disk_flush_events(struct gendisk *disk, unsigned int mask); |
e598a72f BS |
317 | extern void set_capacity_revalidate_and_notify(struct gendisk *disk, |
318 | sector_t size, bool revalidate); | |
77ea887e TH |
319 | extern unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask); |
320 | ||
1da177e4 | 321 | /* drivers/char/random.c */ |
0766f788 | 322 | extern void add_disk_randomness(struct gendisk *disk) __latent_entropy; |
1da177e4 LT |
323 | extern void rand_initialize_disk(struct gendisk *disk); |
324 | ||
325 | static inline sector_t get_start_sect(struct block_device *bdev) | |
326 | { | |
0762b8bd | 327 | return bdev->bd_part->start_sect; |
1da177e4 LT |
328 | } |
329 | static inline sector_t get_capacity(struct gendisk *disk) | |
330 | { | |
80795aef | 331 | return disk->part0.nr_sects; |
1da177e4 LT |
332 | } |
333 | static inline void set_capacity(struct gendisk *disk, sector_t size) | |
334 | { | |
80795aef | 335 | disk->part0.nr_sects = size; |
1da177e4 LT |
336 | } |
337 | ||
cf771cb5 | 338 | extern dev_t blk_lookup_devt(const char *name, int partno); |
1da177e4 | 339 | |
142fe8f4 | 340 | int bdev_disk_changed(struct block_device *bdev, bool invalidate); |
a1548b67 CH |
341 | int blk_add_partitions(struct gendisk *disk, struct block_device *bdev); |
342 | int blk_drop_partitions(struct gendisk *disk, struct block_device *bdev); | |
dd2a345f | 343 | extern void printk_all_partitions(void); |
1da177e4 | 344 | |
e319e1fb | 345 | extern struct gendisk *__alloc_disk_node(int minors, int node_id); |
3079c22e | 346 | extern struct kobject *get_disk_and_module(struct gendisk *disk); |
1da177e4 | 347 | extern void put_disk(struct gendisk *disk); |
9df6c299 | 348 | extern void put_disk_and_module(struct gendisk *disk); |
edfaa7c3 | 349 | extern void blk_register_region(dev_t devt, unsigned long range, |
1da177e4 LT |
350 | struct module *module, |
351 | struct kobject *(*probe)(dev_t, int *, void *), | |
352 | int (*lock)(dev_t, void *), | |
353 | void *data); | |
edfaa7c3 | 354 | extern void blk_unregister_region(dev_t devt, unsigned long range); |
1da177e4 | 355 | |
e319e1fb BP |
356 | #define alloc_disk_node(minors, node_id) \ |
357 | ({ \ | |
358 | static struct lock_class_key __key; \ | |
359 | const char *__name; \ | |
360 | struct gendisk *__disk; \ | |
361 | \ | |
362 | __name = "(gendisk_completion)"#minors"("#node_id")"; \ | |
363 | \ | |
364 | __disk = __alloc_disk_node(minors, node_id); \ | |
365 | \ | |
366 | if (__disk) \ | |
367 | lockdep_init_map(&__disk->lockdep_map, __name, &__key, 0); \ | |
368 | \ | |
369 | __disk; \ | |
370 | }) | |
371 | ||
372 | #define alloc_disk(minors) alloc_disk_node(minors, NUMA_NO_NODE) | |
373 | ||
87c1efbf JA |
374 | #else /* CONFIG_BLOCK */ |
375 | ||
376 | static inline void printk_all_partitions(void) { } | |
377 | ||
cf771cb5 | 378 | static inline dev_t blk_lookup_devt(const char *name, int partno) |
edfaa7c3 KS |
379 | { |
380 | dev_t devt = MKDEV(0, 0); | |
381 | return devt; | |
382 | } | |
87c1efbf | 383 | #endif /* CONFIG_BLOCK */ |
9361401e | 384 | |
a8ae50ba | 385 | #endif /* _LINUX_GENHD_H */ |