linux/init/do_mounts_md.c
<<
>>
Prefs
   1/*
   2 * Many of the syscalls used in this file expect some of the arguments
   3 * to be __user pointers not __kernel pointers.  To limit the sparse
   4 * noise, turn off sparse checking for this file.
   5 */
   6#ifdef __CHECKER__
   7#undef __CHECKER__
   8#warning "Sparse checking disabled for this file"
   9#endif
  10
  11#include <linux/delay.h>
  12#include <linux/raid/md_u.h>
  13#include <linux/raid/md_p.h>
  14
  15#include "do_mounts.h"
  16
  17/*
  18 * When md (and any require personalities) are compiled into the kernel
  19 * (not a module), arrays can be assembles are boot time using with AUTODETECT
  20 * where specially marked partitions are registered with md_autodetect_dev(),
  21 * and with MD_BOOT where devices to be collected are given on the boot line
  22 * with md=.....
  23 * The code for that is here.
  24 */
  25
  26#ifdef CONFIG_MD_AUTODETECT
  27static int __initdata raid_noautodetect;
  28#else
  29static int __initdata raid_noautodetect=1;
  30#endif
  31static int __initdata raid_autopart;
  32
  33static struct {
  34        int minor;
  35        int partitioned;
  36        int level;
  37        int chunk;
  38        char *device_names;
  39} md_setup_args[256] __initdata;
  40
  41static int md_setup_ents __initdata;
  42
  43/*
  44 * Parse the command-line parameters given our kernel, but do not
  45 * actually try to invoke the MD device now; that is handled by
  46 * md_setup_drive after the low-level disk drivers have initialised.
  47 *
  48 * 27/11/1999: Fixed to work correctly with the 2.3 kernel (which
  49 *             assigns the task of parsing integer arguments to the
  50 *             invoked program now).  Added ability to initialise all
  51 *             the MD devices (by specifying multiple "md=" lines)
  52 *             instead of just one.  -- KTK
  53 * 18May2000: Added support for persistent-superblock arrays:
  54 *             md=n,0,factor,fault,device-list   uses RAID0 for device n
  55 *             md=n,-1,factor,fault,device-list  uses LINEAR for device n
  56 *             md=n,device-list      reads a RAID superblock from the devices
  57 *             elements in device-list are read by name_to_kdev_t so can be
  58 *             a hex number or something like /dev/hda1 /dev/sdb
  59 * 2001-06-03: Dave Cinege <dcinege@psychosis.com>
  60 *              Shifted name_to_kdev_t() and related operations to md_set_drive()
  61 *              for later execution. Rewrote section to make devfs compatible.
  62 */
  63static int __init md_setup(char *str)
  64{
  65        int minor, level, factor, fault, partitioned = 0;
  66        char *pername = "";
  67        char *str1;
  68        int ent;
  69
  70        if (*str == 'd') {
  71                partitioned = 1;
  72                str++;
  73        }
  74        if (get_option(&str, &minor) != 2) {    /* MD Number */
  75                printk(KERN_WARNING "md: Too few arguments supplied to md=.\n");
  76                return 0;
  77        }
  78        str1 = str;
  79        for (ent=0 ; ent< md_setup_ents ; ent++)
  80                if (md_setup_args[ent].minor == minor &&
  81                    md_setup_args[ent].partitioned == partitioned) {
  82                        printk(KERN_WARNING "md: md=%s%d, Specified more than once. "
  83                               "Replacing previous definition.\n", partitioned?"d":"", minor);
  84                        break;
  85                }
  86        if (ent >= ARRAY_SIZE(md_setup_args)) {
  87                printk(KERN_WARNING "md: md=%s%d - too many md initialisations\n", partitioned?"d":"", minor);
  88                return 0;
  89        }
  90        if (ent >= md_setup_ents)
  91                md_setup_ents++;
  92        switch (get_option(&str, &level)) {     /* RAID level */
  93        case 2: /* could be 0 or -1.. */
  94                if (level == 0 || level == LEVEL_LINEAR) {
  95                        if (get_option(&str, &factor) != 2 ||   /* Chunk Size */
  96                                        get_option(&str, &fault) != 2) {
  97                                printk(KERN_WARNING "md: Too few arguments supplied to md=.\n");
  98                                return 0;
  99                        }
 100                        md_setup_args[ent].level = level;
 101                        md_setup_args[ent].chunk = 1 << (factor+12);
 102                        if (level ==  LEVEL_LINEAR)
 103                                pername = "linear";
 104                        else
 105                                pername = "raid0";
 106                        break;
 107                }
 108                /* FALL THROUGH */
 109        case 1: /* the first device is numeric */
 110                str = str1;
 111                /* FALL THROUGH */
 112        case 0:
 113                md_setup_args[ent].level = LEVEL_NONE;
 114                pername="super-block";
 115        }
 116
 117        printk(KERN_INFO "md: Will configure md%d (%s) from %s, below.\n",
 118                minor, pername, str);
 119        md_setup_args[ent].device_names = str;
 120        md_setup_args[ent].partitioned = partitioned;
 121        md_setup_args[ent].minor = minor;
 122
 123        return 1;
 124}
 125
 126static void __init md_setup_drive(void)
 127{
 128        int minor, i, ent, partitioned;
 129        dev_t dev;
 130        dev_t devices[MD_SB_DISKS+1];
 131
 132        for (ent = 0; ent < md_setup_ents ; ent++) {
 133                int fd;
 134                int err = 0;
 135                char *devname;
 136                mdu_disk_info_t dinfo;
 137                char name[16];
 138
 139                minor = md_setup_args[ent].minor;
 140                partitioned = md_setup_args[ent].partitioned;
 141                devname = md_setup_args[ent].device_names;
 142
 143                sprintf(name, "/dev/md%s%d", partitioned?"_d":"", minor);
 144                if (partitioned)
 145                        dev = MKDEV(mdp_major, minor << MdpMinorShift);
 146                else
 147                        dev = MKDEV(MD_MAJOR, minor);
 148                create_dev(name, dev);
 149                for (i = 0; i < MD_SB_DISKS && devname != NULL; i++) {
 150                        char *p;
 151                        char comp_name[64];
 152                        u32 rdev;
 153
 154                        p = strchr(devname, ',');
 155                        if (p)
 156                                *p++ = 0;
 157
 158                        dev = name_to_dev_t(devname);
 159                        if (strncmp(devname, "/dev/", 5) == 0)
 160                                devname += 5;
 161                        snprintf(comp_name, 63, "/dev/%s", devname);
 162                        rdev = bstat(comp_name);
 163                        if (rdev)
 164                                dev = new_decode_dev(rdev);
 165                        if (!dev) {
 166                                printk(KERN_WARNING "md: Unknown device name: %s\n", devname);
 167                                break;
 168                        }
 169
 170                        devices[i] = dev;
 171
 172                        devname = p;
 173                }
 174                devices[i] = 0;
 175
 176                if (!i)
 177                        continue;
 178
 179                printk(KERN_INFO "md: Loading md%s%d: %s\n",
 180                        partitioned ? "_d" : "", minor,
 181                        md_setup_args[ent].device_names);
 182
 183                fd = sys_open(name, 0, 0);
 184                if (fd < 0) {
 185                        printk(KERN_ERR "md: open failed - cannot start "
 186                                        "array %s\n", name);
 187                        continue;
 188                }
 189                if (sys_ioctl(fd, SET_ARRAY_INFO, 0) == -EBUSY) {
 190                        printk(KERN_WARNING
 191                               "md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n",
 192                               minor);
 193                        sys_close(fd);
 194                        continue;
 195                }
 196
 197                if (md_setup_args[ent].level != LEVEL_NONE) {
 198                        /* non-persistent */
 199                        mdu_array_info_t ainfo;
 200                        ainfo.level = md_setup_args[ent].level;
 201                        ainfo.size = 0;
 202                        ainfo.nr_disks =0;
 203                        ainfo.raid_disks =0;
 204                        while (devices[ainfo.raid_disks])
 205                                ainfo.raid_disks++;
 206                        ainfo.md_minor =minor;
 207                        ainfo.not_persistent = 1;
 208
 209                        ainfo.state = (1 << MD_SB_CLEAN);
 210                        ainfo.layout = 0;
 211                        ainfo.chunk_size = md_setup_args[ent].chunk;
 212                        err = sys_ioctl(fd, SET_ARRAY_INFO, (long)&ainfo);
 213                        for (i = 0; !err && i <= MD_SB_DISKS; i++) {
 214                                dev = devices[i];
 215                                if (!dev)
 216                                        break;
 217                                dinfo.number = i;
 218                                dinfo.raid_disk = i;
 219                                dinfo.state = (1<<MD_DISK_ACTIVE)|(1<<MD_DISK_SYNC);
 220                                dinfo.major = MAJOR(dev);
 221                                dinfo.minor = MINOR(dev);
 222                                err = sys_ioctl(fd, ADD_NEW_DISK, (long)&dinfo);
 223                        }
 224                } else {
 225                        /* persistent */
 226                        for (i = 0; i <= MD_SB_DISKS; i++) {
 227                                dev = devices[i];
 228                                if (!dev)
 229                                        break;
 230                                dinfo.major = MAJOR(dev);
 231                                dinfo.minor = MINOR(dev);
 232                                sys_ioctl(fd, ADD_NEW_DISK, (long)&dinfo);
 233                        }
 234                }
 235                if (!err)
 236                        err = sys_ioctl(fd, RUN_ARRAY, 0);
 237                if (err)
 238                        printk(KERN_WARNING "md: starting md%d failed\n", minor);
 239                else {
 240                        /* reread the partition table.
 241                         * I (neilb) and not sure why this is needed, but I cannot
 242                         * boot a kernel with devfs compiled in from partitioned md
 243                         * array without it
 244                         */
 245                        sys_close(fd);
 246                        fd = sys_open(name, 0, 0);
 247                        sys_ioctl(fd, BLKRRPART, 0);
 248                }
 249                sys_close(fd);
 250        }
 251}
 252
 253static int __init raid_setup(char *str)
 254{
 255        int len, pos;
 256
 257        len = strlen(str) + 1;
 258        pos = 0;
 259
 260        while (pos < len) {
 261                char *comma = strchr(str+pos, ',');
 262                int wlen;
 263                if (comma)
 264                        wlen = (comma-str)-pos;
 265                else    wlen = (len-1)-pos;
 266
 267                if (!strncmp(str, "noautodetect", wlen))
 268                        raid_noautodetect = 1;
 269                if (!strncmp(str, "autodetect", wlen))
 270                        raid_noautodetect = 0;
 271                if (strncmp(str, "partitionable", wlen)==0)
 272                        raid_autopart = 1;
 273                if (strncmp(str, "part", wlen)==0)
 274                        raid_autopart = 1;
 275                pos += wlen+1;
 276        }
 277        return 1;
 278}
 279
 280__setup("raid=", raid_setup);
 281__setup("md=", md_setup);
 282
 283static void __init autodetect_raid(void)
 284{
 285        int fd;
 286
 287        /*
 288         * Since we don't want to detect and use half a raid array, we need to
 289         * wait for the known devices to complete their probing
 290         */
 291        printk(KERN_INFO "md: Waiting for all devices to be available before autodetect\n");
 292        printk(KERN_INFO "md: If you don't use raid, use raid=noautodetect\n");
 293
 294        wait_for_device_probe();
 295
 296        fd = sys_open("/dev/md0", 0, 0);
 297        if (fd >= 0) {
 298                sys_ioctl(fd, RAID_AUTORUN, raid_autopart);
 299                sys_close(fd);
 300        }
 301}
 302
 303void __init md_run_setup(void)
 304{
 305        create_dev("/dev/md0", MKDEV(MD_MAJOR, 0));
 306
 307        if (raid_noautodetect)
 308                printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=autodetect will force)\n");
 309        else
 310                autodetect_raid();
 311        md_setup_drive();
 312}
 313
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.