genhd.h 24.2 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
Linus Torvalds's avatar
Linus Torvalds committed
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef _LINUX_GENHD_H
#define _LINUX_GENHD_H

/*
 * 	genhd.h Copyright (C) 1992 Drew Eckhardt
 *	Generic hard disk header file by  
 * 		Drew Eckhardt
 *
 *		<drew@colorado.edu>
 */

#include <linux/types.h>
14
#include <linux/kdev_t.h>
15
#include <linux/rcupdate.h>
16
#include <linux/slab.h>
17
#include <linux/percpu-refcount.h>
18
#include <linux/uuid.h>
19
#include <linux/blk_types.h>
20
#include <asm/local.h>
Linus Torvalds's avatar
Linus Torvalds committed
21

22
23
#ifdef CONFIG_BLOCK

24
#define dev_to_disk(device)	container_of((device), struct gendisk, part0.__dev)
25
#define dev_to_part(device)	container_of((device), struct hd_struct, __dev)
26
#define disk_to_dev(disk)	(&(disk)->part0.__dev)
27
#define part_to_dev(part)	(&((part)->__dev))
28
29
30
31
32

extern struct device_type part_type;
extern struct kobject *block_depr;
extern struct class block_class;

Linus Torvalds's avatar
Linus Torvalds committed
33
34
35
36
37
38
39
enum {
/* These three have identical behaviour; use the second one if DOS FDISK gets
   confused about extended/logical partitions starting past cylinder 1023. */
	DOS_EXTENDED_PARTITION = 5,
	LINUX_EXTENDED_PARTITION = 0x85,
	WIN98_EXTENDED_PARTITION = 0x0f,

40
41
	SUN_WHOLE_DISK = DOS_EXTENDED_PARTITION,

Linus Torvalds's avatar
Linus Torvalds committed
42
	LINUX_SWAP_PARTITION = 0x82,
43
44
	LINUX_DATA_PARTITION = 0x83,
	LINUX_LVM_PARTITION = 0x8e,
Linus Torvalds's avatar
Linus Torvalds committed
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
	LINUX_RAID_PARTITION = 0xfd,	/* autodetect RAID partition */

	SOLARIS_X86_PARTITION =	LINUX_SWAP_PARTITION,
	NEW_SOLARIS_X86_PARTITION = 0xbf,

	DM6_AUX1PARTITION = 0x51,	/* no DDO:  use xlated geom */
	DM6_AUX3PARTITION = 0x53,	/* no DDO:  use xlated geom */
	DM6_PARTITION =	0x54,		/* has DDO: use xlated geom & offset */
	EZD_PARTITION =	0x55,		/* EZ-DRIVE */

	FREEBSD_PARTITION = 0xa5,	/* FreeBSD Partition ID */
	OPENBSD_PARTITION = 0xa6,	/* OpenBSD Partition ID */
	NETBSD_PARTITION = 0xa9,	/* NetBSD Partition ID */
	BSDI_PARTITION = 0xb7,		/* BSDI Partition ID */
	MINIX_PARTITION = 0x81,		/* Minix Partition ID */
	UNIXWARE_PARTITION = 0x63,	/* Same as GNU_HURD and SCO Unix */
};

63
#define DISK_MAX_PARTS			256
64
#define DISK_NAME_LEN			32
65

66
67
68
69
70
#include <linux/major.h>
#include <linux/device.h>
#include <linux/smp.h>
#include <linux/string.h>
#include <linux/fs.h>
71
#include <linux/workqueue.h>
72

Linus Torvalds's avatar
Linus Torvalds committed
73
74
75
76
77
78
79
80
81
82
83
84
85
struct partition {
	unsigned char boot_ind;		/* 0x80 - active */
	unsigned char head;		/* starting head */
	unsigned char sector;		/* starting sector */
	unsigned char cyl;		/* starting cylinder */
	unsigned char sys_ind;		/* What partition type */
	unsigned char end_head;		/* end head */
	unsigned char end_sector;	/* end sector */
	unsigned char end_cyl;		/* end cylinder */
	__le32 start_sect;	/* starting sector counting from 0 */
	__le32 nr_sects;		/* nr of sectors in partition */
} __attribute__((packed));

86
struct disk_stats {
87
	u64 nsecs[NR_STAT_GROUPS];
88
89
90
	unsigned long sectors[NR_STAT_GROUPS];
	unsigned long ios[NR_STAT_GROUPS];
	unsigned long merges[NR_STAT_GROUPS];
91
92
	unsigned long io_ticks;
	unsigned long time_in_queue;
93
	local_t in_flight[2];
94
};
95
96

#define PARTITION_META_INFO_VOLNAMELTH	64
97
98
99
100
/*
 * Enough for the string representation of any kind of UUID plus NULL.
 * EFI UUID is 36 characters. MSDOS UUID is 11 characters.
 */
101
#define PARTITION_META_INFO_UUIDLTH	(UUID_STRING_LEN + 1)
102
103

struct partition_meta_info {
104
	char uuid[PARTITION_META_INFO_UUIDLTH];
105
106
107
	u8 volname[PARTITION_META_INFO_VOLNAMELTH];
};

Linus Torvalds's avatar
Linus Torvalds committed
108
109
struct hd_struct {
	sector_t start_sect;
110
111
112
113
114
	/*
	 * nr_sects is protected by sequence counter. One might extend a
	 * partition while IO is happening to it and update of nr_sects
	 * can be non-atomic on 32bit machines with 64bit sector_t.
	 */
Linus Torvalds's avatar
Linus Torvalds committed
115
	sector_t nr_sects;
116
	seqcount_t nr_sects_seq;
117
	sector_t alignment_offset;
118
	unsigned int discard_alignment;
119
	struct device __dev;
120
	struct kobject *holder_dir;
Linus Torvalds's avatar
Linus Torvalds committed
121
	int policy, partno;
122
	struct partition_meta_info *info;
123
124
#ifdef CONFIG_FAIL_MAKE_REQUEST
	int make_it_fail;
125
126
127
#endif
	unsigned long stamp;
#ifdef	CONFIG_SMP
128
	struct disk_stats __percpu *dkstats;
129
130
#else
	struct disk_stats dkstats;
131
#endif
132
	struct percpu_ref ref;
133
	struct rcu_work rcu_work;
Linus Torvalds's avatar
Linus Torvalds committed
134
135
136
};

#define GENHD_FL_REMOVABLE			1
NeilBrown's avatar
NeilBrown committed
137
/* 2 is unused */
138
#define GENHD_FL_MEDIA_CHANGE_NOTIFY		4
Linus Torvalds's avatar
Linus Torvalds committed
139
140
141
#define GENHD_FL_CD				8
#define GENHD_FL_UP				16
#define GENHD_FL_SUPPRESS_PARTITION_INFO	32
142
#define GENHD_FL_EXT_DEVT			64 /* allow extended devt */
143
#define GENHD_FL_NATIVE_CAPACITY		128
144
#define GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE	256
Tejun Heo's avatar
Tejun Heo committed
145
#define GENHD_FL_NO_PART_SCAN			512
146
#define GENHD_FL_HIDDEN				1024
Linus Torvalds's avatar
Linus Torvalds committed
147

148
149
150
151
152
enum {
	DISK_EVENT_MEDIA_CHANGE			= 1 << 0, /* media changed */
	DISK_EVENT_EJECT_REQUEST		= 1 << 1, /* eject requested */
};

153
154
155
156
157
158
159
enum {
	/* Poll even if events_poll_msecs is unset */
	DISK_EVENT_FLAG_POLL			= 1 << 0,
	/* Forward events to udev */
	DISK_EVENT_FLAG_UEVENT			= 1 << 1,
};

160
161
162
struct disk_part_tbl {
	struct rcu_head rcu_head;
	int len;
Arnd Bergmann's avatar
Arnd Bergmann committed
163
164
	struct hd_struct __rcu *last_lookup;
	struct hd_struct __rcu *part[];
165
166
};

167
struct disk_events;
168
struct badblocks;
169

170
171
172
#if defined(CONFIG_BLK_DEV_INTEGRITY)

struct blk_integrity {
173
174
175
176
177
	const struct blk_integrity_profile	*profile;
	unsigned char				flags;
	unsigned char				tuple_size;
	unsigned char				interval_exp;
	unsigned char				tag_size;
178
179
180
181
};

#endif	/* CONFIG_BLK_DEV_INTEGRITY */

Linus Torvalds's avatar
Linus Torvalds committed
182
struct gendisk {
183
184
	/* major, first_minor and minors are input parameters only,
	 * don't use directly.  Use disk_devt() and disk_max_parts().
185
	 */
Linus Torvalds's avatar
Linus Torvalds committed
186
187
188
189
	int major;			/* major number of driver */
	int first_minor;
	int minors;                     /* maximum number of minors, =1 for
                                         * disks that can't be partitioned. */
190

191
	char disk_name[DISK_NAME_LEN];	/* name of major driver */
192
	char *(*devnode)(struct gendisk *gd, umode_t *mode);
193

194
195
	unsigned short events;		/* supported events */
	unsigned short event_flags;	/* flags related to event processing */
196

Tejun Heo's avatar
Tejun Heo committed
197
	/* Array of pointers to partitions indexed by partno.
198
199
200
201
	 * Protected with matching bdev lock but stat and other
	 * non-critical accesses use RCU.  Always access through
	 * helpers.
	 */
Arnd Bergmann's avatar
Arnd Bergmann committed
202
	struct disk_part_tbl __rcu *part_tbl;
Tejun Heo's avatar
Tejun Heo committed
203
	struct hd_struct part0;
204

205
	const struct block_device_operations *fops;
Linus Torvalds's avatar
Linus Torvalds committed
206
207
208
209
	struct request_queue *queue;
	void *private_data;

	int flags;
Jan Kara's avatar
Jan Kara committed
210
	struct rw_semaphore lookup_sem;
211
	struct kobject *slave_dir;
Linus Torvalds's avatar
Linus Torvalds committed
212
213
214

	struct timer_rand_state *random;
	atomic_t sync_io;		/* RAID */
215
	struct disk_events *ev;
216
#ifdef  CONFIG_BLK_DEV_INTEGRITY
217
	struct kobject integrity_kobj;
218
#endif	/* CONFIG_BLK_DEV_INTEGRITY */
219
	int node_id;
220
	struct badblocks *bb;
221
	struct lockdep_map lockdep_map;
Linus Torvalds's avatar
Linus Torvalds committed
222
223
};

Tejun Heo's avatar
Tejun Heo committed
224
225
static inline struct gendisk *part_to_disk(struct hd_struct *part)
{
226
227
228
229
230
231
	if (likely(part)) {
		if (part->partno)
			return dev_to_disk(part_to_dev(part)->parent);
		else
			return dev_to_disk(part_to_dev(part));
	}
Tejun Heo's avatar
Tejun Heo committed
232
233
234
	return NULL;
}

235
236
static inline int disk_max_parts(struct gendisk *disk)
{
237
238
239
	if (disk->flags & GENHD_FL_EXT_DEVT)
		return DISK_MAX_PARTS;
	return disk->minors;
Tejun Heo's avatar
Tejun Heo committed
240
241
}

Tejun Heo's avatar
Tejun Heo committed
242
static inline bool disk_part_scan_enabled(struct gendisk *disk)
Tejun Heo's avatar
Tejun Heo committed
243
{
Tejun Heo's avatar
Tejun Heo committed
244
245
	return disk_max_parts(disk) > 1 &&
		!(disk->flags & GENHD_FL_NO_PART_SCAN);
246
247
}

248
249
250
251
252
253
254
255
256
257
258
259
static inline bool disk_has_partitions(struct gendisk *disk)
{
	bool ret = false;

	rcu_read_lock();
	if (rcu_dereference(disk->part_tbl)->len > 1)
		ret = true;
	rcu_read_unlock();

	return ret;
}

260
261
static inline dev_t disk_devt(struct gendisk *disk)
{
262
	return MKDEV(disk->major, disk->first_minor);
263
264
265
266
}

static inline dev_t part_devt(struct hd_struct *part)
{
267
	return part_to_dev(part)->devt;
268
269
}

270
extern struct hd_struct *__disk_get_part(struct gendisk *disk, int partno);
271
272
273
274
275
extern struct hd_struct *disk_get_part(struct gendisk *disk, int partno);

static inline void disk_put_part(struct hd_struct *part)
{
	if (likely(part))
276
		put_device(part_to_dev(part));
277
278
279
280
281
282
283
}

/*
 * Smarter partition iterator without context limits.
 */
#define DISK_PITER_REVERSE	(1 << 0) /* iterate in the reverse direction */
#define DISK_PITER_INCL_EMPTY	(1 << 1) /* include 0-sized parts */
Tejun Heo's avatar
Tejun Heo committed
284
#define DISK_PITER_INCL_PART0	(1 << 2) /* include partition 0 */
285
#define DISK_PITER_INCL_EMPTY_PART0 (1 << 3) /* include empty partition 0 */
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301

struct disk_part_iter {
	struct gendisk		*disk;
	struct hd_struct	*part;
	int			idx;
	unsigned int		flags;
};

extern void disk_part_iter_init(struct disk_part_iter *piter,
				 struct gendisk *disk, unsigned int flags);
extern struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter);
extern void disk_part_iter_exit(struct disk_part_iter *piter);

extern struct hd_struct *disk_map_sector_rcu(struct gendisk *disk,
					     sector_t sector);

Tejun Heo's avatar
Tejun Heo committed
302
/*
Linus Torvalds's avatar
Linus Torvalds committed
303
304
 * Macros to operate on percpu disk statistics:
 *
Tejun Heo's avatar
Tejun Heo committed
305
306
307
308
309
310
311
312
 * {disk|part|all}_stat_{add|sub|inc|dec}() modify the stat counters
 * and should be called between disk_stat_lock() and
 * disk_stat_unlock().
 *
 * part_stat_read() can be called at any time.
 *
 * part_stat_{add|set_all}() and {init|free}_part_stats are for
 * internal use only.
Linus Torvalds's avatar
Linus Torvalds committed
313
314
 */
#ifdef	CONFIG_SMP
315
316
#define part_stat_lock()	({ rcu_read_lock(); get_cpu(); })
#define part_stat_unlock()	do { put_cpu(); rcu_read_unlock(); } while (0)
317

318
319
320
321
322
#define part_stat_get_cpu(part, field, cpu)					\
	(per_cpu_ptr((part)->dkstats, (cpu))->field)

#define part_stat_get(part, field)					\
	part_stat_get_cpu(part, field, smp_processor_id())
323
324
325

#define part_stat_read(part, field)					\
({									\
326
	typeof((part)->dkstats->field) res = 0;				\
327
328
329
	unsigned int _cpu;						\
	for_each_possible_cpu(_cpu)					\
		res += per_cpu_ptr((part)->dkstats, _cpu)->field;	\
330
331
332
	res;								\
})

333
334
static inline void part_stat_set_all(struct hd_struct *part, int value)
{
335
	int i;
336

337
338
	for_each_possible_cpu(i)
		memset(per_cpu_ptr(part->dkstats, i), value,
339
				sizeof(struct disk_stats));
340
}
Tejun Heo's avatar
Tejun Heo committed
341

342
static inline int init_part_stats(struct hd_struct *part)
343
{
344
345
346
347
	part->dkstats = alloc_percpu(struct disk_stats);
	if (!part->dkstats)
		return 0;
	return 1;
Linus Torvalds's avatar
Linus Torvalds committed
348
}
349

350
static inline void free_part_stats(struct hd_struct *part)
351
{
352
	free_percpu(part->dkstats);
353
354
}

355
356
357
#else /* !CONFIG_SMP */
#define part_stat_lock()	({ rcu_read_lock(); 0; })
#define part_stat_unlock()	rcu_read_unlock()
Tejun Heo's avatar
Tejun Heo committed
358

359
360
361
#define part_stat_get(part, field)		((part)->dkstats.field)
#define part_stat_get_cpu(part, field, cpu)	part_stat_get(part, field)
#define part_stat_read(part, field)		part_stat_get(part, field)
Linus Torvalds's avatar
Linus Torvalds committed
362

363
static inline void part_stat_set_all(struct hd_struct *part, int value)
Linus Torvalds's avatar
Linus Torvalds committed
364
{
365
	memset(&part->dkstats, value, sizeof(struct disk_stats));
Linus Torvalds's avatar
Linus Torvalds committed
366
}
367
368
369
370
371
372
373
374
375
376

static inline int init_part_stats(struct hd_struct *part)
{
	return 1;
}

static inline void free_part_stats(struct hd_struct *part)
{
}

377
#endif /* CONFIG_SMP */
Linus Torvalds's avatar
Linus Torvalds committed
378

379
380
381
#define part_stat_read_msecs(part, which)				\
	div_u64(part_stat_read(part, nsecs[which]), NSEC_PER_MSEC)

382
#define part_stat_read_accum(part, field)				\
383
	(part_stat_read(part, field[STAT_READ]) +			\
384
385
	 part_stat_read(part, field[STAT_WRITE]) +			\
	 part_stat_read(part, field[STAT_DISCARD]))
386

387
388
389
#define __part_stat_add(part, field, addnd)				\
	(part_stat_get(part, field) += (addnd))

390
391
#define part_stat_add(part, field, addnd)	do {			\
	__part_stat_add((part), field, addnd);				\
392
	if ((part)->partno)						\
393
		__part_stat_add(&part_to_disk((part))->part0,		\
394
395
				field, addnd);				\
} while (0)
396

397
398
399
400
401
402
#define part_stat_dec(gendiskp, field)					\
	part_stat_add(gendiskp, field, -1)
#define part_stat_inc(gendiskp, field)					\
	part_stat_add(gendiskp, field, 1)
#define part_stat_sub(gendiskp, field, subnd)				\
	part_stat_add(gendiskp, field, -subnd)
403

404
405
406
407
408
409
410
411
412
#define part_stat_local_dec(gendiskp, field)				\
	local_dec(&(part_stat_get(gendiskp, field)))
#define part_stat_local_inc(gendiskp, field)				\
	local_inc(&(part_stat_get(gendiskp, field)))
#define part_stat_local_read(gendiskp, field)				\
	local_read(&(part_stat_get(gendiskp, field)))
#define part_stat_local_read_cpu(gendiskp, field, cpu)			\
	local_read(&(part_stat_get_cpu(gendiskp, field, cpu)))

413
unsigned int part_in_flight(struct request_queue *q, struct hd_struct *part);
414
415
void part_in_flight_rw(struct request_queue *q, struct hd_struct *part,
		       unsigned int inflight[2]);
416
417
418
419
void part_dec_in_flight(struct request_queue *q, struct hd_struct *part,
			int rw);
void part_inc_in_flight(struct request_queue *q, struct hd_struct *part,
			int rw);
Linus Torvalds's avatar
Linus Torvalds committed
420

421
422
423
424
425
426
427
428
429
430
431
432
433
static inline struct partition_meta_info *alloc_part_info(struct gendisk *disk)
{
	if (disk)
		return kzalloc_node(sizeof(struct partition_meta_info),
				    GFP_KERNEL, disk->node_id);
	return kzalloc(sizeof(struct partition_meta_info), GFP_KERNEL);
}

static inline void free_part_info(struct hd_struct *part)
{
	kfree(part->info);
}

434
void update_io_ticks(struct hd_struct *part, unsigned long now);
Linus Torvalds's avatar
Linus Torvalds committed
435

436
/* block/genhd.c */
437
438
extern void device_add_disk(struct device *parent, struct gendisk *disk,
			    const struct attribute_group **groups);
439
440
static inline void add_disk(struct gendisk *disk)
{
441
	device_add_disk(NULL, disk, NULL);
442
}
443
444
445
446
447
extern void device_add_disk_no_queue_reg(struct device *parent, struct gendisk *disk);
static inline void add_disk_no_queue_reg(struct gendisk *disk)
{
	device_add_disk_no_queue_reg(NULL, disk);
}
448

Linus Torvalds's avatar
Linus Torvalds committed
449
extern void del_gendisk(struct gendisk *gp);
450
extern struct gendisk *get_gendisk(dev_t dev, int *partno);
451
extern struct block_device *bdget_disk(struct gendisk *disk, int partno);
Linus Torvalds's avatar
Linus Torvalds committed
452
453
454
455

extern void set_device_ro(struct block_device *bdev, int flag);
extern void set_disk_ro(struct gendisk *disk, int flag);

456
457
458
459
460
static inline int get_disk_ro(struct gendisk *disk)
{
	return disk->part0.policy;
}

461
462
extern void disk_block_events(struct gendisk *disk);
extern void disk_unblock_events(struct gendisk *disk);
463
extern void disk_flush_events(struct gendisk *disk, unsigned int mask);
464
465
extern unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask);

Linus Torvalds's avatar
Linus Torvalds committed
466
/* drivers/char/random.c */
467
extern void add_disk_randomness(struct gendisk *disk) __latent_entropy;
Linus Torvalds's avatar
Linus Torvalds committed
468
469
470
471
extern void rand_initialize_disk(struct gendisk *disk);

static inline sector_t get_start_sect(struct block_device *bdev)
{
Tejun Heo's avatar
Tejun Heo committed
472
	return bdev->bd_part->start_sect;
Linus Torvalds's avatar
Linus Torvalds committed
473
474
475
}
static inline sector_t get_capacity(struct gendisk *disk)
{
476
	return disk->part0.nr_sects;
Linus Torvalds's avatar
Linus Torvalds committed
477
478
479
}
static inline void set_capacity(struct gendisk *disk, sector_t size)
{
480
	disk->part0.nr_sects = size;
Linus Torvalds's avatar
Linus Torvalds committed
481
482
483
484
}

#ifdef CONFIG_SOLARIS_X86_PARTITION

485
#define SOLARIS_X86_NUMSLICE	16
Linus Torvalds's avatar
Linus Torvalds committed
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
#define SOLARIS_X86_VTOC_SANE	(0x600DDEEEUL)

struct solaris_x86_slice {
	__le16 s_tag;		/* ID tag of partition */
	__le16 s_flag;		/* permission flags */
	__le32 s_start;		/* start sector no of partition */
	__le32 s_size;		/* # of blocks in partition */
};

struct solaris_x86_vtoc {
	unsigned int v_bootinfo[3];	/* info needed by mboot (unsupported) */
	__le32 v_sanity;		/* to verify vtoc sanity */
	__le32 v_version;		/* layout version */
	char	v_volume[8];		/* volume name */
	__le16	v_sectorsz;		/* sector size in bytes */
	__le16	v_nparts;		/* number of partitions */
	unsigned int v_reserved[10];	/* free space */
	struct solaris_x86_slice
		v_slice[SOLARIS_X86_NUMSLICE]; /* slice headers */
	unsigned int timestamp[SOLARIS_X86_NUMSLICE]; /* timestamp (unsupported) */
	char	v_asciilabel[128];	/* for compatibility */
};

#endif /* CONFIG_SOLARIS_X86_PARTITION */

#ifdef CONFIG_BSD_DISKLABEL
/*
 * BSD disklabel support by Yossi Gottlieb <yogo@math.tau.ac.il>
 * updated by Marc Espie <Marc.Espie@openbsd.org>
 */

/* check against BSD src/sys/sys/disklabel.h for consistency */

#define BSD_DISKMAGIC	(0x82564557UL)	/* The disk magic number */
#define BSD_MAXPARTITIONS	16
#define OPENBSD_MAXPARTITIONS	16
#define BSD_FS_UNUSED		0	/* disklabel unused partition entry ID */
struct bsd_disklabel {
	__le32	d_magic;		/* the magic number */
	__s16	d_type;			/* drive type */
	__s16	d_subtype;		/* controller/d_type specific */
	char	d_typename[16];		/* type name, e.g. "eagle" */
	char	d_packname[16];			/* pack identifier */ 
	__u32	d_secsize;		/* # of bytes per sector */
	__u32	d_nsectors;		/* # of data sectors per track */
	__u32	d_ntracks;		/* # of tracks per cylinder */
	__u32	d_ncylinders;		/* # of data cylinders per unit */
	__u32	d_secpercyl;		/* # of data sectors per cylinder */
	__u32	d_secperunit;		/* # of data sectors per unit */
	__u16	d_sparespertrack;	/* # of spare sectors per track */
	__u16	d_sparespercyl;		/* # of spare sectors per cylinder */
	__u32	d_acylinders;		/* # of alt. cylinders per unit */
	__u16	d_rpm;			/* rotational speed */
	__u16	d_interleave;		/* hardware sector interleave */
	__u16	d_trackskew;		/* sector 0 skew, per track */
	__u16	d_cylskew;		/* sector 0 skew, per cylinder */
	__u32	d_headswitch;		/* head switch time, usec */
	__u32	d_trkseek;		/* track-to-track seek, usec */
	__u32	d_flags;		/* generic flags */
#define NDDATA 5
	__u32	d_drivedata[NDDATA];	/* drive-type specific information */
#define NSPARE 5
	__u32	d_spare[NSPARE];	/* reserved for future use */
	__le32	d_magic2;		/* the magic number (again) */
	__le16	d_checksum;		/* xor of data incl. partitions */

			/* filesystem and partition information: */
	__le16	d_npartitions;		/* number of partitions in following */
	__le32	d_bbsize;		/* size of boot area at sn0, bytes */
	__le32	d_sbsize;		/* max size of fs superblock, bytes */
	struct	bsd_partition {		/* the partition table */
		__le32	p_size;		/* number of sectors in partition */
		__le32	p_offset;	/* starting sector */
		__le32	p_fsize;	/* filesystem basic fragment size */
		__u8	p_fstype;	/* filesystem type, see below */
		__u8	p_frag;		/* filesystem fragments per block */
		__le16	p_cpg;		/* filesystem cylinders per group */
	} d_partitions[BSD_MAXPARTITIONS];	/* actually may be more */
};

#endif	/* CONFIG_BSD_DISKLABEL */

#ifdef CONFIG_UNIXWARE_DISKLABEL
/*
 * Unixware slices support by Andrzej Krzysztofowicz <ankry@mif.pg.gda.pl>
 * and Krzysztof G. Baranowski <kgb@knm.org.pl>
 */

#define UNIXWARE_DISKMAGIC     (0xCA5E600DUL)	/* The disk magic number */
#define UNIXWARE_DISKMAGIC2    (0x600DDEEEUL)	/* The slice table magic nr */
#define UNIXWARE_NUMSLICE      16
#define UNIXWARE_FS_UNUSED     0		/* Unused slice entry ID */

struct unixware_slice {
	__le16   s_label;	/* label */
	__le16   s_flags;	/* permission flags */
	__le32   start_sect;	/* starting sector */
	__le32   nr_sects;	/* number of sectors in slice */
};

struct unixware_disklabel {
	__le32   d_type;               	/* drive type */
	__le32   d_magic;                /* the magic number */
	__le32   d_version;              /* version number */
	char    d_serial[12];           /* serial number of the device */
	__le32   d_ncylinders;           /* # of data cylinders per device */
	__le32   d_ntracks;              /* # of tracks per cylinder */
	__le32   d_nsectors;             /* # of data sectors per track */
	__le32   d_secsize;              /* # of bytes per sector */
	__le32   d_part_start;           /* # of first sector of this partition */
	__le32   d_unknown1[12];         /* ? */
 	__le32	d_alt_tbl;              /* byte offset of alternate table */
 	__le32	d_alt_len;              /* byte length of alternate table */
 	__le32	d_phys_cyl;             /* # of physical cylinders per device */
 	__le32	d_phys_trk;             /* # of physical tracks per cylinder */
 	__le32	d_phys_sec;             /* # of physical sectors per track */
 	__le32	d_phys_bytes;           /* # of physical bytes per sector */
 	__le32	d_unknown2;             /* ? */
	__le32   d_unknown3;             /* ? */
	__le32	d_pad[8];               /* pad */

	struct unixware_vtoc {
		__le32	v_magic;		/* the magic number */
		__le32	v_version;		/* version number */
		char	v_name[8];		/* volume name */
		__le16	v_nslices;		/* # of slices */
		__le16	v_unknown1;		/* ? */
		__le32	v_reserved[10];		/* reserved */
		struct unixware_slice
			v_slice[UNIXWARE_NUMSLICE];	/* slice headers */
	} vtoc;

};  /* 408 */

#endif /* CONFIG_UNIXWARE_DISKLABEL */

#ifdef CONFIG_MINIX_SUBPARTITION
#   define MINIX_NR_SUBPARTITIONS  4
#endif /* CONFIG_MINIX_SUBPARTITION */

626
627
628
629
#define ADDPART_FLAG_NONE	0
#define ADDPART_FLAG_RAID	1
#define ADDPART_FLAG_WHOLEDISK	2

630
631
extern int blk_alloc_devt(struct hd_struct *part, dev_t *devt);
extern void blk_free_devt(dev_t devt);
632
extern void blk_invalidate_devt(dev_t devt);
633
634
extern dev_t blk_lookup_devt(const char *name, int partno);
extern char *disk_name (struct gendisk *hd, int partno, char *buf);
Linus Torvalds's avatar
Linus Torvalds committed
635

636
int bdev_disk_changed(struct block_device *bdev, bool invalidate);
637
638
int blk_add_partitions(struct gendisk *disk, struct block_device *bdev);
int blk_drop_partitions(struct gendisk *disk, struct block_device *bdev);
639
extern int disk_expand_part_tbl(struct gendisk *disk, int target);
640
641
extern struct hd_struct * __must_check add_partition(struct gendisk *disk,
						     int partno, sector_t start,
642
643
644
						     sector_t len, int flags,
						     struct partition_meta_info
						       *info);
645
extern void __delete_partition(struct percpu_ref *);
Linus Torvalds's avatar
Linus Torvalds committed
646
extern void delete_partition(struct gendisk *, int);
647
extern void printk_all_partitions(void);
Linus Torvalds's avatar
Linus Torvalds committed
648

649
extern struct gendisk *__alloc_disk_node(int minors, int node_id);
650
extern struct kobject *get_disk_and_module(struct gendisk *disk);
Linus Torvalds's avatar
Linus Torvalds committed
651
extern void put_disk(struct gendisk *disk);
652
extern void put_disk_and_module(struct gendisk *disk);
653
extern void blk_register_region(dev_t devt, unsigned long range,
Linus Torvalds's avatar
Linus Torvalds committed
654
655
656
657
			struct module *module,
			struct kobject *(*probe)(dev_t, int *, void *),
			int (*lock)(dev_t, void *),
			void *data);
658
extern void blk_unregister_region(dev_t devt, unsigned long range);
Linus Torvalds's avatar
Linus Torvalds committed
659

660
661
extern ssize_t part_size_show(struct device *dev,
			      struct device_attribute *attr, char *buf);
662
663
extern ssize_t part_stat_show(struct device *dev,
			      struct device_attribute *attr, char *buf);
664
665
extern ssize_t part_inflight_show(struct device *dev,
			      struct device_attribute *attr, char *buf);
666
667
668
669
670
671
672
#ifdef CONFIG_FAIL_MAKE_REQUEST
extern ssize_t part_fail_show(struct device *dev,
			      struct device_attribute *attr, char *buf);
extern ssize_t part_fail_store(struct device *dev,
			       struct device_attribute *attr,
			       const char *buf, size_t count);
#endif /* CONFIG_FAIL_MAKE_REQUEST */
673

674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
#define alloc_disk_node(minors, node_id)				\
({									\
	static struct lock_class_key __key;				\
	const char *__name;						\
	struct gendisk *__disk;						\
									\
	__name = "(gendisk_completion)"#minors"("#node_id")";		\
									\
	__disk = __alloc_disk_node(minors, node_id);			\
									\
	if (__disk)							\
		lockdep_init_map(&__disk->lockdep_map, __name, &__key, 0); \
									\
	__disk;								\
})

#define alloc_disk(minors) alloc_disk_node(minors, NUMA_NO_NODE)

692
static inline int hd_ref_init(struct hd_struct *part)
693
{
694
695
696
697
	if (percpu_ref_init(&part->ref, __delete_partition, 0,
				GFP_KERNEL))
		return -ENOMEM;
	return 0;
698
699
700
701
}

static inline void hd_struct_get(struct hd_struct *part)
{
702
	percpu_ref_get(&part->ref);
703
704
705
706
}

static inline int hd_struct_try_get(struct hd_struct *part)
{
707
	return percpu_ref_tryget_live(&part->ref);
708
709
710
711
}

static inline void hd_struct_put(struct hd_struct *part)
{
712
713
714
715
716
717
	percpu_ref_put(&part->ref);
}

static inline void hd_struct_kill(struct hd_struct *part)
{
	percpu_ref_kill(&part->ref);
718
719
}

720
721
722
723
static inline void hd_free_part(struct hd_struct *part)
{
	free_part_stats(part);
	free_part_info(part);
724
	percpu_ref_exit(&part->ref);
725
726
}

727
728
729
730
731
732
733
734
735
736
737
/*
 * Any access of part->nr_sects which is not protected by partition
 * bd_mutex or gendisk bdev bd_mutex, should be done using this
 * accessor function.
 *
 * Code written along the lines of i_size_read() and i_size_write().
 * CONFIG_PREEMPT case optimizes the case of UP kernel with preemption
 * on.
 */
static inline sector_t part_nr_sects_read(struct hd_struct *part)
{
Christoph Hellwig's avatar
Christoph Hellwig committed
738
#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
739
740
741
742
743
744
745
	sector_t nr_sects;
	unsigned seq;
	do {
		seq = read_seqcount_begin(&part->nr_sects_seq);
		nr_sects = part->nr_sects;
	} while (read_seqcount_retry(&part->nr_sects_seq, seq));
	return nr_sects;
Christoph Hellwig's avatar
Christoph Hellwig committed
746
#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
	sector_t nr_sects;

	preempt_disable();
	nr_sects = part->nr_sects;
	preempt_enable();
	return nr_sects;
#else
	return part->nr_sects;
#endif
}

/*
 * Should be called with mutex lock held (typically bd_mutex) of partition
 * to provide mutual exlusion among writers otherwise seqcount might be
 * left in wrong state leaving the readers spinning infinitely.
 */
static inline void part_nr_sects_write(struct hd_struct *part, sector_t size)
{
Christoph Hellwig's avatar
Christoph Hellwig committed
765
#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
766
767
768
	write_seqcount_begin(&part->nr_sects_seq);
	part->nr_sects = size;
	write_seqcount_end(&part->nr_sects_seq);
Christoph Hellwig's avatar
Christoph Hellwig committed
769
#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
770
771
772
773
774
775
776
777
	preempt_disable();
	part->nr_sects = size;
	preempt_enable();
#else
	part->nr_sects = size;
#endif
}

778
779
780
781
782
783
784
785
#if defined(CONFIG_BLK_DEV_INTEGRITY)
extern void blk_integrity_add(struct gendisk *);
extern void blk_integrity_del(struct gendisk *);
#else	/* CONFIG_BLK_DEV_INTEGRITY */
static inline void blk_integrity_add(struct gendisk *disk) { }
static inline void blk_integrity_del(struct gendisk *disk) { }
#endif	/* CONFIG_BLK_DEV_INTEGRITY */

786
787
788
789
#else /* CONFIG_BLOCK */

static inline void printk_all_partitions(void) { }

790
static inline dev_t blk_lookup_devt(const char *name, int partno)
791
792
793
794
{
	dev_t devt = MKDEV(0, 0);
	return devt;
}
795
#endif /* CONFIG_BLOCK */
796

797
#endif /* _LINUX_GENHD_H */