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 <xeno/config.h>
18
#include <xeno/module.h>
19
/*#include <xeno/fs.h>*/
20
#include <xeno/genhd.h>
23
#include <xeno/init.h>
24
#include <xeno/spinlock.h>
27
static rwlock_t gendisk_lock;
30
* Global kernel list of partitioning information.
32
* XXX: you should _never_ access this directly.
33
* the only reason this is exported is source compatiblity.
35
/*static*/ struct gendisk *gendisk_head;
36
static struct gendisk *gendisk_array[MAX_BLKDEV];
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);
157
#ifdef CONFIG_PROC_FS
159
get_partition_list(char *page, char **start, off_t offset, int count)
162
struct hd_struct *hd;
166
len = sprintf(page, "major minor #blocks name\n\n");
168
read_lock(&gendisk_lock);
169
for (gp = gendisk_head; gp; gp = gp->next) {
170
for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) {
171
if (gp->part[n].nr_sects == 0)
174
hd = &gp->part[n]; disk_round_stats(hd);
175
len += sprintf(page + len,
176
"%4d %4d %10d %s\n", gp->major,
177
n, gp->sizes[n], disk_name(gp, n, buf));
180
offset -= len, len = 0;
181
else if (len >= offset + count)
187
read_unlock(&gendisk_lock);
188
*start = page + offset;
192
return len > count ? count : len;
196
/* XXX SMH: stuff from fs/partitions dumped here temporarily */
200
* This function will re-read the partition tables for a given device,
201
* and set things back up again. There are some important caveats,
202
* however. You must ensure that no one is using the device, and no one
203
* can start using the device while this function is being executed.
205
* Much of the cleanup from the old partition tables should have already been
208
void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
209
struct block_device_operations *ops, long size)
213
grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
216
void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
219
int first_minor = drive << dev->minor_shift;
220
int end_minor = first_minor + dev->max_p;
223
blk_size[dev->major] = NULL;
225
dev->part[first_minor].nr_sects = size;
226
#ifdef DEVFS_MUST_DIE
227
/* No such device or no minors to use for partitions */
228
if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) )
229
devfs_register_partitions (dev, first_minor, 0);
232
if (!size || minors == 1)
236
dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
237
for (i = first_minor + 1; i < end_minor; i++)
240
blk_size[dev->major] = dev->sizes;
242
/* XXX SMH: don't actually check partition details yet */
243
check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
247
* We need to set the sizes array before we will be able to access
248
* any of the partitions on this device.
250
if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
251
for (i = first_minor; i < end_minor; i++)
252
dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
258
extern int blk_dev_init(void);
259
extern int net_dev_init(void);
260
extern void console_map_init(void);
261
extern int atmdev_init(void);
263
int __init device_init(void)
265
rwlock_init(&gendisk_lock);
272
(void) atmdev_init();
280
__initcall(device_init);