md-autodetect.c (7733B)
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}