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