patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / partitions / check.c
1 /*
2  *  fs/partitions/check.c
3  *
4  *  Code extracted from drivers/block/genhd.c
5  *  Copyright (C) 1991-1998  Linus Torvalds
6  *  Re-organised Feb 1998 Russell King
7  *
8  *  We now have independent partition support from the
9  *  block drivers, which allows all the partition code to
10  *  be grouped in one location, and it to be mostly self
11  *  contained.
12  *
13  *  Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
14  */
15
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/fs.h>
19 #include <linux/kmod.h>
20 #include <linux/ctype.h>
21 #include <linux/devfs_fs_kernel.h>
22
23 #include "check.h"
24 #include "devfs.h"
25
26 #include "acorn.h"
27 #include "amiga.h"
28 #include "atari.h"
29 #include "ldm.h"
30 #include "mac.h"
31 #include "msdos.h"
32 #include "nec98.h"
33 #include "osf.h"
34 #include "sgi.h"
35 #include "sun.h"
36 #include "ibm.h"
37 #include "ultrix.h"
38 #include "efi.h"
39
40 #ifdef CONFIG_BLK_DEV_MD
41 extern void md_autodetect_dev(dev_t dev);
42 #endif
43
44 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
45
46 static int (*check_part[])(struct parsed_partitions *, struct block_device *) = {
47         /*
48          * Probe partition formats with tables at disk address 0
49          * that also have an ADFS boot block at 0xdc0.
50          */
51 #ifdef CONFIG_ACORN_PARTITION_ICS
52         adfspart_check_ICS,
53 #endif
54 #ifdef CONFIG_ACORN_PARTITION_POWERTEC
55         adfspart_check_POWERTEC,
56 #endif
57 #ifdef CONFIG_ACORN_PARTITION_EESOX
58         adfspart_check_EESOX,
59 #endif
60
61         /*
62          * Now move on to formats that only have partition info at
63          * disk address 0xdc0.  Since these may also have stale
64          * PC/BIOS partition tables, they need to come before
65          * the msdos entry.
66          */
67 #ifdef CONFIG_ACORN_PARTITION_CUMANA
68         adfspart_check_CUMANA,
69 #endif
70 #ifdef CONFIG_ACORN_PARTITION_ADFS
71         adfspart_check_ADFS,
72 #endif
73
74 #ifdef CONFIG_EFI_PARTITION
75         efi_partition,          /* this must come before msdos */
76 #endif
77 #ifdef CONFIG_LDM_PARTITION
78         ldm_partition,          /* this must come before msdos */
79 #endif
80 #ifdef CONFIG_NEC98_PARTITION
81         nec98_partition,        /* must be come before `msdos_partition' */
82 #endif
83 #ifdef CONFIG_MSDOS_PARTITION
84         msdos_partition,
85 #endif
86 #ifdef CONFIG_OSF_PARTITION
87         osf_partition,
88 #endif
89 #ifdef CONFIG_SUN_PARTITION
90         sun_partition,
91 #endif
92 #ifdef CONFIG_AMIGA_PARTITION
93         amiga_partition,
94 #endif
95 #ifdef CONFIG_ATARI_PARTITION
96         atari_partition,
97 #endif
98 #ifdef CONFIG_MAC_PARTITION
99         mac_partition,
100 #endif
101 #ifdef CONFIG_SGI_PARTITION
102         sgi_partition,
103 #endif
104 #ifdef CONFIG_ULTRIX_PARTITION
105         ultrix_partition,
106 #endif
107 #ifdef CONFIG_IBM_PARTITION
108         ibm_partition,
109 #endif
110         NULL
111 };
112  
113 /*
114  * disk_name() is used by partition check code and the genhd driver.
115  * It formats the devicename of the indicated disk into
116  * the supplied buffer (of size at least 32), and returns
117  * a pointer to that same buffer (for convenience).
118  */
119
120 char *disk_name(struct gendisk *hd, int part, char *buf)
121 {
122         if (!part)
123                 snprintf(buf, BDEVNAME_SIZE, "%s", hd->disk_name);
124         else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1]))
125                 snprintf(buf, BDEVNAME_SIZE, "%sp%d", hd->disk_name, part);
126         else
127                 snprintf(buf, BDEVNAME_SIZE, "%s%d", hd->disk_name, part);
128
129         return buf;
130 }
131
132 const char *bdevname(struct block_device *bdev, char *buf)
133 {
134         int part = MINOR(bdev->bd_dev) - bdev->bd_disk->first_minor;
135         return disk_name(bdev->bd_disk, part, buf);
136 }
137
138 EXPORT_SYMBOL(bdevname);
139
140 /*
141  * NOTE: this cannot be called from interrupt context.
142  *
143  * But in interrupt context you should really have a struct
144  * block_device anyway and use bdevname() above.
145  */
146 const char *__bdevname(dev_t dev, char *buffer)
147 {
148         struct gendisk *disk;
149         int part;
150
151         disk = get_gendisk(dev, &part);
152         if (disk) {
153                 buffer = disk_name(disk, part, buffer);
154                 put_disk(disk);
155         } else {
156                 snprintf(buffer, BDEVNAME_SIZE, "unknown-block(%u,%u)",
157                                 MAJOR(dev), MINOR(dev));
158         }
159
160         return buffer;
161 }
162
163 EXPORT_SYMBOL(__bdevname);
164
165 static struct parsed_partitions *
166 check_partition(struct gendisk *hd, struct block_device *bdev)
167 {
168         struct parsed_partitions *state;
169         int i, res;
170
171         state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL);
172         if (!state)
173                 return NULL;
174
175 #ifdef CONFIG_DEVFS_FS
176         if (hd->devfs_name[0] != '\0') {
177                 printk(KERN_INFO " /dev/%s:", hd->devfs_name);
178                 sprintf(state->name, "p");
179         }
180 #endif
181         else {
182                 disk_name(hd, 0, state->name);
183                 printk(KERN_INFO " %s:", state->name);
184                 if (isdigit(state->name[strlen(state->name)-1]))
185                         sprintf(state->name, "p");
186         }
187         state->limit = hd->minors;
188         i = res = 0;
189         while (!res && check_part[i]) {
190                 memset(&state->parts, 0, sizeof(state->parts));
191                 res = check_part[i++](state, bdev);
192         }
193         if (res > 0)
194                 return state;
195         if (!res)
196                 printk(" unknown partition table\n");
197         else if (warn_no_part)
198                 printk(" unable to read partition table\n");
199         kfree(state);
200         return NULL;
201 }
202
203 /*
204  * sysfs bindings for partitions
205  */
206
207 struct part_attribute {
208         struct attribute attr;
209         ssize_t (*show)(struct hd_struct *,char *);
210 };
211
212 static ssize_t 
213 part_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
214 {
215         struct hd_struct * p = container_of(kobj,struct hd_struct,kobj);
216         struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr);
217         ssize_t ret = 0;
218         if (part_attr->show)
219                 ret = part_attr->show(p,page);
220         return ret;
221 }
222
223 static struct sysfs_ops part_sysfs_ops = {
224         .show   =       part_attr_show,
225 };
226
227 static ssize_t part_dev_read(struct hd_struct * p, char *page)
228 {
229         struct gendisk *disk = container_of(p->kobj.parent,struct gendisk,kobj);
230         dev_t dev = MKDEV(disk->major, disk->first_minor + p->partno); 
231         return print_dev_t(page, dev);
232 }
233 static ssize_t part_start_read(struct hd_struct * p, char *page)
234 {
235         return sprintf(page, "%llu\n",(unsigned long long)p->start_sect);
236 }
237 static ssize_t part_size_read(struct hd_struct * p, char *page)
238 {
239         return sprintf(page, "%llu\n",(unsigned long long)p->nr_sects);
240 }
241 static ssize_t part_stat_read(struct hd_struct * p, char *page)
242 {
243         return sprintf(page, "%8u %8llu %8u %8llu\n",
244                        p->reads, (unsigned long long)p->read_sectors,
245                        p->writes, (unsigned long long)p->write_sectors);
246 }
247 static struct part_attribute part_attr_dev = {
248         .attr = {.name = "dev", .mode = S_IRUGO },
249         .show   = part_dev_read
250 };
251 static struct part_attribute part_attr_start = {
252         .attr = {.name = "start", .mode = S_IRUGO },
253         .show   = part_start_read
254 };
255 static struct part_attribute part_attr_size = {
256         .attr = {.name = "size", .mode = S_IRUGO },
257         .show   = part_size_read
258 };
259 static struct part_attribute part_attr_stat = {
260         .attr = {.name = "stat", .mode = S_IRUGO },
261         .show   = part_stat_read
262 };
263
264 static struct attribute * default_attrs[] = {
265         &part_attr_dev.attr,
266         &part_attr_start.attr,
267         &part_attr_size.attr,
268         &part_attr_stat.attr,
269         NULL,
270 };
271
272 extern struct subsystem block_subsys;
273
274 static void part_release(struct kobject *kobj)
275 {
276         struct hd_struct * p = container_of(kobj,struct hd_struct,kobj);
277         kfree(p);
278 }
279
280 struct kobj_type ktype_part = {
281         .release        = part_release,
282         .default_attrs  = default_attrs,
283         .sysfs_ops      = &part_sysfs_ops,
284 };
285
286 void delete_partition(struct gendisk *disk, int part)
287 {
288         struct hd_struct *p = disk->part[part-1];
289         if (!p)
290                 return;
291         if (!p->nr_sects)
292                 return;
293         disk->part[part-1] = NULL;
294         p->start_sect = 0;
295         p->nr_sects = 0;
296         p->reads = p->writes = p->read_sectors = p->write_sectors = 0;
297         devfs_remove("%s/part%d", disk->devfs_name, part);
298         kobject_unregister(&p->kobj);
299 }
300
301 void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
302 {
303         struct hd_struct *p;
304
305         p = kmalloc(sizeof(*p), GFP_KERNEL);
306         if (!p)
307                 return;
308         
309         memset(p, 0, sizeof(*p));
310         p->start_sect = start;
311         p->nr_sects = len;
312         p->partno = part;
313
314         devfs_mk_bdev(MKDEV(disk->major, disk->first_minor + part),
315                         S_IFBLK|S_IRUSR|S_IWUSR,
316                         "%s/part%d", disk->devfs_name, part);
317
318         if (isdigit(disk->kobj.name[strlen(disk->kobj.name)-1]))
319                 snprintf(p->kobj.name,KOBJ_NAME_LEN,"%sp%d",disk->kobj.name,part);
320         else
321                 snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part);
322         p->kobj.parent = &disk->kobj;
323         p->kobj.ktype = &ktype_part;
324         kobject_register(&p->kobj);
325         disk->part[part-1] = p;
326 }
327
328 static void disk_sysfs_symlinks(struct gendisk *disk)
329 {
330         struct device *target = get_device(disk->driverfs_dev);
331         if (target) {
332                 sysfs_create_link(&disk->kobj,&target->kobj,"device");
333                 sysfs_create_link(&target->kobj,&disk->kobj,"block");
334         }
335 }
336
337 /* Not exported, helper to add_disk(). */
338 void register_disk(struct gendisk *disk)
339 {
340         struct parsed_partitions *state;
341         struct block_device *bdev;
342         char *s;
343         int j;
344         int err;
345
346         strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN);
347         /* ewww... some of these buggers have / in name... */
348         s = strchr(disk->kobj.name, '/');
349         if (s)
350                 *s = '!';
351         if ((err = kobject_add(&disk->kobj)))
352                 return;
353         disk_sysfs_symlinks(disk);
354
355         /* No minors to use for partitions */
356         if (disk->minors == 1) {
357                 if (disk->devfs_name[0] != '\0')
358                         devfs_add_disk(disk);
359                 return;
360         }
361
362         /* always add handle for the whole disk */
363         devfs_add_partitioned(disk);
364
365         /* No such device (e.g., media were just removed) */
366         if (!get_capacity(disk))
367                 return;
368
369         bdev = bdget_disk(disk, 0);
370         if (!bdev)
371                 return;
372
373         if (blkdev_get(bdev, FMODE_READ, 0) < 0)
374                 return;
375         state = check_partition(disk, bdev);
376         if (state) {
377                 for (j = 1; j < state->limit; j++) {
378                         sector_t size = state->parts[j].size;
379                         sector_t from = state->parts[j].from;
380                         if (!size)
381                                 continue;
382                         add_partition(disk, j, from, size);
383 #ifdef CONFIG_BLK_DEV_MD
384                         if (!state->parts[j].flags)
385                                 continue;
386                         md_autodetect_dev(bdev->bd_dev+j);
387 #endif
388                 }
389                 kfree(state);
390         }
391         blkdev_put(bdev);
392 }
393
394 int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
395 {
396         struct parsed_partitions *state;
397         int p, res;
398
399         if (bdev->bd_part_count)
400                 return -EBUSY;
401         res = invalidate_partition(disk, 0);
402         if (res)
403                 return res;
404         bdev->bd_invalidated = 0;
405         for (p = 1; p < disk->minors; p++)
406                 delete_partition(disk, p);
407         if (disk->fops->revalidate_disk)
408                 disk->fops->revalidate_disk(disk);
409         if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
410                 return res;
411         for (p = 1; p < state->limit; p++) {
412                 sector_t size = state->parts[p].size;
413                 sector_t from = state->parts[p].from;
414                 if (!size)
415                         continue;
416                 add_partition(disk, p, from, size);
417 #ifdef CONFIG_BLK_DEV_MD
418                 if (state->parts[p].flags)
419                         md_autodetect_dev(bdev->bd_dev+p);
420 #endif
421         }
422         kfree(state);
423         return res;
424 }
425
426 unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
427 {
428         struct address_space *mapping = bdev->bd_inode->i_mapping;
429         struct page *page;
430
431         page = read_cache_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)),
432                         (filler_t *)mapping->a_ops->readpage, NULL);
433         if (!IS_ERR(page)) {
434                 wait_on_page_locked(page);
435                 if (!PageUptodate(page))
436                         goto fail;
437                 if (PageError(page))
438                         goto fail;
439                 p->v = page;
440                 return (unsigned char *)page_address(page) +  ((n & ((1 << (PAGE_CACHE_SHIFT - 9)) - 1)) << 9);
441 fail:
442                 page_cache_release(page);
443         }
444         p->v = NULL;
445         return NULL;
446 }
447
448 EXPORT_SYMBOL(read_dev_sector);
449
450 void del_gendisk(struct gendisk *disk)
451 {
452         int p;
453
454         /* invalidate stuff */
455         for (p = disk->minors - 1; p > 0; p--) {
456                 invalidate_partition(disk, p);
457                 delete_partition(disk, p);
458         }
459         invalidate_partition(disk, 0);
460         disk->capacity = 0;
461         disk->flags &= ~GENHD_FL_UP;
462         unlink_gendisk(disk);
463         disk_stat_set_all(disk, 0);
464         disk->stamp = disk->stamp_idle = 0;
465
466         devfs_remove_disk(disk);
467
468         if (disk->driverfs_dev) {
469                 sysfs_remove_link(&disk->kobj, "device");
470                 sysfs_remove_link(&disk->driverfs_dev->kobj, "block");
471                 put_device(disk->driverfs_dev);
472         }
473         kobject_del(&disk->kobj);
474 }