File: /usr/src/linux/fs/partitions/check.c
1 /*
2 * Code extracted from drivers/block/genhd.c
3 * Copyright (C) 1991-1998 Linus Torvalds
4 * Re-organised Feb 1998 Russell King
5 *
6 * We now have independent partition support from the
7 * block drivers, which allows all the partition code to
8 * be grouped in one location, and it to be mostly self
9 * contained.
10 *
11 * Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
12 */
13
14 #include <linux/config.h>
15 #include <linux/fs.h>
16 #include <linux/genhd.h>
17 #include <linux/kernel.h>
18 #include <linux/major.h>
19 #include <linux/blk.h>
20 #include <linux/init.h>
21 #include <linux/raid/md.h>
22
23 #include "check.h"
24
25 #include "acorn.h"
26 #include "amiga.h"
27 #include "atari.h"
28 #include "ldm.h"
29 #include "mac.h"
30 #include "msdos.h"
31 #include "osf.h"
32 #include "sgi.h"
33 #include "sun.h"
34 #include "ibm.h"
35 #include "ultrix.h"
36
37 extern int *blk_size[];
38
39 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
40
41 static int (*check_part[])(struct gendisk *hd, kdev_t dev, unsigned long first_sect, int first_minor) = {
42 #ifdef CONFIG_ACORN_PARTITION
43 acorn_partition,
44 #endif
45 #ifdef CONFIG_LDM_PARTITION
46 ldm_partition, /* this must come before msdos */
47 #endif
48 #ifdef CONFIG_MSDOS_PARTITION
49 msdos_partition,
50 #endif
51 #ifdef CONFIG_OSF_PARTITION
52 osf_partition,
53 #endif
54 #ifdef CONFIG_SUN_PARTITION
55 sun_partition,
56 #endif
57 #ifdef CONFIG_AMIGA_PARTITION
58 amiga_partition,
59 #endif
60 #ifdef CONFIG_ATARI_PARTITION
61 atari_partition,
62 #endif
63 #ifdef CONFIG_MAC_PARTITION
64 mac_partition,
65 #endif
66 #ifdef CONFIG_SGI_PARTITION
67 sgi_partition,
68 #endif
69 #ifdef CONFIG_ULTRIX_PARTITION
70 ultrix_partition,
71 #endif
72 #ifdef CONFIG_IBM_PARTITION
73 ibm_partition,
74 #endif
75 NULL
76 };
77
78 /*
79 * This is ucking fugly but its probably the best thing for 2.4.x
80 * Take it as a clear reminder than we should put the device name
81 * generation in the object kdev_t points to in 2.5.
82 */
83
84 #ifdef CONFIG_ARCH_S390
85 int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
86 EXPORT_SYMBOL(genhd_dasd_name);
87 #endif
88
89 /*
90 * disk_name() is used by partition check code and the md driver.
91 * It formats the devicename of the indicated disk into
92 * the supplied buffer (of size at least 32), and returns
93 * a pointer to that same buffer (for convenience).
94 */
95
96 char *disk_name (struct gendisk *hd, int minor, char *buf)
97 {
98 const char *maj = hd->major_name;
99 unsigned int unit = (minor >> hd->minor_shift);
100 unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
101
102 if ((unit < hd->nr_real) && hd->part[minor].de) {
103 int pos;
104
105 pos = devfs_generate_path (hd->part[minor].de, buf, 64);
106 if (pos >= 0)
107 return buf + pos;
108 }
109
110 #ifdef CONFIG_ARCH_S390
111 if (genhd_dasd_name
112 && genhd_dasd_name (buf, unit, part, hd) == 0)
113 return buf;
114 #endif
115 /*
116 * IDE devices use multiple major numbers, but the drives
117 * are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
118 * This requires special handling here.
119 */
120 switch (hd->major) {
121 case IDE9_MAJOR:
122 unit += 2;
123 case IDE8_MAJOR:
124 unit += 2;
125 case IDE7_MAJOR:
126 unit += 2;
127 case IDE6_MAJOR:
128 unit += 2;
129 case IDE5_MAJOR:
130 unit += 2;
131 case IDE4_MAJOR:
132 unit += 2;
133 case IDE3_MAJOR:
134 unit += 2;
135 case IDE2_MAJOR:
136 unit += 2;
137 case IDE1_MAJOR:
138 unit += 2;
139 case IDE0_MAJOR:
140 maj = "hd";
141 break;
142 case MD_MAJOR:
143 sprintf(buf, "%s%d", maj, unit);
144 return buf;
145 }
146 if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
147 unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
148 if (unit+'a' > 'z') {
149 unit -= 26;
150 sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
151 if (part)
152 sprintf(buf + 4, "%d", part);
153 return buf;
154 }
155 }
156 if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
157 int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
158 if (part == 0)
159 sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
160 else
161 sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
162 return buf;
163 }
164 if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
165 int ctlr = hd->major - COMPAQ_CISS_MAJOR;
166 if (part == 0)
167 sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
168 else
169 sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
170 return buf;
171 }
172 if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
173 int ctlr = hd->major - DAC960_MAJOR;
174 if (part == 0)
175 sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
176 else
177 sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
178 return buf;
179 }
180 if (part)
181 sprintf(buf, "%s%c%d", maj, unit+'a', part);
182 else
183 sprintf(buf, "%s%c", maj, unit+'a');
184 return buf;
185 }
186
187 /*
188 * Add a partitions details to the devices partition description.
189 */
190 void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
191 {
192 #ifndef CONFIG_DEVFS_FS
193 char buf[40];
194 #endif
195
196 hd->part[minor].start_sect = start;
197 hd->part[minor].nr_sects = size;
198 #ifdef CONFIG_DEVFS_FS
199 printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
200 #else
201 if ((hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7) ||
202 (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7))
203 printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
204 else
205 printk(" %s", disk_name(hd, minor, buf));
206 #endif
207 }
208
209 unsigned int get_ptable_blocksize(kdev_t dev)
210 {
211 int ret = 1024;
212
213 /*
214 * See whether the low-level driver has given us a minumum blocksize.
215 * If so, check to see whether it is larger than the default of 1024.
216 */
217 if (!blksize_size[MAJOR(dev)])
218 return ret;
219
220 /*
221 * Check for certain special power of two sizes that we allow.
222 * With anything larger than 1024, we must force the blocksize up to
223 * the natural blocksize for the device so that we don't have to try
224 * and read partial sectors. Anything smaller should be just fine.
225 */
226
227 switch (blksize_size[MAJOR(dev)][MINOR(dev)]) {
228 case 2048:
229 ret = 2048;
230 break;
231 case 4096:
232 ret = 4096;
233 break;
234 case 8192:
235 ret = 8192;
236 break;
237 case 1024:
238 case 512:
239 case 256:
240 case 0:
241 /*
242 * These are all OK.
243 */
244 break;
245 default:
246 panic("Strange blocksize for partition table\n");
247 }
248
249 return ret;
250 }
251
252 static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
253 {
254 devfs_handle_t de = NULL;
255 static int first_time = 1;
256 unsigned long first_sector;
257 char buf[64];
258 int i;
259
260 if (first_time)
261 printk(KERN_INFO "Partition check:\n");
262 first_time = 0;
263 first_sector = hd->part[MINOR(dev)].start_sect;
264
265 /*
266 * This is a kludge to allow the partition check to be
267 * skipped for specific drives (e.g. IDE CD-ROM drives)
268 */
269 if ((int)first_sector == -1) {
270 hd->part[MINOR(dev)].start_sect = 0;
271 return;
272 }
273
274 if (hd->de_arr)
275 de = hd->de_arr[MINOR(dev) >> hd->minor_shift];
276 i = devfs_generate_path (de, buf, sizeof buf);
277 if (i >= 0)
278 printk(KERN_INFO " /dev/%s:", buf + i);
279 else
280 printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
281 for (i = 0; check_part[i]; i++)
282 if (check_part[i](hd, dev, first_sector, first_part_minor))
283 goto setup_devfs;
284
285 printk(" unknown partition table\n");
286 setup_devfs:
287 i = first_part_minor - 1;
288 devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
289 }
290
291 #ifdef CONFIG_DEVFS_FS
292 static void devfs_register_partition (struct gendisk *dev, int minor, int part)
293 {
294 int devnum = minor >> dev->minor_shift;
295 devfs_handle_t dir;
296 unsigned int devfs_flags = DEVFS_FL_DEFAULT;
297 char devname[16];
298
299 if (dev->part[minor + part].de) return;
300 dir = devfs_get_parent (dev->part[minor].de);
301 if (!dir) return;
302 if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
303 devfs_flags |= DEVFS_FL_REMOVABLE;
304 sprintf (devname, "part%d", part);
305 dev->part[minor + part].de =
306 devfs_register (dir, devname, devfs_flags,
307 dev->major, minor + part,
308 S_IFBLK | S_IRUSR | S_IWUSR,
309 dev->fops, NULL);
310 }
311
312 static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
313
314 static void devfs_register_disc (struct gendisk *dev, int minor)
315 {
316 int pos = 0;
317 int devnum = minor >> dev->minor_shift;
318 devfs_handle_t dir, slave;
319 unsigned int devfs_flags = DEVFS_FL_DEFAULT;
320 char dirname[64], symlink[16];
321 static devfs_handle_t devfs_handle;
322
323 if (dev->part[minor].de) return;
324 if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
325 devfs_flags |= DEVFS_FL_REMOVABLE;
326 if (dev->de_arr) {
327 dir = dev->de_arr[devnum];
328 if (!dir) /* Aware driver wants to block disc management */
329 return;
330 pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3);
331 if (pos < 0) return;
332 strncpy (dirname + pos, "../", 3);
333 }
334 else {
335 /* Unaware driver: construct "real" directory */
336 sprintf (dirname, "../%s/disc%d", dev->major_name, devnum);
337 dir = devfs_mk_dir (NULL, dirname + 3, NULL);
338 }
339 if (!devfs_handle)
340 devfs_handle = devfs_mk_dir (NULL, "discs", NULL);
341 dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace);
342 sprintf (symlink, "disc%d", dev->part[minor].number);
343 devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
344 dirname + pos, &slave, NULL);
345 dev->part[minor].de =
346 devfs_register (dir, "disc", devfs_flags, dev->major, minor,
347 S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
348 devfs_auto_unregister (dev->part[minor].de, slave);
349 if (!dev->de_arr)
350 devfs_auto_unregister (slave, dir);
351 }
352 #endif /* CONFIG_DEVFS_FS */
353
354 void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
355 {
356 #ifdef CONFIG_DEVFS_FS
357 int part;
358
359 if (!unregister)
360 devfs_register_disc (dev, minor);
361 for (part = 1; part < dev->max_p; part++) {
362 if ( unregister || (dev->part[part + minor].nr_sects < 1) ) {
363 devfs_unregister (dev->part[part + minor].de);
364 dev->part[part + minor].de = NULL;
365 continue;
366 }
367 devfs_register_partition (dev, minor, part);
368 }
369 if (unregister) {
370 devfs_unregister (dev->part[minor].de);
371 dev->part[minor].de = NULL;
372 devfs_dealloc_unique_number (&disc_numspace,
373 dev->part[minor].number);
374 }
375 #endif /* CONFIG_DEVFS_FS */
376 }
377
378 /*
379 * This function will re-read the partition tables for a given device,
380 * and set things back up again. There are some important caveats,
381 * however. You must ensure that no one is using the device, and no one
382 * can start using the device while this function is being executed.
383 *
384 * Much of the cleanup from the old partition tables should have already been
385 * done
386 */
387
388 void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
389 struct block_device_operations *ops, long size)
390 {
391 if (!gdev)
392 return;
393 grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
394 }
395
396 void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
397 {
398 int i;
399 int first_minor = drive << dev->minor_shift;
400 int end_minor = first_minor + dev->max_p;
401
402 if(!dev->sizes)
403 blk_size[dev->major] = NULL;
404
405 dev->part[first_minor].nr_sects = size;
406 /* No such device or no minors to use for partitions */
407 if (!size || minors == 1)
408 return;
409
410 check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
411
412 /*
413 * We need to set the sizes array before we will be able to access
414 * any of the partitions on this device.
415 */
416 if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
417 for (i = first_minor; i < end_minor; i++)
418 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
419 blk_size[dev->major] = dev->sizes;
420 }
421 }
422