direct-io.hg

view xen/drivers/block/genhd.c @ 875:ad4db8b417c1

bitkeeper revision 1.547 (3fa3dd2aH8eamu3ONvYovJgq8wBNbQ)

Many files:
Fixes to the DOM0 interface and domain building code. Ready for new save/restore dom0_ops.
author kaf24@scramble.cl.cam.ac.uk
date Sat Nov 01 16:19:54 2003 +0000 (2003-11-01)
parents 9888f92572ba
children 9f85adafc1e1
line source
1 /*
2 * Code extracted from
3 * linux/kernel/hd.c
4 *
5 * Copyright (C) 1991-1998 Linus Torvalds
6 *
7 * devfs support - jj, rgooch, 980122
8 *
9 * Moved partition checking code to fs/partitions* - Russell King
10 * (linux@arm.uk.linux.org)
11 */
13 /*
14 * TODO: rip out the remaining init crap from this file --hch
15 */
17 #include <xeno/config.h>
18 #include <xeno/module.h>
19 /*#include <xeno/fs.h>*/
20 #include <xeno/genhd.h>
21 #include <xeno/lib.h>
22 #include <xeno/blk.h>
23 #include <xeno/init.h>
24 #include <xeno/spinlock.h>
27 static rwlock_t gendisk_lock;
29 /*
30 * Global kernel list of partitioning information.
31 *
32 * XXX: you should _never_ access this directly.
33 * the only reason this is exported is source compatiblity.
34 */
35 /*static*/ struct gendisk *gendisk_head;
36 static struct gendisk *gendisk_array[MAX_BLKDEV];
38 EXPORT_SYMBOL(gendisk_head);
41 /**
42 * add_gendisk - add partitioning information to kernel list
43 * @gp: per-device partitioning information
44 *
45 * This function registers the partitioning information in @gp
46 * with the kernel.
47 */
48 void
49 add_gendisk(struct gendisk *gp)
50 {
51 struct gendisk *sgp;
53 write_lock(&gendisk_lock);
55 /*
56 * In 2.5 this will go away. Fix the drivers who rely on
57 * old behaviour.
58 */
60 for (sgp = gendisk_head; sgp; sgp = sgp->next)
61 {
62 if (sgp == gp)
63 {
64 // printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
65 // sgp->major)
66 goto out;
67 }
68 }
69 gendisk_array[gp->major] = gp;
70 gp->next = gendisk_head;
71 gendisk_head = gp;
72 out:
73 write_unlock(&gendisk_lock);
74 }
76 EXPORT_SYMBOL(add_gendisk);
79 /**
80 * del_gendisk - remove partitioning information from kernel list
81 * @gp: per-device partitioning information
82 *
83 * This function unregisters the partitioning information in @gp
84 * with the kernel.
85 */
86 void
87 del_gendisk(struct gendisk *gp)
88 {
89 struct gendisk **gpp;
91 write_lock(&gendisk_lock);
92 gendisk_array[gp->major] = NULL;
93 for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next))
94 if (*gpp == gp)
95 break;
96 if (*gpp)
97 *gpp = (*gpp)->next;
98 write_unlock(&gendisk_lock);
99 }
101 EXPORT_SYMBOL(del_gendisk);
104 /**
105 * get_gendisk - get partitioning information for a given device
106 * @dev: device to get partitioning information for
107 *
108 * This function gets the structure containing partitioning
109 * information for the given device @dev.
110 */
111 struct gendisk *
112 get_gendisk(kdev_t dev)
113 {
114 struct gendisk *gp = NULL;
115 int maj = MAJOR(dev);
117 read_lock(&gendisk_lock);
118 if ((gp = gendisk_array[maj]))
119 goto out;
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)
124 break;
125 out:
126 read_unlock(&gendisk_lock);
127 return gp;
128 }
130 EXPORT_SYMBOL(get_gendisk);
133 /**
134 * walk_gendisk - issue a command for every registered gendisk
135 * @walk: user-specified callback
136 * @data: opaque data for the callback
137 *
138 * This function walks through the gendisk chain and calls back
139 * into @walk for every element.
140 */
141 int
142 walk_gendisk(int (*walk)(struct gendisk *, void *), void *data)
143 {
144 struct gendisk *gp;
145 int error = 0;
147 read_lock(&gendisk_lock);
148 for (gp = gendisk_head; gp; gp = gp->next)
149 if ((error = walk(gp, data)))
150 break;
151 read_unlock(&gendisk_lock);
153 return error;
154 }
157 #ifdef CONFIG_PROC_FS
158 int
159 get_partition_list(char *page, char **start, off_t offset, int count)
160 {
161 struct gendisk *gp;
162 struct hd_struct *hd;
163 char buf[64];
164 int len, n;
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)
172 continue;
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));
179 if (len < offset)
180 offset -= len, len = 0;
181 else if (len >= offset + count)
182 goto out;
183 }
184 }
186 out:
187 read_unlock(&gendisk_lock);
188 *start = page + offset;
189 len -= offset;
190 if (len < 0)
191 len = 0;
192 return len > count ? count : len;
193 }
194 #endif
196 /* XXX SMH: stuff from fs/partitions dumped here temporarily */
199 /*
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.
204 *
205 * Much of the cleanup from the old partition tables should have already been
206 * done
207 */
208 void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
209 struct block_device_operations *ops, long size)
210 {
211 if (!gdev)
212 return;
213 grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
214 }
216 void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
217 {
218 int i;
219 int first_minor = drive << dev->minor_shift;
220 int end_minor = first_minor + dev->max_p;
222 if(!dev->sizes)
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);
230 #endif
232 if (!size || minors == 1)
233 return;
235 if (dev->sizes) {
236 dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
237 for (i = first_minor + 1; i < end_minor; i++)
238 dev->sizes[i] = 0;
239 }
240 blk_size[dev->major] = dev->sizes;
241 #if 0
242 /* XXX SMH: don't actually check partition details yet */
243 check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
244 #endif
246 /*
247 * We need to set the sizes array before we will be able to access
248 * any of the partitions on this device.
249 */
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);
253 }
254 }
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)
264 {
265 rwlock_init(&gendisk_lock);
266 blk_dev_init();
267 sti();
268 #ifdef CONFIG_NET
269 net_dev_init();
270 #endif
271 #ifdef CONFIG_ATM
272 (void) atmdev_init();
273 #endif
274 #ifdef CONFIG_VT
275 console_map_init();
276 #endif
277 return 0;
278 }
280 __initcall(device_init);