Root/init/do_mounts_md.c

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

Archive Download this file



interactive