1
2
3
4
5
6
7
8
9
10
11
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#include "efi.h"
37
38extern int *blk_size[];
39
40int warn_no_part = 1;
41
42static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
43#ifdef CONFIG_ACORN_PARTITION
44 acorn_partition,
45#endif
46#ifdef CONFIG_SGI_PARTITION
47 sgi_partition,
48#endif
49#ifdef CONFIG_EFI_PARTITION
50 efi_partition,
51#endif
52#ifdef CONFIG_LDM_PARTITION
53 ldm_partition,
54#endif
55#ifdef CONFIG_MSDOS_PARTITION
56 msdos_partition,
57#endif
58#ifdef CONFIG_OSF_PARTITION
59 osf_partition,
60#endif
61#ifdef CONFIG_SUN_PARTITION
62 sun_partition,
63#endif
64#ifdef CONFIG_AMIGA_PARTITION
65 amiga_partition,
66#endif
67#ifdef CONFIG_ATARI_PARTITION
68 atari_partition,
69#endif
70#ifdef CONFIG_MAC_PARTITION
71 mac_partition,
72#endif
73#ifdef CONFIG_ULTRIX_PARTITION
74 ultrix_partition,
75#endif
76#ifdef CONFIG_IBM_PARTITION
77 ibm_partition,
78#endif
79 NULL
80};
81
82
83
84
85
86
87
88
89#ifdef CONFIG_ARCH_S390
90int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
91int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
92 unsigned int no, unsigned long data);
93EXPORT_SYMBOL(genhd_dasd_name);
94EXPORT_SYMBOL(genhd_dasd_ioctl);
95#endif
96
97
98
99
100
101
102
103
104char *disk_name (struct gendisk *hd, int minor, char *buf)
105{
106 const char *maj = hd->major_name;
107 unsigned int unit = (minor >> hd->minor_shift);
108 unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
109
110 if ((unit < hd->nr_real) && hd->part[minor].de) {
111 int pos;
112
113 pos = devfs_generate_path (hd->part[minor].de, buf, 64);
114 if (pos >= 0)
115 return buf + pos;
116 }
117
118#ifdef CONFIG_ARCH_S390
119 if (genhd_dasd_name
120 && genhd_dasd_name (buf, unit, part, hd) == 0)
121 return buf;
122#endif
123
124
125
126
127
128 switch (hd->major) {
129 case IDE9_MAJOR:
130 unit += 2;
131 case IDE8_MAJOR:
132 unit += 2;
133 case IDE7_MAJOR:
134 unit += 2;
135 case IDE6_MAJOR:
136 unit += 2;
137 case IDE5_MAJOR:
138 unit += 2;
139 case IDE4_MAJOR:
140 unit += 2;
141 case IDE3_MAJOR:
142 unit += 2;
143 case IDE2_MAJOR:
144 unit += 2;
145 case IDE1_MAJOR:
146 unit += 2;
147 case IDE0_MAJOR:
148 maj = "hd";
149 break;
150 case MD_MAJOR:
151 sprintf(buf, "%s%d", maj, unit);
152 return buf;
153 }
154 if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
155 unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
156 if (unit+'a' > 'z') {
157 unit -= 26;
158 sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
159 if (part)
160 sprintf(buf + 4, "%d", part);
161 return buf;
162 }
163 }
164 if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
165 int ctlr = hd->major - COMPAQ_SMART2_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 >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
173 int ctlr = hd->major - COMPAQ_CISS_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 (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
181 int ctlr = hd->major - DAC960_MAJOR;
182 if (part == 0)
183 sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
184 else
185 sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
186 return buf;
187 }
188 if (hd->major == ATARAID_MAJOR) {
189 int disk = minor >> hd->minor_shift;
190 int part = minor & (( 1 << hd->minor_shift) - 1);
191 if (part == 0)
192 sprintf(buf, "%s/d%d", maj, disk);
193 else
194 sprintf(buf, "%s/d%dp%d", maj, disk, part);
195 return buf;
196 }
197 if (part)
198 sprintf(buf, "%s%c%d", maj, unit+'a', part);
199 else
200 sprintf(buf, "%s%c", maj, unit+'a');
201 return buf;
202}
203
204
205
206
207void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
208{
209#ifndef CONFIG_DEVFS_FS
210 char buf[40];
211#endif
212
213 hd->part[minor].start_sect = start;
214 hd->part[minor].nr_sects = size;
215#ifdef CONFIG_DEVFS_FS
216 printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
217#else
218 if ((hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7) ||
219 (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7))
220 printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
221 else
222 printk(" %s", disk_name(hd, minor, buf));
223#endif
224}
225
226static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
227{
228 devfs_handle_t de = NULL;
229 static int first_time = 1;
230 unsigned long first_sector;
231 struct block_device *bdev;
232 char buf[64];
233 int i;
234
235 if (first_time)
236 printk(KERN_INFO "Partition check:\n");
237 first_time = 0;
238 first_sector = hd->part[MINOR(dev)].start_sect;
239
240
241
242
243
244 if ((int)first_sector == -1) {
245 hd->part[MINOR(dev)].start_sect = 0;
246 return;
247 }
248
249 if (hd->de_arr)
250 de = hd->de_arr[MINOR(dev) >> hd->minor_shift];
251 i = devfs_generate_path (de, buf, sizeof buf);
252 if (i >= 0)
253 printk(KERN_INFO " /dev/%s:", buf + i);
254 else
255 printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
256 bdev = bdget(kdev_t_to_nr(dev));
257 bdev->bd_inode->i_size = (loff_t)hd->part[MINOR(dev)].nr_sects << 9;
258 bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));
259 for (i = 0; check_part[i]; i++) {
260 int res;
261 res = check_part[i](hd, bdev, first_sector, first_part_minor);
262 if (res) {
263 if (res < 0 && warn_no_part)
264 printk(" unable to read partition table\n");
265 goto setup_devfs;
266 }
267 }
268
269 printk(" unknown partition table\n");
270setup_devfs:
271 invalidate_bdev(bdev, 1);
272 truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
273 bdput(bdev);
274 i = first_part_minor - 1;
275 devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
276}
277
278#ifdef CONFIG_DEVFS_FS
279static void devfs_register_partition (struct gendisk *dev, int minor, int part)
280{
281 int devnum = minor >> dev->minor_shift;
282 devfs_handle_t dir;
283 unsigned int devfs_flags = DEVFS_FL_DEFAULT;
284 char devname[16];
285
286 if (dev->part[minor + part].de) return;
287 dir = devfs_get_parent (dev->part[minor].de);
288 if (!dir) return;
289 if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
290 devfs_flags |= DEVFS_FL_REMOVABLE;
291 sprintf (devname, "part%d", part);
292 dev->part[minor + part].de =
293 devfs_register (dir, devname, devfs_flags,
294 dev->major, minor + part,
295 S_IFBLK | S_IRUSR | S_IWUSR,
296 dev->fops, NULL);
297}
298
299static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
300
301static void devfs_register_disc (struct gendisk *dev, int minor)
302{
303 int pos = 0;
304 int devnum = minor >> dev->minor_shift;
305 devfs_handle_t dir, slave;
306 unsigned int devfs_flags = DEVFS_FL_DEFAULT;
307 char dirname[64], symlink[16];
308 static devfs_handle_t devfs_handle;
309
310 if (dev->part[minor].de) return;
311 if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
312 devfs_flags |= DEVFS_FL_REMOVABLE;
313 if (dev->de_arr) {
314 dir = dev->de_arr[devnum];
315 if (!dir)
316 return;
317 pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3);
318 if (pos < 0) return;
319 strncpy (dirname + pos, "../", 3);
320 }
321 else {
322
323 sprintf (dirname, "../%s/disc%d", dev->major_name, devnum);
324 dir = devfs_mk_dir (NULL, dirname + 3, NULL);
325 }
326 if (!devfs_handle)
327 devfs_handle = devfs_mk_dir (NULL, "discs", NULL);
328 dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace);
329 sprintf (symlink, "disc%d", dev->part[minor].number);
330 devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
331 dirname + pos, &slave, NULL);
332 dev->part[minor].de =
333 devfs_register (dir, "disc", devfs_flags, dev->major, minor,
334 S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
335 devfs_auto_unregister (dev->part[minor].de, slave);
336 if (!dev->de_arr)
337 devfs_auto_unregister (slave, dir);
338}
339#endif
340
341void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
342{
343#ifdef CONFIG_DEVFS_FS
344 int part;
345
346 if (!unregister)
347 devfs_register_disc (dev, minor);
348 for (part = 1; part < dev->max_p; part++) {
349 if ( unregister || (dev->part[minor].nr_sects < 1) ||
350 (dev->part[part + minor].nr_sects < 1) ) {
351 devfs_unregister (dev->part[part + minor].de);
352 dev->part[part + minor].de = NULL;
353 continue;
354 }
355 devfs_register_partition (dev, minor, part);
356 }
357 if (unregister) {
358 devfs_unregister (dev->part[minor].de);
359 dev->part[minor].de = NULL;
360 devfs_dealloc_unique_number (&disc_numspace,
361 dev->part[minor].number);
362 }
363#endif
364}
365
366
367
368
369
370
371
372
373
374
375
376void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
377 struct block_device_operations *ops, long size)
378{
379 if (!gdev)
380 return;
381 grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
382}
383
384void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
385{
386 int i;
387 int first_minor = drive << dev->minor_shift;
388 int end_minor = first_minor + dev->max_p;
389
390 if(!dev->sizes)
391 blk_size[dev->major] = NULL;
392
393 dev->part[first_minor].nr_sects = size;
394
395 if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) )
396 devfs_register_partitions (dev, first_minor, 0);
397 if (!size || minors == 1)
398 return;
399
400 if (dev->sizes) {
401 dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
402 for (i = first_minor + 1; i < end_minor; i++)
403 dev->sizes[i] = 0;
404 }
405 blk_size[dev->major] = dev->sizes;
406 check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
407
408
409
410
411
412 if (dev->sizes != NULL) {
413 for (i = first_minor; i < end_minor; i++)
414 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
415 }
416}
417
418unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
419{
420 struct address_space *mapping = bdev->bd_inode->i_mapping;
421 int sect = PAGE_CACHE_SIZE / 512;
422 struct page *page;
423
424 page = read_cache_page(mapping, n/sect,
425 (filler_t *)mapping->a_ops->readpage, NULL);
426 if (!IS_ERR(page)) {
427 wait_on_page(page);
428 if (!Page_Uptodate(page))
429 goto fail;
430 if (PageError(page))
431 goto fail;
432 p->v = page;
433 return (unsigned char *)page_address(page) + 512 * (n % sect);
434fail:
435 page_cache_release(page);
436 }
437 p->v = NULL;
438 return NULL;
439}
440