OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [partitions/] [check.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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
#include "efi.h"
37
 
38
extern int *blk_size[];
39
 
40
int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
41
 
42
static 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,          /* this must come before msdos */
51
#endif
52
#ifdef CONFIG_LDM_PARTITION
53
        ldm_partition,          /* this must come before msdos */
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
 *      This is ucking fugly but its probably the best thing for 2.4.x
84
 *      Take it as a clear reminder that: 1) we should put the device name
85
 *      generation in the object kdev_t points to in 2.5.
86
 *      and 2) ioctls better work on half-opened devices.
87
 */
88
 
89
#ifdef CONFIG_ARCH_S390
90
int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
91
int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
92
                            unsigned int no, unsigned long data);
93
EXPORT_SYMBOL(genhd_dasd_name);
94
EXPORT_SYMBOL(genhd_dasd_ioctl);
95
#endif
96
 
97
/*
98
 * disk_name() is used by partition check code and the md driver.
99
 * It formats the devicename of the indicated disk into
100
 * the supplied buffer (of size at least 32), and returns
101
 * a pointer to that same buffer (for convenience).
102
 */
103
 
104
char *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
         * IDE devices use multiple major numbers, but the drives
125
         * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
126
         * This requires special handling here.
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
 * Add a partitions details to the devices partition description.
206
 */
207
void 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
 
226
static 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
         * This is a kludge to allow the partition check to be
242
         * skipped for specific drives (e.g. IDE CD-ROM drives)
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");
270
setup_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
279
static 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
 
299
static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
300
 
301
static 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)  /*  Aware driver wants to block disc management  */
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
                /*  Unaware driver: construct "real" directory  */
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  /*  CONFIG_DEVFS_FS  */
340
 
341
void 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  /*  CONFIG_DEVFS_FS  */
364
}
365
 
366
/*
367
 * This function will re-read the partition tables for a given device,
368
 * and set things back up again.  There are some important caveats,
369
 * however.  You must ensure that no one is using the device, and no one
370
 * can start using the device while this function is being executed.
371
 *
372
 * Much of the cleanup from the old partition tables should have already been
373
 * done
374
 */
375
 
376
void 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
 
384
void 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
        /* No such device or no minors to use for partitions */
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
         * We need to set the sizes array before we will be able to access
410
         * any of the partitions on this device.
411
         */
412
        if (dev->sizes != NULL) {       /* optional safeguard in ll_rw_blk.c */
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
 
418
unsigned 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);
434
fail:
435
                page_cache_release(page);
436
        }
437
        p->v = NULL;
438
        return NULL;
439
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.