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