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