LCOV - code coverage report
Current view: top level - init - do_mounts_md.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 22 166 13.3 %
Date: 2022-04-01 14:58:12 Functions: 3 5 60.0 %
Branches: 3 84 3.6 %

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

Generated by: LCOV version 1.14