5 * Copyright (C) 1991-1998 Linus Torvalds
7 * devfs support - jj, rgooch, 980122
9 * Moved partition checking code to fs/partitions* - Russell King
10 * (linux@arm.uk.linux.org)
14 * TODO: rip out the remaining init crap from this file --hch
17 #include <linux/config.h>
18 #include <linux/module.h>
20 #include <linux/genhd.h>
21 #include <linux/kernel.h>
22 #include <linux/blk.h>
23 #include <linux/init.h>
24 #include <linux/spinlock.h>
25 #include <linux/seq_file.h>
29 * Global kernel list of partitioning information.
31 * XXX: you should _never_ access this directly.
32 * the only reason this is exported is source compatiblity.
34 /*static*/ struct gendisk *gendisk_head;
35 static struct gendisk *gendisk_array[MAX_BLKDEV];
36 static rwlock_t gendisk_lock = RW_LOCK_UNLOCKED;
38 EXPORT_SYMBOL(gendisk_head);
42 * add_gendisk - add partitioning information to kernel list
43 * @gp: per-device partitioning information
45 * This function registers the partitioning information in @gp
49 add_gendisk(struct gendisk *gp)
53 write_lock(&gendisk_lock);
56 * In 2.5 this will go away. Fix the drivers who rely on
60 for (sgp = gendisk_head; sgp; sgp = sgp->next)
64 // printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
69 gendisk_array[gp->major] = gp;
70 gp->next = gendisk_head;
73 write_unlock(&gendisk_lock);
76 EXPORT_SYMBOL(add_gendisk);
80 * del_gendisk - remove partitioning information from kernel list
81 * @gp: per-device partitioning information
83 * This function unregisters the partitioning information in @gp
87 del_gendisk(struct gendisk *gp)
91 write_lock(&gendisk_lock);
92 gendisk_array[gp->major] = NULL;
93 for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next))
98 write_unlock(&gendisk_lock);
101 EXPORT_SYMBOL(del_gendisk);
105 * get_gendisk - get partitioning information for a given device
106 * @dev: device to get partitioning information for
108 * This function gets the structure containing partitioning
109 * information for the given device @dev.
112 get_gendisk(kdev_t dev)
114 struct gendisk *gp = NULL;
115 int maj = MAJOR(dev);
117 read_lock(&gendisk_lock);
118 if ((gp = gendisk_array[maj]))
121 /* This is needed for early 2.4 source compatiblity. --hch */
122 for (gp = gendisk_head; gp; gp = gp->next)
123 if (gp->major == maj)
126 read_unlock(&gendisk_lock);
130 EXPORT_SYMBOL(get_gendisk);
134 * walk_gendisk - issue a command for every registered gendisk
135 * @walk: user-specified callback
136 * @data: opaque data for the callback
138 * This function walks through the gendisk chain and calls back
139 * into @walk for every element.
142 walk_gendisk(int (*walk)(struct gendisk *, void *), void *data)
147 read_lock(&gendisk_lock);
148 for (gp = gendisk_head; gp; gp = gp->next)
149 if ((error = walk(gp, data)))
151 read_unlock(&gendisk_lock);
156 #ifdef CONFIG_PROC_FS
158 static void *part_start(struct seq_file *s, loff_t *ppos)
163 read_lock(&gendisk_lock);
164 for (gp = gendisk_head; gp; gp = gp->next)
170 static void *part_next(struct seq_file *s, void *v, loff_t *pos)
173 return ((struct gendisk *)v)->next;
176 static void part_stop(struct seq_file *s, void *v)
178 read_unlock(&gendisk_lock);
181 static int part_show(struct seq_file *s, void *v)
183 struct gendisk *gp = v;
187 if (gp == gendisk_head) {
188 seq_puts(s, "major minor #blocks name"
189 #ifdef CONFIG_BLK_STATS
190 " rio rmerge rsect ruse wio wmerge "
191 "wsect wuse running use aveq"
196 /* show the full disk and all non-0 size partitions of it */
197 for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) {
198 if (gp->part[n].nr_sects) {
199 #ifdef CONFIG_BLK_STATS
200 struct hd_struct *hd = &gp->part[n];
202 disk_round_stats(hd);
203 seq_printf(s, "%4d %4d %10d %s "
204 "%d %d %d %d %d %d %d %d %d %d %d\n",
205 gp->major, n, gp->sizes[n],
206 disk_name(gp, n, buf),
207 hd->rd_ios, hd->rd_merges,
208 #define MSEC(x) ((x) * 1000 / HZ)
209 hd->rd_sectors, MSEC(hd->rd_ticks),
210 hd->wr_ios, hd->wr_merges,
211 hd->wr_sectors, MSEC(hd->wr_ticks),
212 hd->ios_in_flight, MSEC(hd->io_ticks),
215 seq_printf(s, "%4d %4d %10d %s\n",
216 gp->major, n, gp->sizes[n],
217 disk_name(gp, n, buf));
218 #endif /* CONFIG_BLK_STATS */
225 struct seq_operations partitions_op = {
233 extern int blk_dev_init(void);
234 extern int net_dev_init(void);
235 extern void console_map_init(void);
236 extern int atmdev_init(void);
238 int __init device_init(void)
246 (void) atmdev_init();
251 #ifdef CONFIG_VIODASD
257 __initcall(device_init);