Merge lp:~xnox/ubuntu/quantal/mdadm/merge into lp:~xnox/ubuntu/quantal/mdadm/quantal
- Quantal (12.10)
- merge
- Merge into quantal
Proposed by
Dimitri John Ledkov
Status: | Merged | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merge reported by: | Dimitri John Ledkov | ||||||||||||||||||||||||||||
Merged at revision: | not available | ||||||||||||||||||||||||||||
Proposed branch: | lp:~xnox/ubuntu/quantal/mdadm/merge | ||||||||||||||||||||||||||||
Merge into: | lp:~xnox/ubuntu/quantal/mdadm/quantal | ||||||||||||||||||||||||||||
Diff against target: |
24674 lines (+7902/-9243) 110 files modified
.pc/applied-patches (+0/-3) .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/Assemble.c (+0/-1650) .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/ReadMe.c (+0/-602) .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/config.c (+0/-1131) .pc/debian-conffile-location.diff/Makefile (+287/-0) .pc/debian-conffile-location.diff/ReadMe.c (+608/-0) .pc/debian-conffile-location.diff/mdadm.8.in (+2899/-0) .pc/debian-conffile-location.diff/mdadm.conf.5 (+581/-0) .pc/debian-conffile-location.diff/mdassemble.8 (+65/-0) .pc/debian-no-Werror.diff/Makefile (+287/-0) .pc/debian/conffile-location.diff/Makefile (+0/-286) .pc/debian/conffile-location.diff/ReadMe.c (+0/-602) .pc/debian/conffile-location.diff/mdadm.8.in (+0/-2880) .pc/debian/conffile-location.diff/mdadm.conf.5 (+0/-581) .pc/debian/conffile-location.diff/mdassemble.8 (+0/-65) .pc/debian/no-Werror.diff/Makefile (+0/-286) .pc/sha1-includes.diff/sha1.h (+141/-0) ANNOUNCE-3.2.4 (+144/-0) ANNOUNCE-3.2.5 (+31/-0) Assemble.c (+72/-23) Create.c (+14/-4) Detail.c (+8/-7) Grow.c (+288/-84) Incremental.c (+6/-8) Makefile (+7/-6) Manage.c (+94/-51) Monitor.c (+19/-12) ReadMe.c (+7/-1) check.d/_numbers (+0/-1) check.d/root_on_raid (+0/-35) config.c (+6/-6) debian/README.source (+0/-18) debian/changelog (+102/-0) debian/checkarray (+15/-0) debian/control (+1/-1) debian/initramfs/local-premount (+1/-0) debian/mdadm.logcheck.ignore.server (+1/-1) debian/patches/debian-conffile-location.diff (+126/-0) debian/patches/debian-disable-udev-incr-assembly.diff (+27/-0) debian/patches/debian-no-Werror.diff (+26/-0) debian/patches/debian/conffile-location.diff (+0/-128) debian/patches/debian/disable-udev-incr-assembly.diff (+0/-29) debian/patches/debian/no-Werror.diff (+0/-28) debian/patches/series (+4/-3) debian/patches/sha1-includes.diff (+45/-0) debian/po/ca.po (+7/-7) debian/po/cs.po (+7/-7) debian/po/da.po (+7/-7) debian/po/de.po (+7/-7) debian/po/es.po (+7/-7) debian/po/eu.po (+7/-7) debian/po/fi.po (+6/-6) debian/po/fr.po (+7/-7) debian/po/gl.po (+7/-7) debian/po/it.po (+7/-7) debian/po/ja.po (+7/-7) debian/po/nl.po (+7/-7) debian/po/pt.po (+7/-7) debian/po/pt_BR.po (+39/-7) debian/po/ru.po (+7/-7) debian/po/sk.po (+7/-7) debian/po/sv.po (+7/-7) debian/po/templates.pot (+2/-2) debian/po/vi.po (+7/-7) debian/rules (+7/-17) debian/source_mdadm.py (+5/-7) inventory (+28/-26) lib.c (+7/-2) makedist (+4/-2) managemon.c (+6/-0) mapfile.c (+6/-11) mdadm.8.in (+42/-23) mdadm.c (+24/-6) mdadm.conf-example (+1/-1) mdadm.conf.5 (+1/-1) mdadm.h (+38/-14) mdadm.spec (+2/-2) mdassemble.8 (+1/-1) mdmon.8 (+13/-3) mdmon.c (+48/-11) mdopen.c (+1/-1) monitor.c (+20/-16) msg.c (+10/-0) msg.h (+1/-0) platform-intel.h (+1/-0) sha1.c (+42/-49) sha1.h (+64/-12) super-ddf.c (+25/-16) super-intel.c (+1159/-189) super0.c (+18/-12) super1.c (+169/-102) sysfs.c (+13/-4) test (+6/-5) tests/00raid1 (+2/-2) tests/05r1-bitmapfile (+3/-3) tests/05r1-grow-external (+2/-2) tests/05r1-grow-internal (+2/-2) tests/05r1-grow-internal-1 (+2/-2) tests/05r1-internalbitmap (+3/-3) tests/05r1-internalbitmap-v1a (+3/-3) tests/05r1-internalbitmap-v1b (+3/-3) tests/05r1-internalbitmap-v1c (+3/-3) tests/05r1-n3-bitmapfile (+3/-3) tests/05r1-re-add (+2/-2) tests/06wrmostly (+2/-2) tests/07autoassemble (+4/-4) tests/09imsm-assemble (+3/-3) tests/09imsm-create-fail-rebuild (+1/-1) tests/10ddf-create (+1/-1) util.c (+30/-12) |
||||||||||||||||||||||||||||
To merge this branch: | bzr merge lp:~xnox/ubuntu/quantal/mdadm/merge | ||||||||||||||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Dimitri John Ledkov | Pending | ||
Review via email:
|
Commit message
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file '.pc/applied-patches' |
2 | --- .pc/applied-patches 1970-01-01 00:00:00 +0000 |
3 | +++ .pc/applied-patches 2012-06-18 08:55:05 +0000 |
4 | @@ -0,0 +1,4 @@ |
5 | +debian-conffile-location.diff |
6 | +debian-no-Werror.diff |
7 | +debian-changes-3.1.4-1+8efb9d1ubuntu4 |
8 | +sha1-includes.diff |
9 | |
10 | === removed file '.pc/applied-patches' |
11 | --- .pc/applied-patches 2012-05-22 16:40:37 +0000 |
12 | +++ .pc/applied-patches 1970-01-01 00:00:00 +0000 |
13 | @@ -1,3 +0,0 @@ |
14 | -debian/conffile-location.diff |
15 | -debian/no-Werror.diff |
16 | -debian-changes-3.1.4-1+8efb9d1ubuntu4 |
17 | |
18 | === removed directory '.pc/debian' |
19 | === added directory '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4' |
20 | === removed directory '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4' |
21 | === added file '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/Assemble.c' |
22 | --- .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/Assemble.c 1970-01-01 00:00:00 +0000 |
23 | +++ .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/Assemble.c 2012-06-18 08:55:05 +0000 |
24 | @@ -0,0 +1,1699 @@ |
25 | +/* |
26 | + * mdadm - manage Linux "md" devices aka RAID arrays. |
27 | + * |
28 | + * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de> |
29 | + * |
30 | + * |
31 | + * This program is free software; you can redistribute it and/or modify |
32 | + * it under the terms of the GNU General Public License as published by |
33 | + * the Free Software Foundation; either version 2 of the License, or |
34 | + * (at your option) any later version. |
35 | + * |
36 | + * This program is distributed in the hope that it will be useful, |
37 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
38 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
39 | + * GNU General Public License for more details. |
40 | + * |
41 | + * You should have received a copy of the GNU General Public License |
42 | + * along with this program; if not, write to the Free Software |
43 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
44 | + * |
45 | + * Author: Neil Brown |
46 | + * Email: <neilb@suse.de> |
47 | + */ |
48 | + |
49 | +#include "mdadm.h" |
50 | +#include <ctype.h> |
51 | + |
52 | +static int name_matches(char *found, char *required, char *homehost) |
53 | +{ |
54 | + /* See if the name found matches the required name, possibly |
55 | + * prefixed with 'homehost' |
56 | + */ |
57 | + char fnd[33]; |
58 | + |
59 | + strncpy(fnd, found, 32); |
60 | + fnd[32] = 0; |
61 | + if (strcmp(found, required)==0) |
62 | + return 1; |
63 | + if (homehost) { |
64 | + int l = strlen(homehost); |
65 | + if (l < 32 && fnd[l] == ':' && |
66 | + strcmp(fnd+l+1, required)==0) |
67 | + return 1; |
68 | + } |
69 | + return 0; |
70 | +} |
71 | + |
72 | +static int is_member_busy(char *metadata_version) |
73 | +{ |
74 | + /* check if the given member array is active */ |
75 | + struct mdstat_ent *mdstat = mdstat_read(1, 0); |
76 | + struct mdstat_ent *ent; |
77 | + int busy = 0; |
78 | + |
79 | + for (ent = mdstat; ent; ent = ent->next) { |
80 | + if (ent->metadata_version == NULL) |
81 | + continue; |
82 | + if (strncmp(ent->metadata_version, "external:", 9) != 0) |
83 | + continue; |
84 | + if (!is_subarray(&ent->metadata_version[9])) |
85 | + continue; |
86 | + /* Skip first char - it can be '/' or '-' */ |
87 | + if (strcmp(&ent->metadata_version[10], metadata_version+1) == 0) { |
88 | + busy = 1; |
89 | + break; |
90 | + } |
91 | + } |
92 | + free_mdstat(mdstat); |
93 | + |
94 | + return busy; |
95 | +} |
96 | + |
97 | +static int ident_matches(struct mddev_ident *ident, |
98 | + struct mdinfo *content, |
99 | + struct supertype *tst, |
100 | + char *homehost, |
101 | + char *update, char *devname) |
102 | +{ |
103 | + |
104 | + if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) && |
105 | + same_uuid(content->uuid, ident->uuid, tst->ss->swapuuid)==0 && |
106 | + memcmp(content->uuid, uuid_zero, sizeof(int[4])) != 0) { |
107 | + if (devname) |
108 | + fprintf(stderr, Name ": %s has wrong uuid.\n", |
109 | + devname); |
110 | + return 0; |
111 | + } |
112 | + if (ident->name[0] && (!update || strcmp(update, "name")!= 0) && |
113 | + name_matches(content->name, ident->name, homehost)==0) { |
114 | + if (devname) |
115 | + fprintf(stderr, Name ": %s has wrong name.\n", |
116 | + devname); |
117 | + return 0; |
118 | + } |
119 | + if (ident->super_minor != UnSet && |
120 | + ident->super_minor != content->array.md_minor) { |
121 | + if (devname) |
122 | + fprintf(stderr, Name ": %s has wrong super-minor.\n", |
123 | + devname); |
124 | + return 0; |
125 | + } |
126 | + if (ident->level != UnSet && |
127 | + ident->level != content->array.level) { |
128 | + if (devname) |
129 | + fprintf(stderr, Name ": %s has wrong raid level.\n", |
130 | + devname); |
131 | + return 0; |
132 | + } |
133 | + if (ident->raid_disks != UnSet && |
134 | + ident->raid_disks!= content->array.raid_disks) { |
135 | + if (devname) |
136 | + fprintf(stderr, Name ": %s requires wrong number of drives.\n", |
137 | + devname); |
138 | + return 0; |
139 | + } |
140 | + if (ident->member && ident->member[0]) { |
141 | + /* content->text_version must match */ |
142 | + char *s = strchr(content->text_version+1, '/'); |
143 | + if (s == NULL) { |
144 | + if (devname) |
145 | + fprintf(stderr, Name ": %s is not a container and one is required.\n", |
146 | + devname); |
147 | + return 0; |
148 | + } else if (strcmp(ident->member, s+1) != 0) { |
149 | + if (devname) |
150 | + fprintf(stderr, Name ": skipping wrong member %s is %s\n", |
151 | + content->text_version, devname); |
152 | + return 0; |
153 | + } |
154 | + } |
155 | + return 1; |
156 | +} |
157 | + |
158 | + |
159 | +int Assemble(struct supertype *st, char *mddev, |
160 | + struct mddev_ident *ident, |
161 | + struct mddev_dev *devlist, |
162 | + char *backup_file, int invalid_backup, |
163 | + int readonly, int runstop, |
164 | + char *update, char *homehost, int require_homehost, |
165 | + int verbose, int force, int freeze_reshape) |
166 | +{ |
167 | + /* |
168 | + * The task of Assemble is to find a collection of |
169 | + * devices that should (according to their superblocks) |
170 | + * form an array, and to give this collection to the MD driver. |
171 | + * In Linux-2.4 and later, this involves submitting a |
172 | + * SET_ARRAY_INFO ioctl with no arg - to prepare |
173 | + * the array - and then submit a number of |
174 | + * ADD_NEW_DISK ioctls to add disks into |
175 | + * the array. Finally RUN_ARRAY might |
176 | + * be submitted to start the array. |
177 | + * |
178 | + * Much of the work of Assemble is in finding and/or |
179 | + * checking the disks to make sure they look right. |
180 | + * |
181 | + * If mddev is not set, then scan must be set and we |
182 | + * read through the config file for dev+uuid mapping |
183 | + * We recurse, setting mddev, for each device that |
184 | + * - isn't running |
185 | + * - has a valid uuid (or any uuid if !uuidset) |
186 | + * |
187 | + * If mddev is set, we try to determine state of md. |
188 | + * check version - must be at least 0.90.0 |
189 | + * check kernel version. must be at least 2.4. |
190 | + * If not, we can possibly fall back on START_ARRAY |
191 | + * Try to GET_ARRAY_INFO. |
192 | + * If possible, give up |
193 | + * If not, try to STOP_ARRAY just to make sure |
194 | + * |
195 | + * If !uuidset and scan, look in conf-file for uuid |
196 | + * If not found, give up |
197 | + * If !devlist and scan and uuidset, get list of devs from conf-file |
198 | + * |
199 | + * For each device: |
200 | + * Check superblock - discard if bad |
201 | + * Check uuid (set if we don't have one) - discard if no match |
202 | + * Check superblock similarity if we have a superblock - discard if different |
203 | + * Record events, devicenum |
204 | + * This should give us a list of devices for the array |
205 | + * We should collect the most recent event number |
206 | + * |
207 | + * Count disks with recent enough event count |
208 | + * While force && !enough disks |
209 | + * Choose newest rejected disks, update event count |
210 | + * mark clean and rewrite superblock |
211 | + * If recent kernel: |
212 | + * SET_ARRAY_INFO |
213 | + * foreach device with recent events : ADD_NEW_DISK |
214 | + * if runstop == 1 || "enough" disks and runstop==0 -> RUN_ARRAY |
215 | + * If old kernel: |
216 | + * Check the device numbers in superblock are right |
217 | + * update superblock if any changes |
218 | + * START_ARRAY |
219 | + * |
220 | + */ |
221 | + int mdfd; |
222 | + int clean; |
223 | + int auto_assem = (mddev == NULL && !ident->uuid_set && |
224 | + ident->super_minor == UnSet && ident->name[0] == 0 |
225 | + && (ident->container == NULL || ident->member == NULL)); |
226 | + int old_linux = 0; |
227 | + int vers = vers; /* Keep gcc quite - it really is initialised */ |
228 | + struct { |
229 | + char *devname; |
230 | + int uptodate; /* set once we decide that this device is as |
231 | + * recent as everything else in the array. |
232 | + */ |
233 | + struct mdinfo i; |
234 | + } *devices; |
235 | + char *devmap; |
236 | + int *best = NULL; /* indexed by raid_disk */ |
237 | + int bestcnt = 0; |
238 | + int devcnt = 0; |
239 | + unsigned int okcnt, sparecnt, rebuilding_cnt; |
240 | + unsigned int req_cnt; |
241 | + int i; |
242 | + int most_recent = 0; |
243 | + int chosen_drive; |
244 | + int change = 0; |
245 | + int inargv = 0; |
246 | + int report_missmatch; |
247 | +#ifndef MDASSEMBLE |
248 | + int bitmap_done; |
249 | +#endif |
250 | + int start_partial_ok = (runstop >= 0) && |
251 | + (force || devlist==NULL || auto_assem); |
252 | + unsigned int num_devs; |
253 | + struct mddev_dev *tmpdev; |
254 | + struct mdinfo info; |
255 | + struct mdinfo *content = NULL; |
256 | + char *avail; |
257 | + int nextspare = 0; |
258 | + char *name = NULL; |
259 | + int trustworthy; |
260 | + char chosen_name[1024]; |
261 | + struct domainlist *domains = NULL; |
262 | + |
263 | + if (get_linux_version() < 2004000) |
264 | + old_linux = 1; |
265 | + |
266 | + /* |
267 | + * If any subdevs are listed, then any that don't |
268 | + * match ident are discarded. Remainder must all match and |
269 | + * become the array. |
270 | + * If no subdevs, then we scan all devices in the config file, but |
271 | + * there must be something in the identity |
272 | + */ |
273 | + |
274 | + if (!devlist && |
275 | + ident->uuid_set == 0 && |
276 | + (ident->super_minor < 0 || ident->super_minor == UnSet) && |
277 | + ident->name[0] == 0 && |
278 | + (ident->container == NULL || ident->member == NULL) && |
279 | + ident->devices == NULL) { |
280 | + fprintf(stderr, Name ": No identity information available for %s - cannot assemble.\n", |
281 | + mddev ? mddev : "further assembly"); |
282 | + return 1; |
283 | + } |
284 | + |
285 | + if (devlist == NULL) |
286 | + devlist = conf_get_devs(); |
287 | + else if (mddev) |
288 | + inargv = 1; |
289 | + |
290 | + report_missmatch = ((inargv && verbose >= 0) || verbose > 0); |
291 | + try_again: |
292 | + /* We come back here when doing auto-assembly and attempting some |
293 | + * set of devices failed. Those are now marked as ->used==2 and |
294 | + * we ignore them and try again |
295 | + */ |
296 | + |
297 | + tmpdev = devlist; num_devs = 0; |
298 | + while (tmpdev) { |
299 | + if (tmpdev->used) |
300 | + tmpdev->used = 2; |
301 | + else |
302 | + num_devs++; |
303 | + tmpdev = tmpdev->next; |
304 | + } |
305 | + |
306 | + if (!st && ident->st) st = ident->st; |
307 | + |
308 | + if (verbose>0) |
309 | + fprintf(stderr, Name ": looking for devices for %s\n", |
310 | + mddev ? mddev : "further assembly"); |
311 | + |
312 | + /* first walk the list of devices to find a consistent set |
313 | + * that match the criterea, if that is possible. |
314 | + * We flag the ones we like with 'used'. |
315 | + */ |
316 | + for (tmpdev = devlist; |
317 | + tmpdev; |
318 | + tmpdev = tmpdev ? tmpdev->next : NULL) { |
319 | + char *devname = tmpdev->devname; |
320 | + int dfd; |
321 | + struct stat stb; |
322 | + struct supertype *tst; |
323 | + struct dev_policy *pol = NULL; |
324 | + int found_container = 0; |
325 | + |
326 | + if (tmpdev->used > 1) continue; |
327 | + |
328 | + if (ident->devices && |
329 | + !match_oneof(ident->devices, devname)) { |
330 | + if (report_missmatch) |
331 | + fprintf(stderr, Name ": %s is not one of %s\n", devname, ident->devices); |
332 | + continue; |
333 | + } |
334 | + |
335 | + tst = dup_super(st); |
336 | + |
337 | + dfd = dev_open(devname, O_RDONLY); |
338 | + if (dfd < 0) { |
339 | + if (report_missmatch) |
340 | + fprintf(stderr, Name ": cannot open device %s: %s\n", |
341 | + devname, strerror(errno)); |
342 | + tmpdev->used = 2; |
343 | + } else if (fstat(dfd, &stb)< 0) { |
344 | + /* Impossible! */ |
345 | + fprintf(stderr, Name ": fstat failed for %s: %s\n", |
346 | + devname, strerror(errno)); |
347 | + tmpdev->used = 2; |
348 | + } else if ((stb.st_mode & S_IFMT) != S_IFBLK) { |
349 | + fprintf(stderr, Name ": %s is not a block device.\n", |
350 | + devname); |
351 | + tmpdev->used = 2; |
352 | + } else if (must_be_container(dfd)) { |
353 | + if (st) { |
354 | + /* already found some components, this cannot |
355 | + * be another one. |
356 | + */ |
357 | + if (report_missmatch) |
358 | + fprintf(stderr, Name ": %s is a container, but we are looking for components\n", |
359 | + devname); |
360 | + tmpdev->used = 2; |
361 | +#if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) |
362 | + } if (!tst && (tst = super_by_fd(dfd, NULL)) == NULL) { |
363 | + if (report_missmatch) |
364 | + fprintf(stderr, Name ": not a recognisable container: %s\n", |
365 | + devname); |
366 | + tmpdev->used = 2; |
367 | +#endif |
368 | + } else if (!tst->ss->load_container |
369 | + || tst->ss->load_container(tst, dfd, NULL)) { |
370 | + if (report_missmatch) |
371 | + fprintf(stderr, Name ": no correct container type: %s\n", |
372 | + devname); |
373 | + tmpdev->used = 2; |
374 | + } else if (auto_assem && |
375 | + !conf_test_metadata(tst->ss->name, (pol = devnum_policy(stb.st_rdev)), |
376 | + tst->ss->match_home(tst, homehost) == 1)) { |
377 | + if (report_missmatch) |
378 | + fprintf(stderr, Name ": %s has metadata type %s for which " |
379 | + "auto-assembly is disabled\n", |
380 | + devname, tst->ss->name); |
381 | + tmpdev->used = 2; |
382 | + } else |
383 | + found_container = 1; |
384 | + } else { |
385 | + if (!tst && (tst = guess_super(dfd)) == NULL) { |
386 | + if (report_missmatch) |
387 | + fprintf(stderr, Name ": no recogniseable superblock on %s\n", |
388 | + devname); |
389 | + tmpdev->used = 2; |
390 | + } else if (tst->ss->load_super(tst,dfd, NULL)) { |
391 | + if (report_missmatch) |
392 | + fprintf(stderr, Name ": no RAID superblock on %s\n", |
393 | + devname); |
394 | + tmpdev->used = 2; |
395 | + } else if (tst->ss->compare_super == NULL) { |
396 | + if (report_missmatch) |
397 | + fprintf(stderr, Name ": Cannot assemble %s metadata on %s\n", |
398 | + tst->ss->name, devname); |
399 | + tmpdev->used = 2; |
400 | + } else if (auto_assem && st == NULL && |
401 | + !conf_test_metadata(tst->ss->name, (pol = devnum_policy(stb.st_rdev)), |
402 | + tst->ss->match_home(tst, homehost) == 1)) { |
403 | + if (report_missmatch) |
404 | + fprintf(stderr, Name ": %s has metadata type %s for which " |
405 | + "auto-assembly is disabled\n", |
406 | + devname, tst->ss->name); |
407 | + tmpdev->used = 2; |
408 | + } |
409 | + } |
410 | + if (dfd >= 0) close(dfd); |
411 | + if (tmpdev->used == 2) { |
412 | + if (auto_assem || !inargv) |
413 | + /* Ignore unrecognised devices during auto-assembly */ |
414 | + goto loop; |
415 | + if (ident->uuid_set || ident->name[0] || |
416 | + ident->super_minor != UnSet) |
417 | + /* Ignore unrecognised device if looking for |
418 | + * specific array */ |
419 | + goto loop; |
420 | + |
421 | + |
422 | + fprintf(stderr, Name ": %s has no superblock - assembly aborted\n", |
423 | + devname); |
424 | + if (st) |
425 | + st->ss->free_super(st); |
426 | + dev_policy_free(pol); |
427 | + domain_free(domains); |
428 | + return 1; |
429 | + } |
430 | + |
431 | + if (found_container) { |
432 | + /* tmpdev is a container. We need to be either |
433 | + * looking for a member, or auto-assembling |
434 | + */ |
435 | + /* should be safe to try an exclusive open now, we |
436 | + * have rejected anything that some other mdadm might |
437 | + * be looking at |
438 | + */ |
439 | + dfd = dev_open(devname, O_RDONLY | O_EXCL); |
440 | + if (dfd < 0) { |
441 | + if (report_missmatch) |
442 | + fprintf(stderr, Name ": %s is busy - skipping\n", devname); |
443 | + goto loop; |
444 | + } |
445 | + close(dfd); |
446 | + |
447 | + if (ident->container) { |
448 | + if (ident->container[0] == '/' && |
449 | + !same_dev(ident->container, devname)) { |
450 | + if (report_missmatch) |
451 | + fprintf(stderr, Name ": %s is not the container required (%s)\n", |
452 | + devname, ident->container); |
453 | + goto loop; |
454 | + } |
455 | + if (ident->container[0] != '/') { |
456 | + /* we have a uuid */ |
457 | + int uuid[4]; |
458 | + |
459 | + content = &info; |
460 | + tst->ss->getinfo_super(tst, content, NULL); |
461 | + |
462 | + if (!parse_uuid(ident->container, uuid) || |
463 | + !same_uuid(content->uuid, uuid, tst->ss->swapuuid)) { |
464 | + if (report_missmatch) |
465 | + fprintf(stderr, Name ": %s has wrong UUID to be required container\n", |
466 | + devname); |
467 | + goto loop; |
468 | + } |
469 | + } |
470 | + } |
471 | + /* It is worth looking inside this container. |
472 | + */ |
473 | + if (verbose > 0) |
474 | + fprintf(stderr, Name ": looking in container %s\n", |
475 | + devname); |
476 | + |
477 | + for (content = tst->ss->container_content(tst, NULL); |
478 | + content; |
479 | + content = content->next) { |
480 | + |
481 | + if (!ident_matches(ident, content, tst, |
482 | + homehost, update, |
483 | + report_missmatch ? devname : NULL)) |
484 | + /* message already printed */; |
485 | + else if (is_member_busy(content->text_version)) { |
486 | + if (report_missmatch) |
487 | + fprintf(stderr, Name ": member %s in %s is already assembled\n", |
488 | + content->text_version, |
489 | + devname); |
490 | + } else if (content->array.state & (1<<MD_SB_BLOCK_VOLUME)) { |
491 | + /* do not assemble arrays with unsupported configurations */ |
492 | + fprintf(stderr, Name ": Cannot activate member %s in %s.\n", |
493 | + content->text_version, |
494 | + devname); |
495 | + } else |
496 | + break; |
497 | + } |
498 | + if (!content) { |
499 | + tmpdev->used = 2; |
500 | + goto loop; /* empty container */ |
501 | + } |
502 | + |
503 | + st = tst; tst = NULL; |
504 | + if (!auto_assem && inargv && tmpdev->next != NULL) { |
505 | + fprintf(stderr, Name ": %s is a container, but is not " |
506 | + "only device given: confused and aborting\n", |
507 | + devname); |
508 | + st->ss->free_super(st); |
509 | + dev_policy_free(pol); |
510 | + domain_free(domains); |
511 | + return 1; |
512 | + } |
513 | + if (verbose > 0) |
514 | + fprintf(stderr, Name ": found match on member %s in %s\n", |
515 | + content->text_version, devname); |
516 | + |
517 | + /* make sure we finished the loop */ |
518 | + tmpdev = NULL; |
519 | + goto loop; |
520 | + } else { |
521 | + |
522 | + content = &info; |
523 | + tst->ss->getinfo_super(tst, content, NULL); |
524 | + |
525 | + if (!ident_matches(ident, content, tst, |
526 | + homehost, update, |
527 | + report_missmatch ? devname : NULL)) |
528 | + goto loop; |
529 | + |
530 | + /* should be safe to try an exclusive open now, we |
531 | + * have rejected anything that some other mdadm might |
532 | + * be looking at |
533 | + */ |
534 | + dfd = dev_open(devname, O_RDONLY | O_EXCL); |
535 | + if (dfd < 0) { |
536 | + if (report_missmatch) |
537 | + fprintf(stderr, Name ": %s is busy - skipping\n", devname); |
538 | + goto loop; |
539 | + } |
540 | + close(dfd); |
541 | + |
542 | + if (st == NULL) |
543 | + st = dup_super(tst); |
544 | + if (st->minor_version == -1) |
545 | + st->minor_version = tst->minor_version; |
546 | + |
547 | + if (memcmp(content->uuid, uuid_zero, |
548 | + sizeof(int[4])) == 0) { |
549 | + /* this is a floating spare. It cannot define |
550 | + * an array unless there are no more arrays of |
551 | + * this type to be found. It can be included |
552 | + * in an array of this type though. |
553 | + */ |
554 | + tmpdev->used = 3; |
555 | + goto loop; |
556 | + } |
557 | + |
558 | + if (st->ss != tst->ss || |
559 | + st->minor_version != tst->minor_version || |
560 | + st->ss->compare_super(st, tst) != 0) { |
561 | + /* Some mismatch. If exactly one array matches this host, |
562 | + * we can resolve on that one. |
563 | + * Or, if we are auto assembling, we just ignore the second |
564 | + * for now. |
565 | + */ |
566 | + if (auto_assem) |
567 | + goto loop; |
568 | + if (homehost) { |
569 | + int first = st->ss->match_home(st, homehost); |
570 | + int last = tst->ss->match_home(tst, homehost); |
571 | + if (first != last && |
572 | + (first == 1 || last == 1)) { |
573 | + /* We can do something */ |
574 | + if (first) {/* just ignore this one */ |
575 | + if (report_missmatch) |
576 | + fprintf(stderr, Name ": %s misses out due to wrong homehost\n", |
577 | + devname); |
578 | + goto loop; |
579 | + } else { /* reject all those sofar */ |
580 | + struct mddev_dev *td; |
581 | + if (report_missmatch) |
582 | + fprintf(stderr, Name ": %s overrides previous devices due to good homehost\n", |
583 | + devname); |
584 | + for (td=devlist; td != tmpdev; td=td->next) |
585 | + if (td->used == 1) |
586 | + td->used = 0; |
587 | + tmpdev->used = 1; |
588 | + goto loop; |
589 | + } |
590 | + } |
591 | + } |
592 | + fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n", |
593 | + devname); |
594 | + tst->ss->free_super(tst); |
595 | + st->ss->free_super(st); |
596 | + dev_policy_free(pol); |
597 | + domain_free(domains); |
598 | + return 1; |
599 | + } |
600 | + tmpdev->used = 1; |
601 | + } |
602 | + loop: |
603 | + /* Collect domain information from members only */ |
604 | + if (tmpdev && tmpdev->used == 1) { |
605 | + if (!pol) |
606 | + pol = devnum_policy(stb.st_rdev); |
607 | + domain_merge(&domains, pol, tst?tst->ss->name:NULL); |
608 | + } |
609 | + dev_policy_free(pol); |
610 | + pol = NULL; |
611 | + if (tst) |
612 | + tst->ss->free_super(tst); |
613 | + } |
614 | + |
615 | + /* Check if we found some imsm spares but no members */ |
616 | + if ((auto_assem || |
617 | + (ident->uuid_set && |
618 | + memcmp(uuid_zero, ident->uuid,sizeof(uuid_zero)) == 0)) && |
619 | + (!st || !st->sb)) |
620 | + for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) { |
621 | + if (tmpdev->used != 3) |
622 | + continue; |
623 | + tmpdev->used = 1; |
624 | + content = &info; |
625 | + |
626 | + if (!st->sb) { |
627 | + /* we need sb from one of the spares */ |
628 | + int dfd = dev_open(tmpdev->devname, O_RDONLY); |
629 | + if (dfd < 0 || |
630 | + st->ss->load_super(st, dfd, NULL)) |
631 | + tmpdev->used = 2; |
632 | + if (dfd > 0) |
633 | + close(dfd); |
634 | + } |
635 | + } |
636 | + |
637 | + /* Now reject spares that don't match domains of identified members */ |
638 | + for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) { |
639 | + struct stat stb; |
640 | + if (tmpdev->used != 3) |
641 | + continue; |
642 | + if (stat(tmpdev->devname, &stb)< 0) { |
643 | + fprintf(stderr, Name ": fstat failed for %s: %s\n", |
644 | + tmpdev->devname, strerror(errno)); |
645 | + tmpdev->used = 2; |
646 | + } else { |
647 | + struct dev_policy *pol = devnum_policy(stb.st_rdev); |
648 | + int dt = domain_test(domains, pol, NULL); |
649 | + if (inargv && dt != 0) |
650 | + /* take this spare as domains match |
651 | + * if there are any */ |
652 | + tmpdev->used = 1; |
653 | + else if (!inargv && dt == 1) |
654 | + /* device wasn't explicitly listed, so need |
655 | + * explicit domain match - which we have */ |
656 | + tmpdev->used = 1; |
657 | + else |
658 | + /* if domains don't match mark as unused */ |
659 | + tmpdev->used = 0; |
660 | + dev_policy_free(pol); |
661 | + } |
662 | + } |
663 | + domain_free(domains); |
664 | + |
665 | + if (!st || !st->sb || !content) |
666 | + return 2; |
667 | + |
668 | + /* Now need to open the array device. Use create_mddev */ |
669 | + if (content == &info) |
670 | + st->ss->getinfo_super(st, content, NULL); |
671 | + |
672 | + trustworthy = FOREIGN; |
673 | + name = content->name; |
674 | + switch (st->ss->match_home(st, homehost) |
675 | + ?: st->ss->match_home(st, "any")) { |
676 | + case 1: |
677 | + trustworthy = LOCAL; |
678 | + name = strchr(content->name, ':'); |
679 | + if (name) |
680 | + name++; |
681 | + else |
682 | + name = content->name; |
683 | + break; |
684 | + } |
685 | + if (!auto_assem) |
686 | + /* If the array is listed in mdadm.conf or on |
687 | + * command line, then we trust the name |
688 | + * even if the array doesn't look local |
689 | + */ |
690 | + trustworthy = LOCAL; |
691 | + |
692 | + if (name[0] == 0 && |
693 | + content->array.level == LEVEL_CONTAINER) { |
694 | + name = content->text_version; |
695 | + trustworthy = METADATA; |
696 | + } |
697 | + |
698 | + if (name[0] && trustworthy != LOCAL && |
699 | + ! require_homehost && |
700 | + conf_name_is_free(name)) |
701 | + trustworthy = LOCAL; |
702 | + |
703 | + if (trustworthy == LOCAL && |
704 | + strchr(name, ':')) |
705 | + /* Ignore 'host:' prefix of name */ |
706 | + name = strchr(name, ':')+1; |
707 | + |
708 | + mdfd = create_mddev(mddev, name, ident->autof, trustworthy, |
709 | + chosen_name); |
710 | + if (mdfd < 0) { |
711 | + st->ss->free_super(st); |
712 | + if (auto_assem) |
713 | + goto try_again; |
714 | + return 1; |
715 | + } |
716 | + mddev = chosen_name; |
717 | + vers = md_get_version(mdfd); |
718 | + if (vers < 9000) { |
719 | + fprintf(stderr, Name ": Assemble requires driver version 0.90.0 or later.\n" |
720 | + " Upgrade your kernel or try --build\n"); |
721 | + close(mdfd); |
722 | + return 1; |
723 | + } |
724 | + if (mddev_busy(fd2devnum(mdfd))) { |
725 | + fprintf(stderr, Name ": %s already active, cannot restart it!\n", |
726 | + mddev); |
727 | + for (tmpdev = devlist ; |
728 | + tmpdev && tmpdev->used != 1; |
729 | + tmpdev = tmpdev->next) |
730 | + ; |
731 | + if (tmpdev && auto_assem) |
732 | + fprintf(stderr, Name ": %s needed for %s...\n", |
733 | + mddev, tmpdev->devname); |
734 | + close(mdfd); |
735 | + mdfd = -3; |
736 | + st->ss->free_super(st); |
737 | + if (auto_assem) |
738 | + goto try_again; |
739 | + return 1; |
740 | + } |
741 | + ioctl(mdfd, STOP_ARRAY, NULL); /* just incase it was started but has no content */ |
742 | + |
743 | +#ifndef MDASSEMBLE |
744 | + if (content != &info) { |
745 | + /* This is a member of a container. Try starting the array. */ |
746 | + int err; |
747 | + err = assemble_container_content(st, mdfd, content, runstop, |
748 | + chosen_name, verbose, |
749 | + backup_file, freeze_reshape); |
750 | + close(mdfd); |
751 | + return err; |
752 | + } |
753 | + bitmap_done = 0; |
754 | +#endif |
755 | + /* Ok, no bad inconsistancy, we can try updating etc */ |
756 | + devices = malloc(num_devs * sizeof(*devices)); |
757 | + devmap = calloc(num_devs * content->array.raid_disks, 1); |
758 | + for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) { |
759 | + char *devname = tmpdev->devname; |
760 | + struct stat stb; |
761 | + /* looks like a good enough match to update the super block if needed */ |
762 | +#ifndef MDASSEMBLE |
763 | + if (update) { |
764 | + int dfd; |
765 | + /* prepare useful information in info structures */ |
766 | + struct stat stb2; |
767 | + struct supertype *tst; |
768 | + int err; |
769 | + fstat(mdfd, &stb2); |
770 | + |
771 | + if (strcmp(update, "uuid")==0 && |
772 | + !ident->uuid_set) { |
773 | + int rfd; |
774 | + if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 || |
775 | + read(rfd, ident->uuid, 16) != 16) { |
776 | + *(__u32*)(ident->uuid) = random(); |
777 | + *(__u32*)(ident->uuid+1) = random(); |
778 | + *(__u32*)(ident->uuid+2) = random(); |
779 | + *(__u32*)(ident->uuid+3) = random(); |
780 | + } |
781 | + if (rfd >= 0) close(rfd); |
782 | + } |
783 | + dfd = dev_open(devname, O_RDWR|O_EXCL); |
784 | + |
785 | + tst = dup_super(st); |
786 | + if (dfd < 0 || tst->ss->load_super(tst, dfd, NULL) != 0) { |
787 | + fprintf(stderr, Name ": cannot re-read metadata from %s - aborting\n", |
788 | + devname); |
789 | + if (dfd >= 0) |
790 | + close(dfd); |
791 | + close(mdfd); |
792 | + free(devices); |
793 | + free(devmap); |
794 | + return 1; |
795 | + } |
796 | + tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks); |
797 | + |
798 | + memcpy(content->uuid, ident->uuid, 16); |
799 | + strcpy(content->name, ident->name); |
800 | + content->array.md_minor = minor(stb2.st_rdev); |
801 | + |
802 | + if (strcmp(update, "byteorder") == 0) |
803 | + err = 0; |
804 | + else |
805 | + err = tst->ss->update_super(tst, content, update, |
806 | + devname, verbose, |
807 | + ident->uuid_set, |
808 | + homehost); |
809 | + if (err < 0) { |
810 | + fprintf(stderr, |
811 | + Name ": --update=%s not understood" |
812 | + " for %s metadata\n", |
813 | + update, tst->ss->name); |
814 | + tst->ss->free_super(tst); |
815 | + free(tst); |
816 | + close(mdfd); |
817 | + close(dfd); |
818 | + free(devices); |
819 | + free(devmap); |
820 | + return 1; |
821 | + } |
822 | + if (strcmp(update, "uuid")==0 && |
823 | + !ident->uuid_set) { |
824 | + ident->uuid_set = 1; |
825 | + memcpy(ident->uuid, content->uuid, 16); |
826 | + } |
827 | + if (tst->ss->store_super(tst, dfd)) |
828 | + fprintf(stderr, Name ": Could not re-write superblock on %s.\n", |
829 | + devname); |
830 | + close(dfd); |
831 | + |
832 | + if (strcmp(update, "uuid")==0 && |
833 | + ident->bitmap_fd >= 0 && !bitmap_done) { |
834 | + if (bitmap_update_uuid(ident->bitmap_fd, |
835 | + content->uuid, |
836 | + tst->ss->swapuuid) != 0) |
837 | + fprintf(stderr, Name ": Could not update uuid on external bitmap.\n"); |
838 | + else |
839 | + bitmap_done = 1; |
840 | + } |
841 | + tst->ss->free_super(tst); |
842 | + } else |
843 | +#endif |
844 | + { |
845 | + struct supertype *tst = dup_super(st); |
846 | + int dfd; |
847 | + dfd = dev_open(devname, O_RDWR|O_EXCL); |
848 | + |
849 | + if (dfd < 0 || tst->ss->load_super(tst, dfd, NULL) != 0) { |
850 | + fprintf(stderr, Name ": cannot re-read metadata from %s - aborting\n", |
851 | + devname); |
852 | + if (dfd >= 0) |
853 | + close(dfd); |
854 | + close(mdfd); |
855 | + free(devices); |
856 | + free(devmap); |
857 | + return 1; |
858 | + } |
859 | + tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks); |
860 | + tst->ss->free_super(tst); |
861 | + close(dfd); |
862 | + } |
863 | + |
864 | + stat(devname, &stb); |
865 | + |
866 | + if (verbose > 0) |
867 | + fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n", |
868 | + devname, mddev, content->disk.raid_disk); |
869 | + devices[devcnt].devname = devname; |
870 | + devices[devcnt].uptodate = 0; |
871 | + devices[devcnt].i = *content; |
872 | + devices[devcnt].i.disk.major = major(stb.st_rdev); |
873 | + devices[devcnt].i.disk.minor = minor(stb.st_rdev); |
874 | + if (most_recent < devcnt) { |
875 | + if (devices[devcnt].i.events |
876 | + > devices[most_recent].i.events) |
877 | + most_recent = devcnt; |
878 | + } |
879 | + if (content->array.level == LEVEL_MULTIPATH) |
880 | + /* with multipath, the raid_disk from the superblock is meaningless */ |
881 | + i = devcnt; |
882 | + else |
883 | + i = devices[devcnt].i.disk.raid_disk; |
884 | + if (i+1 == 0) { |
885 | + if (nextspare < content->array.raid_disks) |
886 | + nextspare = content->array.raid_disks; |
887 | + i = nextspare++; |
888 | + } else { |
889 | + if (i >= content->array.raid_disks && |
890 | + i >= nextspare) |
891 | + nextspare = i+1; |
892 | + } |
893 | + if (i < 10000) { |
894 | + if (i >= bestcnt) { |
895 | + int newbestcnt = i+10; |
896 | + int *newbest = malloc(sizeof(int)*newbestcnt); |
897 | + int c; |
898 | + for (c=0; c < newbestcnt; c++) |
899 | + if (c < bestcnt) |
900 | + newbest[c] = best[c]; |
901 | + else |
902 | + newbest[c] = -1; |
903 | + if (best)free(best); |
904 | + best = newbest; |
905 | + bestcnt = newbestcnt; |
906 | + } |
907 | + if (best[i] >=0 && |
908 | + devices[best[i]].i.events |
909 | + == devices[devcnt].i.events |
910 | + && (devices[best[i]].i.disk.minor |
911 | + != devices[devcnt].i.disk.minor) |
912 | + && st->ss == &super0 |
913 | + && content->array.level != LEVEL_MULTIPATH) { |
914 | + /* two different devices with identical superblock. |
915 | + * Could be a mis-detection caused by overlapping |
916 | + * partitions. fail-safe. |
917 | + */ |
918 | + fprintf(stderr, Name ": WARNING %s and %s appear" |
919 | + " to have very similar superblocks.\n" |
920 | + " If they are really different, " |
921 | + "please --zero the superblock on one\n" |
922 | + " If they are the same or overlap," |
923 | + " please remove one from %s.\n", |
924 | + devices[best[i]].devname, devname, |
925 | + inargv ? "the list" : |
926 | + "the\n DEVICE list in mdadm.conf" |
927 | + ); |
928 | + close(mdfd); |
929 | + free(devices); |
930 | + free(devmap); |
931 | + return 1; |
932 | + } |
933 | + if (best[i] == -1 |
934 | + || (devices[best[i]].i.events |
935 | + < devices[devcnt].i.events)) |
936 | + best[i] = devcnt; |
937 | + } |
938 | + devcnt++; |
939 | + } |
940 | + |
941 | + if (devcnt == 0) { |
942 | + fprintf(stderr, Name ": no devices found for %s\n", |
943 | + mddev); |
944 | + if (st) |
945 | + st->ss->free_super(st); |
946 | + close(mdfd); |
947 | + free(devices); |
948 | + free(devmap); |
949 | + return 1; |
950 | + } |
951 | + |
952 | + if (update && strcmp(update, "byteorder")==0) |
953 | + st->minor_version = 90; |
954 | + |
955 | + st->ss->getinfo_super(st, content, NULL); |
956 | + clean = content->array.state & 1; |
957 | + |
958 | + /* now we have some devices that might be suitable. |
959 | + * I wonder how many |
960 | + */ |
961 | + avail = malloc(content->array.raid_disks); |
962 | + memset(avail, 0, content->array.raid_disks); |
963 | + okcnt = 0; |
964 | + sparecnt=0; |
965 | + rebuilding_cnt=0; |
966 | + for (i=0; i< bestcnt; i++) { |
967 | + int j = best[i]; |
968 | + int event_margin = 1; /* always allow a difference of '1' |
969 | + * like the kernel does |
970 | + */ |
971 | + if (j < 0) continue; |
972 | + /* note: we ignore error flags in multipath arrays |
973 | + * as they don't make sense |
974 | + */ |
975 | + if (content->array.level != LEVEL_MULTIPATH) |
976 | + if (!(devices[j].i.disk.state & (1<<MD_DISK_ACTIVE))) { |
977 | + if (!(devices[j].i.disk.state |
978 | + & (1<<MD_DISK_FAULTY))) { |
979 | + devices[j].uptodate = 1; |
980 | + sparecnt++; |
981 | + } |
982 | + continue; |
983 | + } |
984 | + /* If this device thinks that 'most_recent' has failed, then |
985 | + * we must reject this device. |
986 | + */ |
987 | + if (j != most_recent && |
988 | + content->array.raid_disks > 0 && |
989 | + devices[most_recent].i.disk.raid_disk >= 0 && |
990 | + devmap[j * content->array.raid_disks + devices[most_recent].i.disk.raid_disk] == 0) { |
991 | + if (verbose > -1) |
992 | + fprintf(stderr, Name ": ignoring %s as it reports %s as failed\n", |
993 | + devices[j].devname, devices[most_recent].devname); |
994 | + best[i] = -1; |
995 | + continue; |
996 | + } |
997 | + if (devices[j].i.events+event_margin >= |
998 | + devices[most_recent].i.events) { |
999 | + devices[j].uptodate = 1; |
1000 | + if (i < content->array.raid_disks) { |
1001 | + if (devices[j].i.recovery_start == MaxSector || |
1002 | + (content->reshape_active && |
1003 | + ((i >= content->array.raid_disks - content->delta_disks) || |
1004 | + (i >= content->array.raid_disks - content->delta_disks - 1 |
1005 | + && content->array.level == 4)))) { |
1006 | + okcnt++; |
1007 | + avail[i]=1; |
1008 | + } else |
1009 | + rebuilding_cnt++; |
1010 | + } else |
1011 | + sparecnt++; |
1012 | + } |
1013 | + } |
1014 | + free(devmap); |
1015 | + while (force && |
1016 | + (!enough(content->array.level, content->array.raid_disks, |
1017 | + content->array.layout, 1, |
1018 | + avail) |
1019 | + || |
1020 | + (content->reshape_active && content->delta_disks > 0 && |
1021 | + !enough(content->array.level, (content->array.raid_disks |
1022 | + - content->delta_disks), |
1023 | + content->new_layout, 1, |
1024 | + avail) |
1025 | + ))) { |
1026 | + /* Choose the newest best drive which is |
1027 | + * not up-to-date, update the superblock |
1028 | + * and add it. |
1029 | + */ |
1030 | + int fd; |
1031 | + struct supertype *tst; |
1032 | + unsigned long long current_events; |
1033 | + chosen_drive = -1; |
1034 | + for (i = 0; i < content->array.raid_disks && i < bestcnt; i++) { |
1035 | + int j = best[i]; |
1036 | + if (j>=0 && |
1037 | + !devices[j].uptodate && |
1038 | + devices[j].i.recovery_start == MaxSector && |
1039 | + (chosen_drive < 0 || |
1040 | + devices[j].i.events |
1041 | + > devices[chosen_drive].i.events)) |
1042 | + chosen_drive = j; |
1043 | + } |
1044 | + if (chosen_drive < 0) |
1045 | + break; |
1046 | + current_events = devices[chosen_drive].i.events; |
1047 | + add_another: |
1048 | + if (verbose >= 0) |
1049 | + fprintf(stderr, Name ": forcing event count in %s(%d) from %d upto %d\n", |
1050 | + devices[chosen_drive].devname, |
1051 | + devices[chosen_drive].i.disk.raid_disk, |
1052 | + (int)(devices[chosen_drive].i.events), |
1053 | + (int)(devices[most_recent].i.events)); |
1054 | + fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL); |
1055 | + if (fd < 0) { |
1056 | + fprintf(stderr, Name ": Couldn't open %s for write - not updating\n", |
1057 | + devices[chosen_drive].devname); |
1058 | + devices[chosen_drive].i.events = 0; |
1059 | + continue; |
1060 | + } |
1061 | + tst = dup_super(st); |
1062 | + if (tst->ss->load_super(tst,fd, NULL)) { |
1063 | + close(fd); |
1064 | + fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n", |
1065 | + devices[chosen_drive].devname); |
1066 | + devices[chosen_drive].i.events = 0; |
1067 | + continue; |
1068 | + } |
1069 | + content->events = devices[most_recent].i.events; |
1070 | + tst->ss->update_super(tst, content, "force-one", |
1071 | + devices[chosen_drive].devname, verbose, |
1072 | + 0, NULL); |
1073 | + |
1074 | + if (tst->ss->store_super(tst, fd)) { |
1075 | + close(fd); |
1076 | + fprintf(stderr, Name ": Could not re-write superblock on %s\n", |
1077 | + devices[chosen_drive].devname); |
1078 | + devices[chosen_drive].i.events = 0; |
1079 | + tst->ss->free_super(tst); |
1080 | + continue; |
1081 | + } |
1082 | + close(fd); |
1083 | + devices[chosen_drive].i.events = devices[most_recent].i.events; |
1084 | + devices[chosen_drive].uptodate = 1; |
1085 | + avail[chosen_drive] = 1; |
1086 | + okcnt++; |
1087 | + tst->ss->free_super(tst); |
1088 | + |
1089 | + /* If there are any other drives of the same vintage, |
1090 | + * add them in as well. We can't lose and we might gain |
1091 | + */ |
1092 | + for (i = 0; i < content->array.raid_disks && i < bestcnt ; i++) { |
1093 | + int j = best[i]; |
1094 | + if (j >= 0 && |
1095 | + !devices[j].uptodate && |
1096 | + devices[j].i.recovery_start == MaxSector && |
1097 | + devices[j].i.events == current_events) { |
1098 | + chosen_drive = j; |
1099 | + goto add_another; |
1100 | + } |
1101 | + } |
1102 | + } |
1103 | + |
1104 | + /* Now we want to look at the superblock which the kernel will base things on |
1105 | + * and compare the devices that we think are working with the devices that the |
1106 | + * superblock thinks are working. |
1107 | + * If there are differences and --force is given, then update this chosen |
1108 | + * superblock. |
1109 | + */ |
1110 | + chosen_drive = -1; |
1111 | + st->ss->free_super(st); |
1112 | + for (i=0; chosen_drive < 0 && i<bestcnt; i++) { |
1113 | + int j = best[i]; |
1114 | + int fd; |
1115 | + |
1116 | + if (j<0) |
1117 | + continue; |
1118 | + if (!devices[j].uptodate) |
1119 | + continue; |
1120 | + if (devices[j].i.events < devices[most_recent].i.events) |
1121 | + continue; |
1122 | + chosen_drive = j; |
1123 | + if ((fd=dev_open(devices[j].devname, O_RDONLY|O_EXCL))< 0) { |
1124 | + fprintf(stderr, Name ": Cannot open %s: %s\n", |
1125 | + devices[j].devname, strerror(errno)); |
1126 | + close(mdfd); |
1127 | + free(devices); |
1128 | + return 1; |
1129 | + } |
1130 | + if (st->ss->load_super(st,fd, NULL)) { |
1131 | + close(fd); |
1132 | + fprintf(stderr, Name ": RAID superblock has disappeared from %s\n", |
1133 | + devices[j].devname); |
1134 | + close(mdfd); |
1135 | + free(devices); |
1136 | + return 1; |
1137 | + } |
1138 | + close(fd); |
1139 | + } |
1140 | + if (st->sb == NULL) { |
1141 | + fprintf(stderr, Name ": No suitable drives found for %s\n", mddev); |
1142 | + close(mdfd); |
1143 | + free(devices); |
1144 | + return 1; |
1145 | + } |
1146 | + st->ss->getinfo_super(st, content, NULL); |
1147 | +#ifndef MDASSEMBLE |
1148 | + sysfs_init(content, mdfd, 0); |
1149 | +#endif |
1150 | + for (i=0; i<bestcnt; i++) { |
1151 | + int j = best[i]; |
1152 | + unsigned int desired_state; |
1153 | + |
1154 | + if (i < content->array.raid_disks) |
1155 | + desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC); |
1156 | + else |
1157 | + desired_state = 0; |
1158 | + |
1159 | + if (j<0) |
1160 | + continue; |
1161 | + if (!devices[j].uptodate) |
1162 | + continue; |
1163 | + |
1164 | + devices[j].i.disk.state = desired_state; |
1165 | + if (!(devices[j].i.array.state & 1)) |
1166 | + clean = 0; |
1167 | + |
1168 | + if (st->ss->update_super(st, &devices[j].i, "assemble", NULL, |
1169 | + verbose, 0, NULL)) { |
1170 | + if (force) { |
1171 | + if (verbose >= 0) |
1172 | + fprintf(stderr, Name ": " |
1173 | + "clearing FAULTY flag for device %d in %s for %s\n", |
1174 | + j, mddev, devices[j].devname); |
1175 | + change = 1; |
1176 | + } else { |
1177 | + if (verbose >= -1) |
1178 | + fprintf(stderr, Name ": " |
1179 | + "device %d in %s has wrong state in superblock, but %s seems ok\n", |
1180 | + i, mddev, devices[j].devname); |
1181 | + } |
1182 | + } |
1183 | +#if 0 |
1184 | + if (!(super.disks[i].i.disk.state & (1 << MD_DISK_FAULTY))) { |
1185 | + fprintf(stderr, Name ": devices %d of %s is not marked FAULTY in superblock, but cannot be found\n", |
1186 | + i, mddev); |
1187 | + } |
1188 | +#endif |
1189 | + } |
1190 | + if (force && !clean && |
1191 | + !enough(content->array.level, content->array.raid_disks, |
1192 | + content->array.layout, clean, |
1193 | + avail)) { |
1194 | + change += st->ss->update_super(st, content, "force-array", |
1195 | + devices[chosen_drive].devname, verbose, |
1196 | + 0, NULL); |
1197 | + clean = 1; |
1198 | + } |
1199 | + |
1200 | + if (change) { |
1201 | + int fd; |
1202 | + fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL); |
1203 | + if (fd < 0) { |
1204 | + fprintf(stderr, Name ": Could not open %s for write - cannot Assemble array.\n", |
1205 | + devices[chosen_drive].devname); |
1206 | + close(mdfd); |
1207 | + free(devices); |
1208 | + return 1; |
1209 | + } |
1210 | + if (st->ss->store_super(st, fd)) { |
1211 | + close(fd); |
1212 | + fprintf(stderr, Name ": Could not re-write superblock on %s\n", |
1213 | + devices[chosen_drive].devname); |
1214 | + close(mdfd); |
1215 | + free(devices); |
1216 | + return 1; |
1217 | + } |
1218 | + if (verbose >= 0) |
1219 | + fprintf(stderr, Name ": Marking array %s as 'clean'\n", |
1220 | + mddev); |
1221 | + close(fd); |
1222 | + } |
1223 | + |
1224 | + /* If we are in the middle of a reshape we may need to restore saved data |
1225 | + * that was moved aside due to the reshape overwriting live data |
1226 | + * The code of doing this lives in Grow.c |
1227 | + */ |
1228 | +#ifndef MDASSEMBLE |
1229 | + if (content->reshape_active) { |
1230 | + int err = 0; |
1231 | + int *fdlist = malloc(sizeof(int)* bestcnt); |
1232 | + if (verbose > 0) |
1233 | + fprintf(stderr, Name ":%s has an active reshape - checking " |
1234 | + "if critical section needs to be restored\n", |
1235 | + chosen_name); |
1236 | + for (i=0; i<bestcnt; i++) { |
1237 | + int j = best[i]; |
1238 | + if (j >= 0) { |
1239 | + fdlist[i] = dev_open(devices[j].devname, O_RDWR|O_EXCL); |
1240 | + if (fdlist[i] < 0) { |
1241 | + fprintf(stderr, Name ": Could not open %s for write - cannot Assemble array.\n", |
1242 | + devices[j].devname); |
1243 | + err = 1; |
1244 | + break; |
1245 | + } |
1246 | + } else |
1247 | + fdlist[i] = -1; |
1248 | + } |
1249 | + if (!err) { |
1250 | + if (st->ss->external && st->ss->recover_backup) |
1251 | + err = st->ss->recover_backup(st, content); |
1252 | + else |
1253 | + err = Grow_restart(st, content, fdlist, bestcnt, |
1254 | + backup_file, verbose > 0); |
1255 | + if (err && invalid_backup) { |
1256 | + if (verbose > 0) |
1257 | + fprintf(stderr, Name ": continuing" |
1258 | + " without restoring backup\n"); |
1259 | + err = 0; |
1260 | + } |
1261 | + } |
1262 | + while (i>0) { |
1263 | + i--; |
1264 | + if (fdlist[i]>=0) close(fdlist[i]); |
1265 | + } |
1266 | + if (err) { |
1267 | + fprintf(stderr, Name ": Failed to restore critical section for reshape, sorry.\n"); |
1268 | + if (backup_file == NULL) |
1269 | + fprintf(stderr," Possibly you needed to specify the --backup-file\n"); |
1270 | + close(mdfd); |
1271 | + free(devices); |
1272 | + return err; |
1273 | + } |
1274 | + } |
1275 | +#endif |
1276 | + /* count number of in-sync devices according to the superblock. |
1277 | + * We must have this number to start the array without -s or -R |
1278 | + */ |
1279 | + req_cnt = content->array.working_disks; |
1280 | + |
1281 | + /* Almost ready to actually *do* something */ |
1282 | + if (!old_linux) { |
1283 | + int rv; |
1284 | + |
1285 | + /* First, fill in the map, so that udev can find our name |
1286 | + * as soon as we become active. |
1287 | + */ |
1288 | + map_update(NULL, fd2devnum(mdfd), content->text_version, |
1289 | + content->uuid, chosen_name); |
1290 | + |
1291 | + rv = set_array_info(mdfd, st, content); |
1292 | + if (rv) { |
1293 | + fprintf(stderr, Name ": failed to set array info for %s: %s\n", |
1294 | + mddev, strerror(errno)); |
1295 | + ioctl(mdfd, STOP_ARRAY, NULL); |
1296 | + close(mdfd); |
1297 | + free(devices); |
1298 | + return 1; |
1299 | + } |
1300 | + if (ident->bitmap_fd >= 0) { |
1301 | + if (ioctl(mdfd, SET_BITMAP_FILE, ident->bitmap_fd) != 0) { |
1302 | + fprintf(stderr, Name ": SET_BITMAP_FILE failed.\n"); |
1303 | + ioctl(mdfd, STOP_ARRAY, NULL); |
1304 | + close(mdfd); |
1305 | + free(devices); |
1306 | + return 1; |
1307 | + } |
1308 | + } else if (ident->bitmap_file) { |
1309 | + /* From config file */ |
1310 | + int bmfd = open(ident->bitmap_file, O_RDWR); |
1311 | + if (bmfd < 0) { |
1312 | + fprintf(stderr, Name ": Could not open bitmap file %s\n", |
1313 | + ident->bitmap_file); |
1314 | + ioctl(mdfd, STOP_ARRAY, NULL); |
1315 | + close(mdfd); |
1316 | + free(devices); |
1317 | + return 1; |
1318 | + } |
1319 | + if (ioctl(mdfd, SET_BITMAP_FILE, bmfd) != 0) { |
1320 | + fprintf(stderr, Name ": Failed to set bitmapfile for %s\n", mddev); |
1321 | + close(bmfd); |
1322 | + ioctl(mdfd, STOP_ARRAY, NULL); |
1323 | + close(mdfd); |
1324 | + free(devices); |
1325 | + return 1; |
1326 | + } |
1327 | + close(bmfd); |
1328 | + } |
1329 | + |
1330 | + /* First, add the raid disks, but add the chosen one last */ |
1331 | + for (i=0; i<= bestcnt; i++) { |
1332 | + int j; |
1333 | + if (i < bestcnt) { |
1334 | + j = best[i]; |
1335 | + if (j == chosen_drive) |
1336 | + continue; |
1337 | + } else |
1338 | + j = chosen_drive; |
1339 | + |
1340 | + if (j >= 0 /* && devices[j].uptodate */) { |
1341 | + int dfd = dev_open(devices[j].devname, |
1342 | + O_RDWR|O_EXCL); |
1343 | + if (dfd >= 0) { |
1344 | + remove_partitions(dfd); |
1345 | + close(dfd); |
1346 | + } |
1347 | + rv = add_disk(mdfd, st, content, &devices[j].i); |
1348 | + |
1349 | + if (rv) { |
1350 | + fprintf(stderr, Name ": failed to add " |
1351 | + "%s to %s: %s\n", |
1352 | + devices[j].devname, |
1353 | + mddev, |
1354 | + strerror(errno)); |
1355 | + if (i < content->array.raid_disks |
1356 | + || i == bestcnt) |
1357 | + okcnt--; |
1358 | + else |
1359 | + sparecnt--; |
1360 | + } else if (verbose > 0) |
1361 | + fprintf(stderr, Name ": added %s " |
1362 | + "to %s as %d%s\n", |
1363 | + devices[j].devname, mddev, |
1364 | + devices[j].i.disk.raid_disk, |
1365 | + devices[j].uptodate?"": |
1366 | + " (possibly out of date)"); |
1367 | + } else if (verbose > 0 && i < content->array.raid_disks) |
1368 | + fprintf(stderr, Name ": no uptodate device for " |
1369 | + "slot %d of %s\n", |
1370 | + i, mddev); |
1371 | + } |
1372 | + |
1373 | + if (content->array.level == LEVEL_CONTAINER) { |
1374 | + if (verbose >= 0) { |
1375 | + fprintf(stderr, Name ": Container %s has been " |
1376 | + "assembled with %d drive%s", |
1377 | + mddev, okcnt+sparecnt, okcnt+sparecnt==1?"":"s"); |
1378 | + if (okcnt < (unsigned)content->array.raid_disks) |
1379 | + fprintf(stderr, " (out of %d)", |
1380 | + content->array.raid_disks); |
1381 | + fprintf(stderr, "\n"); |
1382 | + } |
1383 | + st->ss->free_super(st); |
1384 | + sysfs_uevent(content, "change"); |
1385 | + wait_for(chosen_name, mdfd); |
1386 | + close(mdfd); |
1387 | + free(devices); |
1388 | + return 0; |
1389 | + } |
1390 | + |
1391 | + if (runstop == 1 || |
1392 | + (runstop <= 0 && |
1393 | + ( enough(content->array.level, content->array.raid_disks, |
1394 | + content->array.layout, clean, avail) && |
1395 | + (okcnt + rebuilding_cnt >= req_cnt || start_partial_ok) |
1396 | + ))) { |
1397 | + /* This array is good-to-go. |
1398 | + * If a reshape is in progress then we might need to |
1399 | + * continue monitoring it. In that case we start |
1400 | + * it read-only and let the grow code make it writable. |
1401 | + */ |
1402 | + int rv; |
1403 | +#ifndef MDASSEMBLE |
1404 | + if (content->reshape_active && |
1405 | + content->delta_disks <= 0) { |
1406 | + rv = sysfs_set_str(content, NULL, |
1407 | + "array_state", "readonly"); |
1408 | + if (rv == 0) |
1409 | + rv = Grow_continue(mdfd, st, content, |
1410 | + backup_file, |
1411 | + freeze_reshape); |
1412 | + } else |
1413 | +#endif |
1414 | + rv = ioctl(mdfd, RUN_ARRAY, NULL); |
1415 | + if (rv == 0) { |
1416 | + if (verbose >= 0) { |
1417 | + fprintf(stderr, Name ": %s has been started with %d drive%s", |
1418 | + mddev, okcnt, okcnt==1?"":"s"); |
1419 | + if (okcnt < (unsigned)content->array.raid_disks) |
1420 | + fprintf(stderr, " (out of %d)", content->array.raid_disks); |
1421 | + if (rebuilding_cnt) |
1422 | + fprintf(stderr, "%s %d rebuilding", sparecnt?",":" and", rebuilding_cnt); |
1423 | + if (sparecnt) |
1424 | + fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); |
1425 | + fprintf(stderr, ".\n"); |
1426 | + } |
1427 | + if (content->reshape_active && |
1428 | + content->array.level >= 4 && |
1429 | + content->array.level <= 6) { |
1430 | + /* might need to increase the size |
1431 | + * of the stripe cache - default is 256 |
1432 | + */ |
1433 | + if (256 < 4 * (content->array.chunk_size/4096)) { |
1434 | + struct mdinfo *sra = sysfs_read(mdfd, 0, 0); |
1435 | + if (sra) |
1436 | + sysfs_set_num(sra, NULL, |
1437 | + "stripe_cache_size", |
1438 | + (4 * content->array.chunk_size / 4096) + 1); |
1439 | + sysfs_free(sra); |
1440 | + } |
1441 | + } |
1442 | + if (okcnt < (unsigned)content->array.raid_disks) { |
1443 | + /* If any devices did not get added |
1444 | + * because the kernel rejected them based |
1445 | + * on event count, try adding them |
1446 | + * again providing the action policy is |
1447 | + * 're-add' or greater. The bitmap |
1448 | + * might allow them to be included, or |
1449 | + * they will become spares. |
1450 | + */ |
1451 | + for (i = 0; i < bestcnt; i++) { |
1452 | + int j = best[i]; |
1453 | + if (j >= 0 && !devices[j].uptodate) { |
1454 | + if (!disk_action_allows(&devices[j].i, st->ss->name, act_re_add)) |
1455 | + continue; |
1456 | + rv = add_disk(mdfd, st, content, |
1457 | + &devices[j].i); |
1458 | + if (rv == 0 && verbose >= 0) |
1459 | + fprintf(stderr, |
1460 | + Name ": %s has been re-added.\n", |
1461 | + devices[j].devname); |
1462 | + } |
1463 | + } |
1464 | + } |
1465 | + wait_for(mddev, mdfd); |
1466 | + close(mdfd); |
1467 | + if (auto_assem) { |
1468 | + int usecs = 1; |
1469 | + /* There is a nasty race with 'mdadm --monitor'. |
1470 | + * If it opens this device before we close it, |
1471 | + * it gets an incomplete open on which IO |
1472 | + * doesn't work and the capacity is |
1473 | + * wrong. |
1474 | + * If we reopen (to check for layered devices) |
1475 | + * before --monitor closes, we loose. |
1476 | + * |
1477 | + * So: wait upto 1 second for there to be |
1478 | + * a non-zero capacity. |
1479 | + */ |
1480 | + while (usecs < 1000) { |
1481 | + mdfd = open(mddev, O_RDONLY); |
1482 | + if (mdfd >= 0) { |
1483 | + unsigned long long size; |
1484 | + if (get_dev_size(mdfd, NULL, &size) && |
1485 | + size > 0) |
1486 | + break; |
1487 | + close(mdfd); |
1488 | + } |
1489 | + usleep(usecs); |
1490 | + usecs <<= 1; |
1491 | + } |
1492 | + } |
1493 | + free(devices); |
1494 | + return 0; |
1495 | + } |
1496 | + fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n", |
1497 | + mddev, strerror(errno)); |
1498 | + |
1499 | + if (!enough(content->array.level, content->array.raid_disks, |
1500 | + content->array.layout, 1, avail)) |
1501 | + fprintf(stderr, Name ": Not enough devices to " |
1502 | + "start the array.\n"); |
1503 | + else if (!enough(content->array.level, |
1504 | + content->array.raid_disks, |
1505 | + content->array.layout, clean, |
1506 | + avail)) |
1507 | + fprintf(stderr, Name ": Not enough devices to " |
1508 | + "start the array while not clean " |
1509 | + "- consider --force.\n"); |
1510 | + |
1511 | + if (auto_assem) |
1512 | + ioctl(mdfd, STOP_ARRAY, NULL); |
1513 | + close(mdfd); |
1514 | + free(devices); |
1515 | + return 1; |
1516 | + } |
1517 | + if (runstop == -1) { |
1518 | + fprintf(stderr, Name ": %s assembled from %d drive%s", |
1519 | + mddev, okcnt, okcnt==1?"":"s"); |
1520 | + if (okcnt != (unsigned)content->array.raid_disks) |
1521 | + fprintf(stderr, " (out of %d)", content->array.raid_disks); |
1522 | + fprintf(stderr, ", but not started.\n"); |
1523 | + close(mdfd); |
1524 | + free(devices); |
1525 | + return 0; |
1526 | + } |
1527 | + if (verbose >= -1) { |
1528 | + fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s"); |
1529 | + if (rebuilding_cnt) |
1530 | + fprintf(stderr, "%s %d rebuilding", sparecnt?", ":" and ", rebuilding_cnt); |
1531 | + if (sparecnt) |
1532 | + fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); |
1533 | + if (!enough(content->array.level, content->array.raid_disks, |
1534 | + content->array.layout, 1, avail)) |
1535 | + fprintf(stderr, " - not enough to start the array.\n"); |
1536 | + else if (!enough(content->array.level, |
1537 | + content->array.raid_disks, |
1538 | + content->array.layout, clean, |
1539 | + avail)) |
1540 | + fprintf(stderr, " - not enough to start the " |
1541 | + "array while not clean - consider " |
1542 | + "--force.\n"); |
1543 | + else { |
1544 | + if (req_cnt == (unsigned)content->array.raid_disks) |
1545 | + fprintf(stderr, " - need all %d to start it", req_cnt); |
1546 | + else |
1547 | + fprintf(stderr, " - need %d of %d to start", req_cnt, content->array.raid_disks); |
1548 | + fprintf(stderr, " (use --run to insist).\n"); |
1549 | + } |
1550 | + } |
1551 | + if (auto_assem) |
1552 | + ioctl(mdfd, STOP_ARRAY, NULL); |
1553 | + close(mdfd); |
1554 | + free(devices); |
1555 | + return 1; |
1556 | + } else { |
1557 | + /* The "chosen_drive" is a good choice, and if necessary, the superblock has |
1558 | + * been updated to point to the current locations of devices. |
1559 | + * so we can just start the array |
1560 | + */ |
1561 | + unsigned long dev; |
1562 | + dev = makedev(devices[chosen_drive].i.disk.major, |
1563 | + devices[chosen_drive].i.disk.minor); |
1564 | + if (ioctl(mdfd, START_ARRAY, dev)) { |
1565 | + fprintf(stderr, Name ": Cannot start array: %s\n", |
1566 | + strerror(errno)); |
1567 | + } |
1568 | + |
1569 | + } |
1570 | + close(mdfd); |
1571 | + free(devices); |
1572 | + return 0; |
1573 | +} |
1574 | + |
1575 | +#ifndef MDASSEMBLE |
1576 | +int assemble_container_content(struct supertype *st, int mdfd, |
1577 | + struct mdinfo *content, int runstop, |
1578 | + char *chosen_name, int verbose, |
1579 | + char *backup_file, int freeze_reshape) |
1580 | +{ |
1581 | + struct mdinfo *dev, *sra; |
1582 | + int working = 0, preexist = 0; |
1583 | + int expansion = 0; |
1584 | + struct map_ent *map = NULL; |
1585 | + int old_raid_disks; |
1586 | + int start_reshape; |
1587 | + |
1588 | + sysfs_init(content, mdfd, 0); |
1589 | + |
1590 | + sra = sysfs_read(mdfd, 0, GET_VERSION); |
1591 | + if (sra == NULL || strcmp(sra->text_version, content->text_version) != 0) |
1592 | + if (sysfs_set_array(content, md_get_version(mdfd)) != 0) { |
1593 | + if (sra) |
1594 | + sysfs_free(sra); |
1595 | + return 1; |
1596 | + } |
1597 | + |
1598 | + /* There are two types of reshape: container wide or sub-array specific |
1599 | + * Check if metadata requests blocking container wide reshapes |
1600 | + */ |
1601 | + start_reshape = (content->reshape_active && |
1602 | + !((content->reshape_active == CONTAINER_RESHAPE) && |
1603 | + (content->array.state & (1<<MD_SB_BLOCK_CONTAINER_RESHAPE)))); |
1604 | + |
1605 | + /* Block subarray here if it is under reshape now |
1606 | + * Do not allow for any changes in this array |
1607 | + */ |
1608 | + if (st->ss->external && content->recovery_blocked && start_reshape) |
1609 | + block_subarray(content); |
1610 | + |
1611 | + if (sra) |
1612 | + sysfs_free(sra); |
1613 | + old_raid_disks = content->array.raid_disks - content->delta_disks; |
1614 | + for (dev = content->devs; dev; dev = dev->next) |
1615 | + if (sysfs_add_disk(content, dev, 1) == 0) { |
1616 | + if (dev->disk.raid_disk >= old_raid_disks && |
1617 | + content->reshape_active) |
1618 | + expansion++; |
1619 | + else |
1620 | + working++; |
1621 | + } else if (errno == EEXIST) |
1622 | + preexist++; |
1623 | + if (working + expansion == 0) |
1624 | + return 1;/* Nothing new, don't try to start */ |
1625 | + |
1626 | + map_update(&map, fd2devnum(mdfd), |
1627 | + content->text_version, |
1628 | + content->uuid, chosen_name); |
1629 | + |
1630 | + if (runstop > 0 || |
1631 | + (working + preexist + expansion) >= |
1632 | + content->array.working_disks) { |
1633 | + int err; |
1634 | + |
1635 | + if (start_reshape) { |
1636 | + int spare = content->array.raid_disks + expansion; |
1637 | + if (restore_backup(st, content, |
1638 | + working, |
1639 | + spare, backup_file, verbose) == 1) |
1640 | + return 1; |
1641 | + |
1642 | + err = sysfs_set_str(content, NULL, |
1643 | + "array_state", "readonly"); |
1644 | + if (err) |
1645 | + return 1; |
1646 | + |
1647 | + if (st->ss->external) { |
1648 | + if (!mdmon_running(st->container_dev)) |
1649 | + start_mdmon(st->container_dev); |
1650 | + ping_monitor_by_id(st->container_dev); |
1651 | + if (mdmon_running(st->container_dev) && |
1652 | + st->update_tail == NULL) |
1653 | + st->update_tail = &st->updates; |
1654 | + } |
1655 | + |
1656 | + err = Grow_continue(mdfd, st, content, backup_file, |
1657 | + freeze_reshape); |
1658 | + } else switch(content->array.level) { |
1659 | + case LEVEL_LINEAR: |
1660 | + case LEVEL_MULTIPATH: |
1661 | + case 0: |
1662 | + err = sysfs_set_str(content, NULL, "array_state", |
1663 | + "active"); |
1664 | + break; |
1665 | + default: |
1666 | + err = sysfs_set_str(content, NULL, "array_state", |
1667 | + "readonly"); |
1668 | + /* start mdmon if needed. */ |
1669 | + if (!err) { |
1670 | + if (!mdmon_running(st->container_dev)) |
1671 | + start_mdmon(st->container_dev); |
1672 | + ping_monitor_by_id(st->container_dev); |
1673 | + } |
1674 | + break; |
1675 | + } |
1676 | + if (!err) |
1677 | + sysfs_set_safemode(content, content->safe_mode_delay); |
1678 | + |
1679 | + /* Block subarray here if it is not reshaped now |
1680 | + * It has be blocked a little later to allow mdmon to switch in |
1681 | + * in to R/W state |
1682 | + */ |
1683 | + if (st->ss->external && content->recovery_blocked && |
1684 | + !start_reshape) |
1685 | + block_subarray(content); |
1686 | + |
1687 | + if (verbose >= 0) { |
1688 | + if (err) |
1689 | + fprintf(stderr, Name |
1690 | + ": array %s now has %d device%s", |
1691 | + chosen_name, working + preexist, |
1692 | + working + preexist == 1 ? "":"s"); |
1693 | + else |
1694 | + fprintf(stderr, Name |
1695 | + ": Started %s with %d device%s", |
1696 | + chosen_name, working + preexist, |
1697 | + working + preexist == 1 ? "":"s"); |
1698 | + if (preexist) |
1699 | + fprintf(stderr, " (%d new)", working); |
1700 | + if (expansion) |
1701 | + fprintf(stderr, " ( + %d for expansion)", |
1702 | + expansion); |
1703 | + fprintf(stderr, "\n"); |
1704 | + } |
1705 | + if (!err) |
1706 | + wait_for(chosen_name, mdfd); |
1707 | + return err; |
1708 | + /* FIXME should have an O_EXCL and wait for read-auto */ |
1709 | + } else { |
1710 | + if (verbose >= 0) { |
1711 | + fprintf(stderr, Name |
1712 | + ": %s assembled with %d device%s", |
1713 | + chosen_name, preexist + working, |
1714 | + preexist + working == 1 ? "":"s"); |
1715 | + if (preexist) |
1716 | + fprintf(stderr, " (%d new)", working); |
1717 | + fprintf(stderr, " but not started\n"); |
1718 | + } |
1719 | + return 1; |
1720 | + } |
1721 | +} |
1722 | +#endif |
1723 | + |
1724 | |
1725 | === removed file '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/Assemble.c' |
1726 | --- .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/Assemble.c 2012-02-09 16:53:02 +0000 |
1727 | +++ .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/Assemble.c 1970-01-01 00:00:00 +0000 |
1728 | @@ -1,1650 +0,0 @@ |
1729 | -/* |
1730 | - * mdadm - manage Linux "md" devices aka RAID arrays. |
1731 | - * |
1732 | - * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de> |
1733 | - * |
1734 | - * |
1735 | - * This program is free software; you can redistribute it and/or modify |
1736 | - * it under the terms of the GNU General Public License as published by |
1737 | - * the Free Software Foundation; either version 2 of the License, or |
1738 | - * (at your option) any later version. |
1739 | - * |
1740 | - * This program is distributed in the hope that it will be useful, |
1741 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1742 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1743 | - * GNU General Public License for more details. |
1744 | - * |
1745 | - * You should have received a copy of the GNU General Public License |
1746 | - * along with this program; if not, write to the Free Software |
1747 | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1748 | - * |
1749 | - * Author: Neil Brown |
1750 | - * Email: <neilb@suse.de> |
1751 | - */ |
1752 | - |
1753 | -#include "mdadm.h" |
1754 | -#include <ctype.h> |
1755 | - |
1756 | -static int name_matches(char *found, char *required, char *homehost) |
1757 | -{ |
1758 | - /* See if the name found matches the required name, possibly |
1759 | - * prefixed with 'homehost' |
1760 | - */ |
1761 | - char fnd[33]; |
1762 | - |
1763 | - strncpy(fnd, found, 32); |
1764 | - fnd[32] = 0; |
1765 | - if (strcmp(found, required)==0) |
1766 | - return 1; |
1767 | - if (homehost) { |
1768 | - int l = strlen(homehost); |
1769 | - if (l < 32 && fnd[l] == ':' && |
1770 | - strcmp(fnd+l+1, required)==0) |
1771 | - return 1; |
1772 | - } |
1773 | - return 0; |
1774 | -} |
1775 | - |
1776 | -static int is_member_busy(char *metadata_version) |
1777 | -{ |
1778 | - /* check if the given member array is active */ |
1779 | - struct mdstat_ent *mdstat = mdstat_read(1, 0); |
1780 | - struct mdstat_ent *ent; |
1781 | - int busy = 0; |
1782 | - |
1783 | - for (ent = mdstat; ent; ent = ent->next) { |
1784 | - if (ent->metadata_version == NULL) |
1785 | - continue; |
1786 | - if (strncmp(ent->metadata_version, "external:", 9) != 0) |
1787 | - continue; |
1788 | - if (!is_subarray(&ent->metadata_version[9])) |
1789 | - continue; |
1790 | - /* Skip first char - it can be '/' or '-' */ |
1791 | - if (strcmp(&ent->metadata_version[10], metadata_version+1) == 0) { |
1792 | - busy = 1; |
1793 | - break; |
1794 | - } |
1795 | - } |
1796 | - free_mdstat(mdstat); |
1797 | - |
1798 | - return busy; |
1799 | -} |
1800 | - |
1801 | -static int ident_matches(struct mddev_ident *ident, |
1802 | - struct mdinfo *content, |
1803 | - struct supertype *tst, |
1804 | - char *homehost, |
1805 | - char *update, char *devname) |
1806 | -{ |
1807 | - |
1808 | - if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) && |
1809 | - same_uuid(content->uuid, ident->uuid, tst->ss->swapuuid)==0 && |
1810 | - memcmp(content->uuid, uuid_zero, sizeof(int[4])) != 0) { |
1811 | - if (devname) |
1812 | - fprintf(stderr, Name ": %s has wrong uuid.\n", |
1813 | - devname); |
1814 | - return 0; |
1815 | - } |
1816 | - if (ident->name[0] && (!update || strcmp(update, "name")!= 0) && |
1817 | - name_matches(content->name, ident->name, homehost)==0) { |
1818 | - if (devname) |
1819 | - fprintf(stderr, Name ": %s has wrong name.\n", |
1820 | - devname); |
1821 | - return 0; |
1822 | - } |
1823 | - if (ident->super_minor != UnSet && |
1824 | - ident->super_minor != content->array.md_minor) { |
1825 | - if (devname) |
1826 | - fprintf(stderr, Name ": %s has wrong super-minor.\n", |
1827 | - devname); |
1828 | - return 0; |
1829 | - } |
1830 | - if (ident->level != UnSet && |
1831 | - ident->level != content->array.level) { |
1832 | - if (devname) |
1833 | - fprintf(stderr, Name ": %s has wrong raid level.\n", |
1834 | - devname); |
1835 | - return 0; |
1836 | - } |
1837 | - if (ident->raid_disks != UnSet && |
1838 | - ident->raid_disks!= content->array.raid_disks) { |
1839 | - if (devname) |
1840 | - fprintf(stderr, Name ": %s requires wrong number of drives.\n", |
1841 | - devname); |
1842 | - return 0; |
1843 | - } |
1844 | - if (ident->member && ident->member[0]) { |
1845 | - /* content->text_version must match */ |
1846 | - char *s = strchr(content->text_version+1, '/'); |
1847 | - if (s == NULL) { |
1848 | - if (devname) |
1849 | - fprintf(stderr, Name ": %s is not a container and one is required.\n", |
1850 | - devname); |
1851 | - return 0; |
1852 | - } else if (strcmp(ident->member, s+1) != 0) { |
1853 | - if (devname) |
1854 | - fprintf(stderr, Name ": skipping wrong member %s is %s\n", |
1855 | - content->text_version, devname); |
1856 | - return 0; |
1857 | - } |
1858 | - } |
1859 | - return 1; |
1860 | -} |
1861 | - |
1862 | - |
1863 | -int Assemble(struct supertype *st, char *mddev, |
1864 | - struct mddev_ident *ident, |
1865 | - struct mddev_dev *devlist, |
1866 | - char *backup_file, int invalid_backup, |
1867 | - int readonly, int runstop, |
1868 | - char *update, char *homehost, int require_homehost, |
1869 | - int verbose, int force, int freeze_reshape) |
1870 | -{ |
1871 | - /* |
1872 | - * The task of Assemble is to find a collection of |
1873 | - * devices that should (according to their superblocks) |
1874 | - * form an array, and to give this collection to the MD driver. |
1875 | - * In Linux-2.4 and later, this involves submitting a |
1876 | - * SET_ARRAY_INFO ioctl with no arg - to prepare |
1877 | - * the array - and then submit a number of |
1878 | - * ADD_NEW_DISK ioctls to add disks into |
1879 | - * the array. Finally RUN_ARRAY might |
1880 | - * be submitted to start the array. |
1881 | - * |
1882 | - * Much of the work of Assemble is in finding and/or |
1883 | - * checking the disks to make sure they look right. |
1884 | - * |
1885 | - * If mddev is not set, then scan must be set and we |
1886 | - * read through the config file for dev+uuid mapping |
1887 | - * We recurse, setting mddev, for each device that |
1888 | - * - isn't running |
1889 | - * - has a valid uuid (or any uuid if !uuidset) |
1890 | - * |
1891 | - * If mddev is set, we try to determine state of md. |
1892 | - * check version - must be at least 0.90.0 |
1893 | - * check kernel version. must be at least 2.4. |
1894 | - * If not, we can possibly fall back on START_ARRAY |
1895 | - * Try to GET_ARRAY_INFO. |
1896 | - * If possible, give up |
1897 | - * If not, try to STOP_ARRAY just to make sure |
1898 | - * |
1899 | - * If !uuidset and scan, look in conf-file for uuid |
1900 | - * If not found, give up |
1901 | - * If !devlist and scan and uuidset, get list of devs from conf-file |
1902 | - * |
1903 | - * For each device: |
1904 | - * Check superblock - discard if bad |
1905 | - * Check uuid (set if we don't have one) - discard if no match |
1906 | - * Check superblock similarity if we have a superblock - discard if different |
1907 | - * Record events, devicenum |
1908 | - * This should give us a list of devices for the array |
1909 | - * We should collect the most recent event number |
1910 | - * |
1911 | - * Count disks with recent enough event count |
1912 | - * While force && !enough disks |
1913 | - * Choose newest rejected disks, update event count |
1914 | - * mark clean and rewrite superblock |
1915 | - * If recent kernel: |
1916 | - * SET_ARRAY_INFO |
1917 | - * foreach device with recent events : ADD_NEW_DISK |
1918 | - * if runstop == 1 || "enough" disks and runstop==0 -> RUN_ARRAY |
1919 | - * If old kernel: |
1920 | - * Check the device numbers in superblock are right |
1921 | - * update superblock if any changes |
1922 | - * START_ARRAY |
1923 | - * |
1924 | - */ |
1925 | - int mdfd; |
1926 | - int clean; |
1927 | - int auto_assem = (mddev == NULL && !ident->uuid_set && |
1928 | - ident->super_minor == UnSet && ident->name[0] == 0 |
1929 | - && (ident->container == NULL || ident->member == NULL)); |
1930 | - int old_linux = 0; |
1931 | - int vers = vers; /* Keep gcc quite - it really is initialised */ |
1932 | - struct { |
1933 | - char *devname; |
1934 | - int uptodate; /* set once we decide that this device is as |
1935 | - * recent as everything else in the array. |
1936 | - */ |
1937 | - struct mdinfo i; |
1938 | - } *devices; |
1939 | - char *devmap; |
1940 | - int *best = NULL; /* indexed by raid_disk */ |
1941 | - int bestcnt = 0; |
1942 | - int devcnt = 0; |
1943 | - unsigned int okcnt, sparecnt, rebuilding_cnt; |
1944 | - unsigned int req_cnt; |
1945 | - int i; |
1946 | - int most_recent = 0; |
1947 | - int chosen_drive; |
1948 | - int change = 0; |
1949 | - int inargv = 0; |
1950 | - int report_missmatch; |
1951 | -#ifndef MDASSEMBLE |
1952 | - int bitmap_done; |
1953 | -#endif |
1954 | - int start_partial_ok = (runstop >= 0) && |
1955 | - (force || devlist==NULL || auto_assem); |
1956 | - unsigned int num_devs; |
1957 | - struct mddev_dev *tmpdev; |
1958 | - struct mdinfo info; |
1959 | - struct mdinfo *content = NULL; |
1960 | - char *avail; |
1961 | - int nextspare = 0; |
1962 | - char *name = NULL; |
1963 | - int trustworthy; |
1964 | - char chosen_name[1024]; |
1965 | - struct domainlist *domains = NULL; |
1966 | - |
1967 | - if (get_linux_version() < 2004000) |
1968 | - old_linux = 1; |
1969 | - |
1970 | - /* |
1971 | - * If any subdevs are listed, then any that don't |
1972 | - * match ident are discarded. Remainder must all match and |
1973 | - * become the array. |
1974 | - * If no subdevs, then we scan all devices in the config file, but |
1975 | - * there must be something in the identity |
1976 | - */ |
1977 | - |
1978 | - if (!devlist && |
1979 | - ident->uuid_set == 0 && |
1980 | - (ident->super_minor < 0 || ident->super_minor == UnSet) && |
1981 | - ident->name[0] == 0 && |
1982 | - (ident->container == NULL || ident->member == NULL) && |
1983 | - ident->devices == NULL) { |
1984 | - fprintf(stderr, Name ": No identity information available for %s - cannot assemble.\n", |
1985 | - mddev ? mddev : "further assembly"); |
1986 | - return 1; |
1987 | - } |
1988 | - |
1989 | - if (devlist == NULL) |
1990 | - devlist = conf_get_devs(); |
1991 | - else if (mddev) |
1992 | - inargv = 1; |
1993 | - |
1994 | - report_missmatch = ((inargv && verbose >= 0) || verbose > 0); |
1995 | - try_again: |
1996 | - /* We come back here when doing auto-assembly and attempting some |
1997 | - * set of devices failed. Those are now marked as ->used==2 and |
1998 | - * we ignore them and try again |
1999 | - */ |
2000 | - |
2001 | - tmpdev = devlist; num_devs = 0; |
2002 | - while (tmpdev) { |
2003 | - if (tmpdev->used) |
2004 | - tmpdev->used = 2; |
2005 | - else |
2006 | - num_devs++; |
2007 | - tmpdev = tmpdev->next; |
2008 | - } |
2009 | - |
2010 | - if (!st && ident->st) st = ident->st; |
2011 | - |
2012 | - if (verbose>0) |
2013 | - fprintf(stderr, Name ": looking for devices for %s\n", |
2014 | - mddev ? mddev : "further assembly"); |
2015 | - |
2016 | - /* first walk the list of devices to find a consistent set |
2017 | - * that match the criterea, if that is possible. |
2018 | - * We flag the ones we like with 'used'. |
2019 | - */ |
2020 | - for (tmpdev = devlist; |
2021 | - tmpdev; |
2022 | - tmpdev = tmpdev ? tmpdev->next : NULL) { |
2023 | - char *devname = tmpdev->devname; |
2024 | - int dfd; |
2025 | - struct stat stb; |
2026 | - struct supertype *tst; |
2027 | - struct dev_policy *pol = NULL; |
2028 | - int found_container = 0; |
2029 | - |
2030 | - if (tmpdev->used > 1) continue; |
2031 | - |
2032 | - if (ident->devices && |
2033 | - !match_oneof(ident->devices, devname)) { |
2034 | - if (report_missmatch) |
2035 | - fprintf(stderr, Name ": %s is not one of %s\n", devname, ident->devices); |
2036 | - continue; |
2037 | - } |
2038 | - |
2039 | - tst = dup_super(st); |
2040 | - |
2041 | - dfd = dev_open(devname, O_RDONLY|O_EXCL); |
2042 | - if (dfd < 0) { |
2043 | - if (report_missmatch) |
2044 | - fprintf(stderr, Name ": cannot open device %s: %s\n", |
2045 | - devname, strerror(errno)); |
2046 | - tmpdev->used = 2; |
2047 | - } else if (fstat(dfd, &stb)< 0) { |
2048 | - /* Impossible! */ |
2049 | - fprintf(stderr, Name ": fstat failed for %s: %s\n", |
2050 | - devname, strerror(errno)); |
2051 | - tmpdev->used = 2; |
2052 | - } else if ((stb.st_mode & S_IFMT) != S_IFBLK) { |
2053 | - fprintf(stderr, Name ": %s is not a block device.\n", |
2054 | - devname); |
2055 | - tmpdev->used = 2; |
2056 | - } else if (must_be_container(dfd)) { |
2057 | - if (st) { |
2058 | - /* already found some components, this cannot |
2059 | - * be another one. |
2060 | - */ |
2061 | - if (report_missmatch) |
2062 | - fprintf(stderr, Name ": %s is a container, but we are looking for components\n", |
2063 | - devname); |
2064 | - tmpdev->used = 2; |
2065 | -#if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) |
2066 | - } if (!tst && (tst = super_by_fd(dfd, NULL)) == NULL) { |
2067 | - if (report_missmatch) |
2068 | - fprintf(stderr, Name ": not a recognisable container: %s\n", |
2069 | - devname); |
2070 | - tmpdev->used = 2; |
2071 | -#endif |
2072 | - } else if (!tst->ss->load_container |
2073 | - || tst->ss->load_container(tst, dfd, NULL)) { |
2074 | - if (report_missmatch) |
2075 | - fprintf(stderr, Name ": no correct container type: %s\n", |
2076 | - devname); |
2077 | - tmpdev->used = 2; |
2078 | - } else if (auto_assem && |
2079 | - !conf_test_metadata(tst->ss->name, (pol = devnum_policy(stb.st_rdev)), |
2080 | - tst->ss->match_home(tst, homehost) == 1)) { |
2081 | - if (report_missmatch) |
2082 | - fprintf(stderr, Name ": %s has metadata type %s for which " |
2083 | - "auto-assembly is disabled\n", |
2084 | - devname, tst->ss->name); |
2085 | - tmpdev->used = 2; |
2086 | - } else |
2087 | - found_container = 1; |
2088 | - } else { |
2089 | - if (!tst && (tst = guess_super(dfd)) == NULL) { |
2090 | - if (report_missmatch) |
2091 | - fprintf(stderr, Name ": no recogniseable superblock on %s\n", |
2092 | - devname); |
2093 | - tmpdev->used = 2; |
2094 | - } else if (tst->ss->load_super(tst,dfd, NULL)) { |
2095 | - if (report_missmatch) |
2096 | - fprintf(stderr, Name ": no RAID superblock on %s\n", |
2097 | - devname); |
2098 | - tmpdev->used = 2; |
2099 | - } else if (tst->ss->compare_super == NULL) { |
2100 | - if (report_missmatch) |
2101 | - fprintf(stderr, Name ": Cannot assemble %s metadata on %s\n", |
2102 | - tst->ss->name, devname); |
2103 | - tmpdev->used = 2; |
2104 | - } else if (auto_assem && st == NULL && |
2105 | - !conf_test_metadata(tst->ss->name, (pol = devnum_policy(stb.st_rdev)), |
2106 | - tst->ss->match_home(tst, homehost) == 1)) { |
2107 | - if (report_missmatch) |
2108 | - fprintf(stderr, Name ": %s has metadata type %s for which " |
2109 | - "auto-assembly is disabled\n", |
2110 | - devname, tst->ss->name); |
2111 | - tmpdev->used = 2; |
2112 | - } |
2113 | - } |
2114 | - if (dfd >= 0) close(dfd); |
2115 | - if (tmpdev->used == 2) { |
2116 | - if (auto_assem || !inargv) |
2117 | - /* Ignore unrecognised devices during auto-assembly */ |
2118 | - goto loop; |
2119 | - if (ident->uuid_set || ident->name[0] || |
2120 | - ident->super_minor != UnSet) |
2121 | - /* Ignore unrecognised device if looking for |
2122 | - * specific array */ |
2123 | - goto loop; |
2124 | - |
2125 | - |
2126 | - fprintf(stderr, Name ": %s has no superblock - assembly aborted\n", |
2127 | - devname); |
2128 | - if (st) |
2129 | - st->ss->free_super(st); |
2130 | - dev_policy_free(pol); |
2131 | - domain_free(domains); |
2132 | - return 1; |
2133 | - } |
2134 | - |
2135 | - if (found_container) { |
2136 | - /* tmpdev is a container. We need to be either |
2137 | - * looking for a member, or auto-assembling |
2138 | - */ |
2139 | - |
2140 | - if (ident->container) { |
2141 | - if (ident->container[0] == '/' && |
2142 | - !same_dev(ident->container, devname)) { |
2143 | - if (report_missmatch) |
2144 | - fprintf(stderr, Name ": %s is not the container required (%s)\n", |
2145 | - devname, ident->container); |
2146 | - goto loop; |
2147 | - } |
2148 | - if (ident->container[0] != '/') { |
2149 | - /* we have a uuid */ |
2150 | - int uuid[4]; |
2151 | - |
2152 | - content = &info; |
2153 | - tst->ss->getinfo_super(tst, content, NULL); |
2154 | - |
2155 | - if (!parse_uuid(ident->container, uuid) || |
2156 | - !same_uuid(content->uuid, uuid, tst->ss->swapuuid)) { |
2157 | - if (report_missmatch) |
2158 | - fprintf(stderr, Name ": %s has wrong UUID to be required container\n", |
2159 | - devname); |
2160 | - goto loop; |
2161 | - } |
2162 | - } |
2163 | - } |
2164 | - /* It is worth looking inside this container. |
2165 | - */ |
2166 | - if (verbose > 0) |
2167 | - fprintf(stderr, Name ": looking in container %s\n", |
2168 | - devname); |
2169 | - |
2170 | - for (content = tst->ss->container_content(tst, NULL); |
2171 | - content; |
2172 | - content = content->next) { |
2173 | - |
2174 | - if (!ident_matches(ident, content, tst, |
2175 | - homehost, update, |
2176 | - report_missmatch ? devname : NULL)) |
2177 | - /* message already printed */; |
2178 | - else if (is_member_busy(content->text_version)) { |
2179 | - if (report_missmatch) |
2180 | - fprintf(stderr, Name ": member %s in %s is already assembled\n", |
2181 | - content->text_version, |
2182 | - devname); |
2183 | - } else if (content->array.state & (1<<MD_SB_BLOCK_VOLUME)) { |
2184 | - /* do not assemble arrays with unsupported configurations */ |
2185 | - fprintf(stderr, Name ": Cannot activate member %s in %s.\n", |
2186 | - content->text_version, |
2187 | - devname); |
2188 | - } else |
2189 | - break; |
2190 | - } |
2191 | - if (!content) { |
2192 | - tmpdev->used = 2; |
2193 | - goto loop; /* empty container */ |
2194 | - } |
2195 | - |
2196 | - st = tst; tst = NULL; |
2197 | - if (!auto_assem && inargv && tmpdev->next != NULL) { |
2198 | - fprintf(stderr, Name ": %s is a container, but is not " |
2199 | - "only device given: confused and aborting\n", |
2200 | - devname); |
2201 | - st->ss->free_super(st); |
2202 | - dev_policy_free(pol); |
2203 | - domain_free(domains); |
2204 | - return 1; |
2205 | - } |
2206 | - if (verbose > 0) |
2207 | - fprintf(stderr, Name ": found match on member %s in %s\n", |
2208 | - content->text_version, devname); |
2209 | - |
2210 | - /* make sure we finished the loop */ |
2211 | - tmpdev = NULL; |
2212 | - goto loop; |
2213 | - } else { |
2214 | - |
2215 | - content = &info; |
2216 | - tst->ss->getinfo_super(tst, content, NULL); |
2217 | - |
2218 | - if (!ident_matches(ident, content, tst, |
2219 | - homehost, update, |
2220 | - report_missmatch ? devname : NULL)) |
2221 | - goto loop; |
2222 | - |
2223 | - if (st == NULL) |
2224 | - st = dup_super(tst); |
2225 | - if (st->minor_version == -1) |
2226 | - st->minor_version = tst->minor_version; |
2227 | - |
2228 | - if (memcmp(content->uuid, uuid_zero, |
2229 | - sizeof(int[4])) == 0) { |
2230 | - /* this is a floating spare. It cannot define |
2231 | - * an array unless there are no more arrays of |
2232 | - * this type to be found. It can be included |
2233 | - * in an array of this type though. |
2234 | - */ |
2235 | - tmpdev->used = 3; |
2236 | - goto loop; |
2237 | - } |
2238 | - |
2239 | - if (st->ss != tst->ss || |
2240 | - st->minor_version != tst->minor_version || |
2241 | - st->ss->compare_super(st, tst) != 0) { |
2242 | - /* Some mismatch. If exactly one array matches this host, |
2243 | - * we can resolve on that one. |
2244 | - * Or, if we are auto assembling, we just ignore the second |
2245 | - * for now. |
2246 | - */ |
2247 | - if (auto_assem) |
2248 | - goto loop; |
2249 | - if (homehost) { |
2250 | - int first = st->ss->match_home(st, homehost); |
2251 | - int last = tst->ss->match_home(tst, homehost); |
2252 | - if (first != last && |
2253 | - (first == 1 || last == 1)) { |
2254 | - /* We can do something */ |
2255 | - if (first) {/* just ignore this one */ |
2256 | - if (report_missmatch) |
2257 | - fprintf(stderr, Name ": %s misses out due to wrong homehost\n", |
2258 | - devname); |
2259 | - goto loop; |
2260 | - } else { /* reject all those sofar */ |
2261 | - struct mddev_dev *td; |
2262 | - if (report_missmatch) |
2263 | - fprintf(stderr, Name ": %s overrides previous devices due to good homehost\n", |
2264 | - devname); |
2265 | - for (td=devlist; td != tmpdev; td=td->next) |
2266 | - if (td->used == 1) |
2267 | - td->used = 0; |
2268 | - tmpdev->used = 1; |
2269 | - goto loop; |
2270 | - } |
2271 | - } |
2272 | - } |
2273 | - fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n", |
2274 | - devname); |
2275 | - tst->ss->free_super(tst); |
2276 | - st->ss->free_super(st); |
2277 | - dev_policy_free(pol); |
2278 | - domain_free(domains); |
2279 | - return 1; |
2280 | - } |
2281 | - tmpdev->used = 1; |
2282 | - } |
2283 | - loop: |
2284 | - /* Collect domain information from members only */ |
2285 | - if (tmpdev && tmpdev->used == 1) { |
2286 | - if (!pol) |
2287 | - pol = devnum_policy(stb.st_rdev); |
2288 | - domain_merge(&domains, pol, tst?tst->ss->name:NULL); |
2289 | - } |
2290 | - dev_policy_free(pol); |
2291 | - pol = NULL; |
2292 | - if (tst) |
2293 | - tst->ss->free_super(tst); |
2294 | - } |
2295 | - |
2296 | - /* Check if we found some imsm spares but no members */ |
2297 | - if ((auto_assem || |
2298 | - (ident->uuid_set && |
2299 | - memcmp(uuid_zero, ident->uuid,sizeof(uuid_zero)) == 0)) && |
2300 | - (!st || !st->sb)) |
2301 | - for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) { |
2302 | - if (tmpdev->used != 3) |
2303 | - continue; |
2304 | - tmpdev->used = 1; |
2305 | - content = &info; |
2306 | - |
2307 | - if (!st->sb) { |
2308 | - /* we need sb from one of the spares */ |
2309 | - int dfd = dev_open(tmpdev->devname, O_RDONLY); |
2310 | - if (dfd < 0 || |
2311 | - st->ss->load_super(st, dfd, NULL)) |
2312 | - tmpdev->used = 2; |
2313 | - if (dfd > 0) |
2314 | - close(dfd); |
2315 | - } |
2316 | - } |
2317 | - |
2318 | - /* Now reject spares that don't match domains of identified members */ |
2319 | - for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) { |
2320 | - struct stat stb; |
2321 | - if (tmpdev->used != 3) |
2322 | - continue; |
2323 | - if (stat(tmpdev->devname, &stb)< 0) { |
2324 | - fprintf(stderr, Name ": fstat failed for %s: %s\n", |
2325 | - tmpdev->devname, strerror(errno)); |
2326 | - tmpdev->used = 2; |
2327 | - } else { |
2328 | - struct dev_policy *pol = devnum_policy(stb.st_rdev); |
2329 | - int dt = domain_test(domains, pol, NULL); |
2330 | - if (inargv && dt != 0) |
2331 | - /* take this spare as domains match |
2332 | - * if there are any */ |
2333 | - tmpdev->used = 1; |
2334 | - else if (!inargv && dt == 1) |
2335 | - /* device wasn't explicitly listed, so need |
2336 | - * explicit domain match - which we have */ |
2337 | - tmpdev->used = 1; |
2338 | - else |
2339 | - /* if domains don't match mark as unused */ |
2340 | - tmpdev->used = 0; |
2341 | - dev_policy_free(pol); |
2342 | - } |
2343 | - } |
2344 | - domain_free(domains); |
2345 | - |
2346 | - if (!st || !st->sb || !content) |
2347 | - return 2; |
2348 | - |
2349 | - /* Now need to open the array device. Use create_mddev */ |
2350 | - if (content == &info) |
2351 | - st->ss->getinfo_super(st, content, NULL); |
2352 | - |
2353 | - trustworthy = FOREIGN; |
2354 | - name = content->name; |
2355 | - switch (st->ss->match_home(st, homehost) |
2356 | - ?: st->ss->match_home(st, "any")) { |
2357 | - case 1: |
2358 | - trustworthy = LOCAL; |
2359 | - name = strchr(content->name, ':'); |
2360 | - if (name) |
2361 | - name++; |
2362 | - else |
2363 | - name = content->name; |
2364 | - break; |
2365 | - } |
2366 | - if (!auto_assem) |
2367 | - /* If the array is listed in mdadm.conf or on |
2368 | - * command line, then we trust the name |
2369 | - * even if the array doesn't look local |
2370 | - */ |
2371 | - trustworthy = LOCAL; |
2372 | - |
2373 | - if (name[0] == 0 && |
2374 | - content->array.level == LEVEL_CONTAINER) { |
2375 | - name = content->text_version; |
2376 | - trustworthy = METADATA; |
2377 | - } |
2378 | - |
2379 | - if (name[0] && trustworthy != LOCAL && |
2380 | - ! require_homehost && |
2381 | - conf_name_is_free(name)) |
2382 | - trustworthy = LOCAL; |
2383 | - |
2384 | - if (trustworthy == LOCAL && |
2385 | - strchr(name, ':')) |
2386 | - /* Ignore 'host:' prefix of name */ |
2387 | - name = strchr(name, ':')+1; |
2388 | - |
2389 | - mdfd = create_mddev(mddev, name, ident->autof, trustworthy, |
2390 | - chosen_name); |
2391 | - if (mdfd < 0) { |
2392 | - st->ss->free_super(st); |
2393 | - if (auto_assem) |
2394 | - goto try_again; |
2395 | - return 1; |
2396 | - } |
2397 | - mddev = chosen_name; |
2398 | - vers = md_get_version(mdfd); |
2399 | - if (vers < 9000) { |
2400 | - fprintf(stderr, Name ": Assemble requires driver version 0.90.0 or later.\n" |
2401 | - " Upgrade your kernel or try --build\n"); |
2402 | - close(mdfd); |
2403 | - return 1; |
2404 | - } |
2405 | - if (mddev_busy(fd2devnum(mdfd))) { |
2406 | - fprintf(stderr, Name ": %s already active, cannot restart it!\n", |
2407 | - mddev); |
2408 | - for (tmpdev = devlist ; |
2409 | - tmpdev && tmpdev->used != 1; |
2410 | - tmpdev = tmpdev->next) |
2411 | - ; |
2412 | - if (tmpdev && auto_assem) |
2413 | - fprintf(stderr, Name ": %s needed for %s...\n", |
2414 | - mddev, tmpdev->devname); |
2415 | - close(mdfd); |
2416 | - mdfd = -3; |
2417 | - st->ss->free_super(st); |
2418 | - if (auto_assem) |
2419 | - goto try_again; |
2420 | - return 1; |
2421 | - } |
2422 | - ioctl(mdfd, STOP_ARRAY, NULL); /* just incase it was started but has no content */ |
2423 | - |
2424 | -#ifndef MDASSEMBLE |
2425 | - if (content != &info) { |
2426 | - /* This is a member of a container. Try starting the array. */ |
2427 | - int err; |
2428 | - err = assemble_container_content(st, mdfd, content, runstop, |
2429 | - chosen_name, verbose, |
2430 | - backup_file, freeze_reshape); |
2431 | - close(mdfd); |
2432 | - return err; |
2433 | - } |
2434 | - bitmap_done = 0; |
2435 | -#endif |
2436 | - /* Ok, no bad inconsistancy, we can try updating etc */ |
2437 | - devices = malloc(num_devs * sizeof(*devices)); |
2438 | - devmap = calloc(num_devs * content->array.raid_disks, 1); |
2439 | - for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) { |
2440 | - char *devname = tmpdev->devname; |
2441 | - struct stat stb; |
2442 | - /* looks like a good enough match to update the super block if needed */ |
2443 | -#ifndef MDASSEMBLE |
2444 | - if (update) { |
2445 | - int dfd; |
2446 | - /* prepare useful information in info structures */ |
2447 | - struct stat stb2; |
2448 | - struct supertype *tst; |
2449 | - int err; |
2450 | - fstat(mdfd, &stb2); |
2451 | - |
2452 | - if (strcmp(update, "uuid")==0 && |
2453 | - !ident->uuid_set) { |
2454 | - int rfd; |
2455 | - if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 || |
2456 | - read(rfd, ident->uuid, 16) != 16) { |
2457 | - *(__u32*)(ident->uuid) = random(); |
2458 | - *(__u32*)(ident->uuid+1) = random(); |
2459 | - *(__u32*)(ident->uuid+2) = random(); |
2460 | - *(__u32*)(ident->uuid+3) = random(); |
2461 | - } |
2462 | - if (rfd >= 0) close(rfd); |
2463 | - } |
2464 | - dfd = dev_open(devname, O_RDWR|O_EXCL); |
2465 | - |
2466 | - tst = dup_super(st); |
2467 | - if (dfd < 0 || tst->ss->load_super(tst, dfd, NULL) != 0) { |
2468 | - fprintf(stderr, Name ": cannot re-read metadata from %s - aborting\n", |
2469 | - devname); |
2470 | - if (dfd >= 0) |
2471 | - close(dfd); |
2472 | - close(mdfd); |
2473 | - free(devices); |
2474 | - free(devmap); |
2475 | - return 1; |
2476 | - } |
2477 | - tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks); |
2478 | - |
2479 | - memcpy(content->uuid, ident->uuid, 16); |
2480 | - strcpy(content->name, ident->name); |
2481 | - content->array.md_minor = minor(stb2.st_rdev); |
2482 | - |
2483 | - if (strcmp(update, "byteorder") == 0) |
2484 | - err = 0; |
2485 | - else |
2486 | - err = tst->ss->update_super(tst, content, update, |
2487 | - devname, verbose, |
2488 | - ident->uuid_set, |
2489 | - homehost); |
2490 | - if (err < 0) { |
2491 | - fprintf(stderr, |
2492 | - Name ": --update=%s not understood" |
2493 | - " for %s metadata\n", |
2494 | - update, tst->ss->name); |
2495 | - tst->ss->free_super(tst); |
2496 | - free(tst); |
2497 | - close(mdfd); |
2498 | - close(dfd); |
2499 | - free(devices); |
2500 | - free(devmap); |
2501 | - return 1; |
2502 | - } |
2503 | - if (strcmp(update, "uuid")==0 && |
2504 | - !ident->uuid_set) { |
2505 | - ident->uuid_set = 1; |
2506 | - memcpy(ident->uuid, content->uuid, 16); |
2507 | - } |
2508 | - if (tst->ss->store_super(tst, dfd)) |
2509 | - fprintf(stderr, Name ": Could not re-write superblock on %s.\n", |
2510 | - devname); |
2511 | - close(dfd); |
2512 | - |
2513 | - if (strcmp(update, "uuid")==0 && |
2514 | - ident->bitmap_fd >= 0 && !bitmap_done) { |
2515 | - if (bitmap_update_uuid(ident->bitmap_fd, |
2516 | - content->uuid, |
2517 | - tst->ss->swapuuid) != 0) |
2518 | - fprintf(stderr, Name ": Could not update uuid on external bitmap.\n"); |
2519 | - else |
2520 | - bitmap_done = 1; |
2521 | - } |
2522 | - tst->ss->free_super(tst); |
2523 | - } else |
2524 | -#endif |
2525 | - { |
2526 | - struct supertype *tst = dup_super(st); |
2527 | - int dfd; |
2528 | - dfd = dev_open(devname, O_RDWR|O_EXCL); |
2529 | - |
2530 | - if (dfd < 0 || tst->ss->load_super(tst, dfd, NULL) != 0) { |
2531 | - fprintf(stderr, Name ": cannot re-read metadata from %s - aborting\n", |
2532 | - devname); |
2533 | - if (dfd >= 0) |
2534 | - close(dfd); |
2535 | - close(mdfd); |
2536 | - free(devices); |
2537 | - free(devmap); |
2538 | - return 1; |
2539 | - } |
2540 | - tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks); |
2541 | - tst->ss->free_super(tst); |
2542 | - close(dfd); |
2543 | - } |
2544 | - |
2545 | - stat(devname, &stb); |
2546 | - |
2547 | - if (verbose > 0) |
2548 | - fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n", |
2549 | - devname, mddev, content->disk.raid_disk); |
2550 | - devices[devcnt].devname = devname; |
2551 | - devices[devcnt].uptodate = 0; |
2552 | - devices[devcnt].i = *content; |
2553 | - devices[devcnt].i.disk.major = major(stb.st_rdev); |
2554 | - devices[devcnt].i.disk.minor = minor(stb.st_rdev); |
2555 | - if (most_recent < devcnt) { |
2556 | - if (devices[devcnt].i.events |
2557 | - > devices[most_recent].i.events) |
2558 | - most_recent = devcnt; |
2559 | - } |
2560 | - if (content->array.level == LEVEL_MULTIPATH) |
2561 | - /* with multipath, the raid_disk from the superblock is meaningless */ |
2562 | - i = devcnt; |
2563 | - else |
2564 | - i = devices[devcnt].i.disk.raid_disk; |
2565 | - if (i+1 == 0) { |
2566 | - if (nextspare < content->array.raid_disks) |
2567 | - nextspare = content->array.raid_disks; |
2568 | - i = nextspare++; |
2569 | - } else { |
2570 | - if (i >= content->array.raid_disks && |
2571 | - i >= nextspare) |
2572 | - nextspare = i+1; |
2573 | - } |
2574 | - if (i < 10000) { |
2575 | - if (i >= bestcnt) { |
2576 | - int newbestcnt = i+10; |
2577 | - int *newbest = malloc(sizeof(int)*newbestcnt); |
2578 | - int c; |
2579 | - for (c=0; c < newbestcnt; c++) |
2580 | - if (c < bestcnt) |
2581 | - newbest[c] = best[c]; |
2582 | - else |
2583 | - newbest[c] = -1; |
2584 | - if (best)free(best); |
2585 | - best = newbest; |
2586 | - bestcnt = newbestcnt; |
2587 | - } |
2588 | - if (best[i] >=0 && |
2589 | - devices[best[i]].i.events |
2590 | - == devices[devcnt].i.events |
2591 | - && (devices[best[i]].i.disk.minor |
2592 | - != devices[devcnt].i.disk.minor) |
2593 | - && st->ss == &super0 |
2594 | - && content->array.level != LEVEL_MULTIPATH) { |
2595 | - /* two different devices with identical superblock. |
2596 | - * Could be a mis-detection caused by overlapping |
2597 | - * partitions. fail-safe. |
2598 | - */ |
2599 | - fprintf(stderr, Name ": WARNING %s and %s appear" |
2600 | - " to have very similar superblocks.\n" |
2601 | - " If they are really different, " |
2602 | - "please --zero the superblock on one\n" |
2603 | - " If they are the same or overlap," |
2604 | - " please remove one from %s.\n", |
2605 | - devices[best[i]].devname, devname, |
2606 | - inargv ? "the list" : |
2607 | - "the\n DEVICE list in mdadm.conf" |
2608 | - ); |
2609 | - close(mdfd); |
2610 | - free(devices); |
2611 | - free(devmap); |
2612 | - return 1; |
2613 | - } |
2614 | - if (best[i] == -1 |
2615 | - || (devices[best[i]].i.events |
2616 | - < devices[devcnt].i.events)) |
2617 | - best[i] = devcnt; |
2618 | - } |
2619 | - devcnt++; |
2620 | - } |
2621 | - |
2622 | - if (devcnt == 0) { |
2623 | - fprintf(stderr, Name ": no devices found for %s\n", |
2624 | - mddev); |
2625 | - if (st) |
2626 | - st->ss->free_super(st); |
2627 | - close(mdfd); |
2628 | - free(devices); |
2629 | - free(devmap); |
2630 | - return 1; |
2631 | - } |
2632 | - |
2633 | - if (update && strcmp(update, "byteorder")==0) |
2634 | - st->minor_version = 90; |
2635 | - |
2636 | - st->ss->getinfo_super(st, content, NULL); |
2637 | - clean = content->array.state & 1; |
2638 | - |
2639 | - /* now we have some devices that might be suitable. |
2640 | - * I wonder how many |
2641 | - */ |
2642 | - avail = malloc(content->array.raid_disks); |
2643 | - memset(avail, 0, content->array.raid_disks); |
2644 | - okcnt = 0; |
2645 | - sparecnt=0; |
2646 | - rebuilding_cnt=0; |
2647 | - for (i=0; i< bestcnt; i++) { |
2648 | - int j = best[i]; |
2649 | - int event_margin = 1; /* always allow a difference of '1' |
2650 | - * like the kernel does |
2651 | - */ |
2652 | - if (j < 0) continue; |
2653 | - /* note: we ignore error flags in multipath arrays |
2654 | - * as they don't make sense |
2655 | - */ |
2656 | - if (content->array.level != LEVEL_MULTIPATH) |
2657 | - if (!(devices[j].i.disk.state & (1<<MD_DISK_ACTIVE))) { |
2658 | - if (!(devices[j].i.disk.state |
2659 | - & (1<<MD_DISK_FAULTY))) { |
2660 | - devices[j].uptodate = 1; |
2661 | - sparecnt++; |
2662 | - } |
2663 | - continue; |
2664 | - } |
2665 | - /* If this devices thinks that 'most_recent' has failed, then |
2666 | - * we must reject this device. |
2667 | - */ |
2668 | - if (j != most_recent && |
2669 | - content->array.raid_disks > 0 && |
2670 | - devices[most_recent].i.disk.raid_disk >= 0 && |
2671 | - devmap[j * content->array.raid_disks + devices[most_recent].i.disk.raid_disk] == 0) { |
2672 | - if (verbose > -1) |
2673 | - fprintf(stderr, Name ": ignoring %s as it reports %s as failed\n", |
2674 | - devices[j].devname, devices[most_recent].devname); |
2675 | - best[i] = -1; |
2676 | - continue; |
2677 | - } |
2678 | - if (devices[j].i.events+event_margin >= |
2679 | - devices[most_recent].i.events) { |
2680 | - devices[j].uptodate = 1; |
2681 | - if (i < content->array.raid_disks) { |
2682 | - if (devices[j].i.recovery_start == MaxSector || |
2683 | - (content->reshape_active && |
2684 | - j >= content->array.raid_disks - content->delta_disks)) { |
2685 | - okcnt++; |
2686 | - avail[i]=1; |
2687 | - } else |
2688 | - rebuilding_cnt++; |
2689 | - } else |
2690 | - sparecnt++; |
2691 | - } |
2692 | - } |
2693 | - free(devmap); |
2694 | - while (force && !enough(content->array.level, content->array.raid_disks, |
2695 | - content->array.layout, 1, |
2696 | - avail, okcnt)) { |
2697 | - /* Choose the newest best drive which is |
2698 | - * not up-to-date, update the superblock |
2699 | - * and add it. |
2700 | - */ |
2701 | - int fd; |
2702 | - struct supertype *tst; |
2703 | - unsigned long long current_events; |
2704 | - chosen_drive = -1; |
2705 | - for (i = 0; i < content->array.raid_disks && i < bestcnt; i++) { |
2706 | - int j = best[i]; |
2707 | - if (j>=0 && |
2708 | - !devices[j].uptodate && |
2709 | - devices[j].i.recovery_start == MaxSector && |
2710 | - (chosen_drive < 0 || |
2711 | - devices[j].i.events |
2712 | - > devices[chosen_drive].i.events)) |
2713 | - chosen_drive = j; |
2714 | - } |
2715 | - if (chosen_drive < 0) |
2716 | - break; |
2717 | - current_events = devices[chosen_drive].i.events; |
2718 | - add_another: |
2719 | - if (verbose >= 0) |
2720 | - fprintf(stderr, Name ": forcing event count in %s(%d) from %d upto %d\n", |
2721 | - devices[chosen_drive].devname, |
2722 | - devices[chosen_drive].i.disk.raid_disk, |
2723 | - (int)(devices[chosen_drive].i.events), |
2724 | - (int)(devices[most_recent].i.events)); |
2725 | - fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL); |
2726 | - if (fd < 0) { |
2727 | - fprintf(stderr, Name ": Couldn't open %s for write - not updating\n", |
2728 | - devices[chosen_drive].devname); |
2729 | - devices[chosen_drive].i.events = 0; |
2730 | - continue; |
2731 | - } |
2732 | - tst = dup_super(st); |
2733 | - if (tst->ss->load_super(tst,fd, NULL)) { |
2734 | - close(fd); |
2735 | - fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n", |
2736 | - devices[chosen_drive].devname); |
2737 | - devices[chosen_drive].i.events = 0; |
2738 | - continue; |
2739 | - } |
2740 | - content->events = devices[most_recent].i.events; |
2741 | - tst->ss->update_super(tst, content, "force-one", |
2742 | - devices[chosen_drive].devname, verbose, |
2743 | - 0, NULL); |
2744 | - |
2745 | - if (tst->ss->store_super(tst, fd)) { |
2746 | - close(fd); |
2747 | - fprintf(stderr, Name ": Could not re-write superblock on %s\n", |
2748 | - devices[chosen_drive].devname); |
2749 | - devices[chosen_drive].i.events = 0; |
2750 | - tst->ss->free_super(tst); |
2751 | - continue; |
2752 | - } |
2753 | - close(fd); |
2754 | - devices[chosen_drive].i.events = devices[most_recent].i.events; |
2755 | - devices[chosen_drive].uptodate = 1; |
2756 | - avail[chosen_drive] = 1; |
2757 | - okcnt++; |
2758 | - tst->ss->free_super(tst); |
2759 | - |
2760 | - /* If there are any other drives of the same vintage, |
2761 | - * add them in as well. We can't lose and we might gain |
2762 | - */ |
2763 | - for (i = 0; i < content->array.raid_disks && i < bestcnt ; i++) { |
2764 | - int j = best[i]; |
2765 | - if (j >= 0 && |
2766 | - !devices[j].uptodate && |
2767 | - devices[j].i.events == current_events) { |
2768 | - chosen_drive = j; |
2769 | - goto add_another; |
2770 | - } |
2771 | - } |
2772 | - } |
2773 | - |
2774 | - /* Now we want to look at the superblock which the kernel will base things on |
2775 | - * and compare the devices that we think are working with the devices that the |
2776 | - * superblock thinks are working. |
2777 | - * If there are differences and --force is given, then update this chosen |
2778 | - * superblock. |
2779 | - */ |
2780 | - chosen_drive = -1; |
2781 | - st->ss->free_super(st); |
2782 | - for (i=0; chosen_drive < 0 && i<bestcnt; i++) { |
2783 | - int j = best[i]; |
2784 | - int fd; |
2785 | - |
2786 | - if (j<0) |
2787 | - continue; |
2788 | - if (!devices[j].uptodate) |
2789 | - continue; |
2790 | - if (devices[j].i.events < devices[most_recent].i.events) |
2791 | - continue; |
2792 | - chosen_drive = j; |
2793 | - if ((fd=dev_open(devices[j].devname, O_RDONLY|O_EXCL))< 0) { |
2794 | - fprintf(stderr, Name ": Cannot open %s: %s\n", |
2795 | - devices[j].devname, strerror(errno)); |
2796 | - close(mdfd); |
2797 | - free(devices); |
2798 | - return 1; |
2799 | - } |
2800 | - if (st->ss->load_super(st,fd, NULL)) { |
2801 | - close(fd); |
2802 | - fprintf(stderr, Name ": RAID superblock has disappeared from %s\n", |
2803 | - devices[j].devname); |
2804 | - close(mdfd); |
2805 | - free(devices); |
2806 | - return 1; |
2807 | - } |
2808 | - close(fd); |
2809 | - } |
2810 | - if (st->sb == NULL) { |
2811 | - fprintf(stderr, Name ": No suitable drives found for %s\n", mddev); |
2812 | - close(mdfd); |
2813 | - free(devices); |
2814 | - return 1; |
2815 | - } |
2816 | - st->ss->getinfo_super(st, content, NULL); |
2817 | -#ifndef MDASSEMBLE |
2818 | - sysfs_init(content, mdfd, 0); |
2819 | -#endif |
2820 | - for (i=0; i<bestcnt; i++) { |
2821 | - int j = best[i]; |
2822 | - unsigned int desired_state; |
2823 | - |
2824 | - if (i < content->array.raid_disks) |
2825 | - desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC); |
2826 | - else |
2827 | - desired_state = 0; |
2828 | - |
2829 | - if (j<0) |
2830 | - continue; |
2831 | - if (!devices[j].uptodate) |
2832 | - continue; |
2833 | - |
2834 | - devices[j].i.disk.state = desired_state; |
2835 | - if (!(devices[j].i.array.state & 1)) |
2836 | - clean = 0; |
2837 | - |
2838 | - if (st->ss->update_super(st, &devices[j].i, "assemble", NULL, |
2839 | - verbose, 0, NULL)) { |
2840 | - if (force) { |
2841 | - if (verbose >= 0) |
2842 | - fprintf(stderr, Name ": " |
2843 | - "clearing FAULTY flag for device %d in %s for %s\n", |
2844 | - j, mddev, devices[j].devname); |
2845 | - change = 1; |
2846 | - } else { |
2847 | - if (verbose >= -1) |
2848 | - fprintf(stderr, Name ": " |
2849 | - "device %d in %s has wrong state in superblock, but %s seems ok\n", |
2850 | - i, mddev, devices[j].devname); |
2851 | - } |
2852 | - } |
2853 | -#if 0 |
2854 | - if (!(super.disks[i].i.disk.state & (1 << MD_DISK_FAULTY))) { |
2855 | - fprintf(stderr, Name ": devices %d of %s is not marked FAULTY in superblock, but cannot be found\n", |
2856 | - i, mddev); |
2857 | - } |
2858 | -#endif |
2859 | - } |
2860 | - if (force && !clean && |
2861 | - !enough(content->array.level, content->array.raid_disks, |
2862 | - content->array.layout, clean, |
2863 | - avail, okcnt)) { |
2864 | - change += st->ss->update_super(st, content, "force-array", |
2865 | - devices[chosen_drive].devname, verbose, |
2866 | - 0, NULL); |
2867 | - clean = 1; |
2868 | - } |
2869 | - |
2870 | - if (change) { |
2871 | - int fd; |
2872 | - fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL); |
2873 | - if (fd < 0) { |
2874 | - fprintf(stderr, Name ": Could not open %s for write - cannot Assemble array.\n", |
2875 | - devices[chosen_drive].devname); |
2876 | - close(mdfd); |
2877 | - free(devices); |
2878 | - return 1; |
2879 | - } |
2880 | - if (st->ss->store_super(st, fd)) { |
2881 | - close(fd); |
2882 | - fprintf(stderr, Name ": Could not re-write superblock on %s\n", |
2883 | - devices[chosen_drive].devname); |
2884 | - close(mdfd); |
2885 | - free(devices); |
2886 | - return 1; |
2887 | - } |
2888 | - if (verbose >= 0) |
2889 | - fprintf(stderr, Name ": Marking array %s as 'clean'\n", |
2890 | - mddev); |
2891 | - close(fd); |
2892 | - } |
2893 | - |
2894 | - /* If we are in the middle of a reshape we may need to restore saved data |
2895 | - * that was moved aside due to the reshape overwriting live data |
2896 | - * The code of doing this lives in Grow.c |
2897 | - */ |
2898 | -#ifndef MDASSEMBLE |
2899 | - if (content->reshape_active) { |
2900 | - int err = 0; |
2901 | - int *fdlist = malloc(sizeof(int)* bestcnt); |
2902 | - if (verbose > 0) |
2903 | - fprintf(stderr, Name ":%s has an active reshape - checking " |
2904 | - "if critical section needs to be restored\n", |
2905 | - chosen_name); |
2906 | - for (i=0; i<bestcnt; i++) { |
2907 | - int j = best[i]; |
2908 | - if (j >= 0) { |
2909 | - fdlist[i] = dev_open(devices[j].devname, O_RDWR|O_EXCL); |
2910 | - if (fdlist[i] < 0) { |
2911 | - fprintf(stderr, Name ": Could not open %s for write - cannot Assemble array.\n", |
2912 | - devices[j].devname); |
2913 | - err = 1; |
2914 | - break; |
2915 | - } |
2916 | - } else |
2917 | - fdlist[i] = -1; |
2918 | - } |
2919 | - if (!err) { |
2920 | - if (st->ss->external && st->ss->recover_backup) |
2921 | - err = st->ss->recover_backup(st, content); |
2922 | - else |
2923 | - err = Grow_restart(st, content, fdlist, bestcnt, |
2924 | - backup_file, verbose > 0); |
2925 | - if (err && invalid_backup) { |
2926 | - if (verbose > 0) |
2927 | - fprintf(stderr, Name ": continuing" |
2928 | - " without restoring backup\n"); |
2929 | - err = 0; |
2930 | - } |
2931 | - } |
2932 | - while (i>0) { |
2933 | - i--; |
2934 | - if (fdlist[i]>=0) close(fdlist[i]); |
2935 | - } |
2936 | - if (err) { |
2937 | - fprintf(stderr, Name ": Failed to restore critical section for reshape, sorry.\n"); |
2938 | - if (backup_file == NULL) |
2939 | - fprintf(stderr," Possibly you needed to specify the --backup-file\n"); |
2940 | - close(mdfd); |
2941 | - free(devices); |
2942 | - return err; |
2943 | - } |
2944 | - } |
2945 | -#endif |
2946 | - /* count number of in-sync devices according to the superblock. |
2947 | - * We must have this number to start the array without -s or -R |
2948 | - */ |
2949 | - req_cnt = content->array.working_disks; |
2950 | - |
2951 | - /* Almost ready to actually *do* something */ |
2952 | - if (!old_linux) { |
2953 | - int rv; |
2954 | - |
2955 | - /* First, fill in the map, so that udev can find our name |
2956 | - * as soon as we become active. |
2957 | - */ |
2958 | - map_update(NULL, fd2devnum(mdfd), content->text_version, |
2959 | - content->uuid, chosen_name); |
2960 | - |
2961 | - rv = set_array_info(mdfd, st, content); |
2962 | - if (rv) { |
2963 | - fprintf(stderr, Name ": failed to set array info for %s: %s\n", |
2964 | - mddev, strerror(errno)); |
2965 | - ioctl(mdfd, STOP_ARRAY, NULL); |
2966 | - close(mdfd); |
2967 | - free(devices); |
2968 | - return 1; |
2969 | - } |
2970 | - if (ident->bitmap_fd >= 0) { |
2971 | - if (ioctl(mdfd, SET_BITMAP_FILE, ident->bitmap_fd) != 0) { |
2972 | - fprintf(stderr, Name ": SET_BITMAP_FILE failed.\n"); |
2973 | - ioctl(mdfd, STOP_ARRAY, NULL); |
2974 | - close(mdfd); |
2975 | - free(devices); |
2976 | - return 1; |
2977 | - } |
2978 | - } else if (ident->bitmap_file) { |
2979 | - /* From config file */ |
2980 | - int bmfd = open(ident->bitmap_file, O_RDWR); |
2981 | - if (bmfd < 0) { |
2982 | - fprintf(stderr, Name ": Could not open bitmap file %s\n", |
2983 | - ident->bitmap_file); |
2984 | - ioctl(mdfd, STOP_ARRAY, NULL); |
2985 | - close(mdfd); |
2986 | - free(devices); |
2987 | - return 1; |
2988 | - } |
2989 | - if (ioctl(mdfd, SET_BITMAP_FILE, bmfd) != 0) { |
2990 | - fprintf(stderr, Name ": Failed to set bitmapfile for %s\n", mddev); |
2991 | - close(bmfd); |
2992 | - ioctl(mdfd, STOP_ARRAY, NULL); |
2993 | - close(mdfd); |
2994 | - free(devices); |
2995 | - return 1; |
2996 | - } |
2997 | - close(bmfd); |
2998 | - } |
2999 | - |
3000 | - /* First, add the raid disks, but add the chosen one last */ |
3001 | - for (i=0; i<= bestcnt; i++) { |
3002 | - int j; |
3003 | - if (i < bestcnt) { |
3004 | - j = best[i]; |
3005 | - if (j == chosen_drive) |
3006 | - continue; |
3007 | - } else |
3008 | - j = chosen_drive; |
3009 | - |
3010 | - if (j >= 0 /* && devices[j].uptodate */) { |
3011 | - int dfd = dev_open(devices[j].devname, |
3012 | - O_RDWR|O_EXCL); |
3013 | - if (dfd >= 0) { |
3014 | - remove_partitions(dfd); |
3015 | - close(dfd); |
3016 | - } |
3017 | - rv = add_disk(mdfd, st, content, &devices[j].i); |
3018 | - |
3019 | - if (rv) { |
3020 | - fprintf(stderr, Name ": failed to add " |
3021 | - "%s to %s: %s\n", |
3022 | - devices[j].devname, |
3023 | - mddev, |
3024 | - strerror(errno)); |
3025 | - if (i < content->array.raid_disks |
3026 | - || i == bestcnt) |
3027 | - okcnt--; |
3028 | - else |
3029 | - sparecnt--; |
3030 | - } else if (verbose > 0) |
3031 | - fprintf(stderr, Name ": added %s " |
3032 | - "to %s as %d\n", |
3033 | - devices[j].devname, mddev, |
3034 | - devices[j].i.disk.raid_disk); |
3035 | - } else if (verbose > 0 && i < content->array.raid_disks) |
3036 | - fprintf(stderr, Name ": no uptodate device for " |
3037 | - "slot %d of %s\n", |
3038 | - i, mddev); |
3039 | - } |
3040 | - |
3041 | - if (content->array.level == LEVEL_CONTAINER) { |
3042 | - if (verbose >= 0) { |
3043 | - fprintf(stderr, Name ": Container %s has been " |
3044 | - "assembled with %d drive%s", |
3045 | - mddev, okcnt+sparecnt, okcnt+sparecnt==1?"":"s"); |
3046 | - if (okcnt < (unsigned)content->array.raid_disks) |
3047 | - fprintf(stderr, " (out of %d)", |
3048 | - content->array.raid_disks); |
3049 | - fprintf(stderr, "\n"); |
3050 | - } |
3051 | - st->ss->free_super(st); |
3052 | - sysfs_uevent(content, "change"); |
3053 | - wait_for(chosen_name, mdfd); |
3054 | - close(mdfd); |
3055 | - free(devices); |
3056 | - return 0; |
3057 | - } |
3058 | - |
3059 | - if (runstop == 1 || |
3060 | - (runstop <= 0 && |
3061 | - ( enough(content->array.level, content->array.raid_disks, |
3062 | - content->array.layout, clean, avail, okcnt) && |
3063 | - (okcnt + rebuilding_cnt >= req_cnt || start_partial_ok) |
3064 | - ))) { |
3065 | - /* This array is good-to-go. |
3066 | - * If a reshape is in progress then we might need to |
3067 | - * continue monitoring it. In that case we start |
3068 | - * it read-only and let the grow code make it writable. |
3069 | - */ |
3070 | - int rv; |
3071 | -#ifndef MDASSEMBLE |
3072 | - if (content->reshape_active && |
3073 | - content->delta_disks <= 0) { |
3074 | - rv = sysfs_set_str(content, NULL, |
3075 | - "array_state", "readonly"); |
3076 | - if (rv == 0) |
3077 | - rv = Grow_continue(mdfd, st, content, |
3078 | - backup_file, |
3079 | - freeze_reshape); |
3080 | - } else |
3081 | -#endif |
3082 | - rv = ioctl(mdfd, RUN_ARRAY, NULL); |
3083 | - if (rv == 0) { |
3084 | - if (verbose >= 0) { |
3085 | - fprintf(stderr, Name ": %s has been started with %d drive%s", |
3086 | - mddev, okcnt, okcnt==1?"":"s"); |
3087 | - if (okcnt < (unsigned)content->array.raid_disks) |
3088 | - fprintf(stderr, " (out of %d)", content->array.raid_disks); |
3089 | - if (rebuilding_cnt) |
3090 | - fprintf(stderr, "%s %d rebuilding", sparecnt?",":" and", rebuilding_cnt); |
3091 | - if (sparecnt) |
3092 | - fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); |
3093 | - fprintf(stderr, ".\n"); |
3094 | - } |
3095 | - if (content->reshape_active && |
3096 | - content->array.level >= 4 && |
3097 | - content->array.level <= 6) { |
3098 | - /* might need to increase the size |
3099 | - * of the stripe cache - default is 256 |
3100 | - */ |
3101 | - if (256 < 4 * (content->array.chunk_size/4096)) { |
3102 | - struct mdinfo *sra = sysfs_read(mdfd, 0, 0); |
3103 | - if (sra) |
3104 | - sysfs_set_num(sra, NULL, |
3105 | - "stripe_cache_size", |
3106 | - (4 * content->array.chunk_size / 4096) + 1); |
3107 | - sysfs_free(sra); |
3108 | - } |
3109 | - } |
3110 | - if (okcnt < (unsigned)content->array.raid_disks) { |
3111 | - /* If any devices did not get added |
3112 | - * because the kernel rejected them based |
3113 | - * on event count, try adding them |
3114 | - * again providing the action policy is |
3115 | - * 're-add' or greater. The bitmap |
3116 | - * might allow them to be included, or |
3117 | - * they will become spares. |
3118 | - */ |
3119 | - for (i = 0; i < bestcnt; i++) { |
3120 | - int j = best[i]; |
3121 | - if (j >= 0 && !devices[j].uptodate) { |
3122 | - if (!disk_action_allows(&devices[j].i, st->ss->name, act_re_add)) |
3123 | - continue; |
3124 | - rv = add_disk(mdfd, st, content, |
3125 | - &devices[j].i); |
3126 | - if (rv == 0 && verbose >= 0) |
3127 | - fprintf(stderr, |
3128 | - Name ": %s has been re-added.\n", |
3129 | - devices[j].devname); |
3130 | - } |
3131 | - } |
3132 | - } |
3133 | - wait_for(mddev, mdfd); |
3134 | - close(mdfd); |
3135 | - if (auto_assem) { |
3136 | - int usecs = 1; |
3137 | - /* There is a nasty race with 'mdadm --monitor'. |
3138 | - * If it opens this device before we close it, |
3139 | - * it gets an incomplete open on which IO |
3140 | - * doesn't work and the capacity is |
3141 | - * wrong. |
3142 | - * If we reopen (to check for layered devices) |
3143 | - * before --monitor closes, we loose. |
3144 | - * |
3145 | - * So: wait upto 1 second for there to be |
3146 | - * a non-zero capacity. |
3147 | - */ |
3148 | - while (usecs < 1000) { |
3149 | - mdfd = open(mddev, O_RDONLY); |
3150 | - if (mdfd >= 0) { |
3151 | - unsigned long long size; |
3152 | - if (get_dev_size(mdfd, NULL, &size) && |
3153 | - size > 0) |
3154 | - break; |
3155 | - close(mdfd); |
3156 | - } |
3157 | - usleep(usecs); |
3158 | - usecs <<= 1; |
3159 | - } |
3160 | - } |
3161 | - free(devices); |
3162 | - return 0; |
3163 | - } |
3164 | - fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n", |
3165 | - mddev, strerror(errno)); |
3166 | - |
3167 | - if (!enough(content->array.level, content->array.raid_disks, |
3168 | - content->array.layout, 1, avail, okcnt)) |
3169 | - fprintf(stderr, Name ": Not enough devices to " |
3170 | - "start the array.\n"); |
3171 | - else if (!enough(content->array.level, |
3172 | - content->array.raid_disks, |
3173 | - content->array.layout, clean, |
3174 | - avail, okcnt)) |
3175 | - fprintf(stderr, Name ": Not enough devices to " |
3176 | - "start the array while not clean " |
3177 | - "- consider --force.\n"); |
3178 | - |
3179 | - if (auto_assem) |
3180 | - ioctl(mdfd, STOP_ARRAY, NULL); |
3181 | - close(mdfd); |
3182 | - free(devices); |
3183 | - return 1; |
3184 | - } |
3185 | - if (runstop == -1) { |
3186 | - fprintf(stderr, Name ": %s assembled from %d drive%s", |
3187 | - mddev, okcnt, okcnt==1?"":"s"); |
3188 | - if (okcnt != (unsigned)content->array.raid_disks) |
3189 | - fprintf(stderr, " (out of %d)", content->array.raid_disks); |
3190 | - fprintf(stderr, ", but not started.\n"); |
3191 | - close(mdfd); |
3192 | - free(devices); |
3193 | - return 0; |
3194 | - } |
3195 | - if (verbose >= -1) { |
3196 | - fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s"); |
3197 | - if (rebuilding_cnt) |
3198 | - fprintf(stderr, "%s %d rebuilding", sparecnt?", ":" and ", rebuilding_cnt); |
3199 | - if (sparecnt) |
3200 | - fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); |
3201 | - if (!enough(content->array.level, content->array.raid_disks, |
3202 | - content->array.layout, 1, avail, okcnt)) |
3203 | - fprintf(stderr, " - not enough to start the array.\n"); |
3204 | - else if (!enough(content->array.level, |
3205 | - content->array.raid_disks, |
3206 | - content->array.layout, clean, |
3207 | - avail, okcnt)) |
3208 | - fprintf(stderr, " - not enough to start the " |
3209 | - "array while not clean - consider " |
3210 | - "--force.\n"); |
3211 | - else { |
3212 | - if (req_cnt == (unsigned)content->array.raid_disks) |
3213 | - fprintf(stderr, " - need all %d to start it", req_cnt); |
3214 | - else |
3215 | - fprintf(stderr, " - need %d of %d to start", req_cnt, content->array.raid_disks); |
3216 | - fprintf(stderr, " (use --run to insist).\n"); |
3217 | - } |
3218 | - } |
3219 | - if (auto_assem) |
3220 | - ioctl(mdfd, STOP_ARRAY, NULL); |
3221 | - close(mdfd); |
3222 | - free(devices); |
3223 | - return 1; |
3224 | - } else { |
3225 | - /* The "chosen_drive" is a good choice, and if necessary, the superblock has |
3226 | - * been updated to point to the current locations of devices. |
3227 | - * so we can just start the array |
3228 | - */ |
3229 | - unsigned long dev; |
3230 | - dev = makedev(devices[chosen_drive].i.disk.major, |
3231 | - devices[chosen_drive].i.disk.minor); |
3232 | - if (ioctl(mdfd, START_ARRAY, dev)) { |
3233 | - fprintf(stderr, Name ": Cannot start array: %s\n", |
3234 | - strerror(errno)); |
3235 | - } |
3236 | - |
3237 | - } |
3238 | - close(mdfd); |
3239 | - free(devices); |
3240 | - return 0; |
3241 | -} |
3242 | - |
3243 | -#ifndef MDASSEMBLE |
3244 | -int assemble_container_content(struct supertype *st, int mdfd, |
3245 | - struct mdinfo *content, int runstop, |
3246 | - char *chosen_name, int verbose, |
3247 | - char *backup_file, int freeze_reshape) |
3248 | -{ |
3249 | - struct mdinfo *dev, *sra; |
3250 | - int working = 0, preexist = 0; |
3251 | - int expansion = 0; |
3252 | - struct map_ent *map = NULL; |
3253 | - int old_raid_disks; |
3254 | - |
3255 | - sysfs_init(content, mdfd, 0); |
3256 | - |
3257 | - sra = sysfs_read(mdfd, 0, GET_VERSION); |
3258 | - if (sra == NULL || strcmp(sra->text_version, content->text_version) != 0) |
3259 | - if (sysfs_set_array(content, md_get_version(mdfd)) != 0) { |
3260 | - if (sra) |
3261 | - sysfs_free(sra); |
3262 | - return 1; |
3263 | - } |
3264 | - |
3265 | - if (st->ss->external && content->recovery_blocked) |
3266 | - block_subarray(content); |
3267 | - |
3268 | - if (sra) |
3269 | - sysfs_free(sra); |
3270 | - old_raid_disks = content->array.raid_disks - content->delta_disks; |
3271 | - for (dev = content->devs; dev; dev = dev->next) |
3272 | - if (sysfs_add_disk(content, dev, 1) == 0) { |
3273 | - if (dev->disk.raid_disk >= old_raid_disks && |
3274 | - content->reshape_active) |
3275 | - expansion++; |
3276 | - else |
3277 | - working++; |
3278 | - } else if (errno == EEXIST) |
3279 | - preexist++; |
3280 | - if (working == 0) |
3281 | - return 1;/* Nothing new, don't try to start */ |
3282 | - |
3283 | - map_update(&map, fd2devnum(mdfd), |
3284 | - content->text_version, |
3285 | - content->uuid, chosen_name); |
3286 | - |
3287 | - if (runstop > 0 || |
3288 | - (working + preexist + expansion) >= |
3289 | - content->array.working_disks) { |
3290 | - int err; |
3291 | - int start_reshape; |
3292 | - |
3293 | - /* There are two types of reshape: container wide or sub-array specific |
3294 | - * Check if metadata requests blocking container wide reshapes |
3295 | - */ |
3296 | - start_reshape = (content->reshape_active && |
3297 | - !((content->reshape_active == CONTAINER_RESHAPE) && |
3298 | - (content->array.state & (1<<MD_SB_BLOCK_CONTAINER_RESHAPE)))); |
3299 | - if (start_reshape) { |
3300 | - int spare = content->array.raid_disks + expansion; |
3301 | - if (restore_backup(st, content, |
3302 | - working, |
3303 | - spare, backup_file, verbose) == 1) |
3304 | - return 1; |
3305 | - |
3306 | - err = sysfs_set_str(content, NULL, |
3307 | - "array_state", "readonly"); |
3308 | - if (err) |
3309 | - return 1; |
3310 | - |
3311 | - if (st->ss->external) { |
3312 | - if (!mdmon_running(st->container_dev)) |
3313 | - start_mdmon(st->container_dev); |
3314 | - ping_monitor_by_id(st->container_dev); |
3315 | - if (mdmon_running(st->container_dev) && |
3316 | - st->update_tail == NULL) |
3317 | - st->update_tail = &st->updates; |
3318 | - } |
3319 | - |
3320 | - err = Grow_continue(mdfd, st, content, backup_file, |
3321 | - freeze_reshape); |
3322 | - } else switch(content->array.level) { |
3323 | - case LEVEL_LINEAR: |
3324 | - case LEVEL_MULTIPATH: |
3325 | - case 0: |
3326 | - err = sysfs_set_str(content, NULL, "array_state", |
3327 | - "active"); |
3328 | - break; |
3329 | - default: |
3330 | - err = sysfs_set_str(content, NULL, "array_state", |
3331 | - "readonly"); |
3332 | - /* start mdmon if needed. */ |
3333 | - if (!err) { |
3334 | - if (!mdmon_running(st->container_dev)) |
3335 | - start_mdmon(st->container_dev); |
3336 | - ping_monitor_by_id(st->container_dev); |
3337 | - } |
3338 | - break; |
3339 | - } |
3340 | - if (!err) |
3341 | - sysfs_set_safemode(content, content->safe_mode_delay); |
3342 | - if (verbose >= 0) { |
3343 | - if (err) |
3344 | - fprintf(stderr, Name |
3345 | - ": array %s now has %d device%s", |
3346 | - chosen_name, working + preexist, |
3347 | - working + preexist == 1 ? "":"s"); |
3348 | - else |
3349 | - fprintf(stderr, Name |
3350 | - ": Started %s with %d device%s", |
3351 | - chosen_name, working + preexist, |
3352 | - working + preexist == 1 ? "":"s"); |
3353 | - if (preexist) |
3354 | - fprintf(stderr, " (%d new)", working); |
3355 | - if (expansion) |
3356 | - fprintf(stderr, " ( + %d for expansion)", |
3357 | - expansion); |
3358 | - fprintf(stderr, "\n"); |
3359 | - } |
3360 | - if (!err) |
3361 | - wait_for(chosen_name, mdfd); |
3362 | - return err; |
3363 | - /* FIXME should have an O_EXCL and wait for read-auto */ |
3364 | - } else { |
3365 | - if (verbose >= 0) { |
3366 | - fprintf(stderr, Name |
3367 | - ": %s assembled with %d device%s", |
3368 | - chosen_name, preexist + working, |
3369 | - preexist + working == 1 ? "":"s"); |
3370 | - if (preexist) |
3371 | - fprintf(stderr, " (%d new)", working); |
3372 | - fprintf(stderr, " but not started\n"); |
3373 | - } |
3374 | - return 1; |
3375 | - } |
3376 | -} |
3377 | -#endif |
3378 | - |
3379 | |
3380 | === added file '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/ReadMe.c' |
3381 | --- .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/ReadMe.c 1970-01-01 00:00:00 +0000 |
3382 | +++ .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/ReadMe.c 2012-06-18 08:55:05 +0000 |
3383 | @@ -0,0 +1,608 @@ |
3384 | +/* |
3385 | + * mdadm - manage Linux "md" devices aka RAID arrays. |
3386 | + * |
3387 | + * Copyright (C) 2001-2010 Neil Brown <neilb@suse.de> |
3388 | + * |
3389 | + * |
3390 | + * This program is free software; you can redistribute it and/or modify |
3391 | + * it under the terms of the GNU General Public License as published by |
3392 | + * the Free Software Foundation; either version 2 of the License, or |
3393 | + * (at your option) any later version. |
3394 | + * |
3395 | + * This program is distributed in the hope that it will be useful, |
3396 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3397 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3398 | + * GNU General Public License for more details. |
3399 | + * |
3400 | + * You should have received a copy of the GNU General Public License |
3401 | + * along with this program; if not, write to the Free Software |
3402 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
3403 | + * |
3404 | + * Author: Neil Brown |
3405 | + * Email: <neilb@suse.de> |
3406 | + */ |
3407 | + |
3408 | +#include "mdadm.h" |
3409 | + |
3410 | +char Version[] = Name " - v3.2.5 - 18th May 2012\n"; |
3411 | + |
3412 | +/* |
3413 | + * File: ReadMe.c |
3414 | + * |
3415 | + * This file contains general comments about the implementation |
3416 | + * and the various usage messages that can be displayed by mdadm |
3417 | + * |
3418 | + * mdadm is a single program that can be used to control Linux md devices. |
3419 | + * It is intended to provide all the functionality of the mdtools and |
3420 | + * raidtools but with a very different interface. |
3421 | + * mdadm can perform all functions without a configuration file. |
3422 | + * There is the option of using a configuration file, but not in the same |
3423 | + * way that raidtools uses one |
3424 | + * raidtools uses a configuration file to describe how to create a RAID |
3425 | + * array, and also uses this file partially to start a previously |
3426 | + * created RAID array. Further, raidtools requires the configuration |
3427 | + * file for such things as stopping a raid array which needs to know |
3428 | + * nothing about the array. |
3429 | + * |
3430 | + * The configuration file that can be used by mdadm lists two |
3431 | + * different things: |
3432 | + * 1/ a mapping from uuid to md device to identify which arrays are |
3433 | + * expect and what names (numbers) they should be given |
3434 | + * 2/ a list of devices that should be scanned for md sub-devices |
3435 | + * |
3436 | + * |
3437 | + */ |
3438 | + |
3439 | +/* |
3440 | + * mdadm has 7 major modes of operation: |
3441 | + * 1/ Create |
3442 | + * This mode is used to create a new array with a superblock |
3443 | + * It can progress in several step create-add-add-run |
3444 | + * or it can all happen with one command |
3445 | + * 2/ Assemble |
3446 | + * This mode is used to assemble the parts of a previously created |
3447 | + * array into an active array. Components can be explicitly given |
3448 | + * or can be searched for. mdadm (optionally) check that the components |
3449 | + * do form a bona-fide array, and can, on request, fiddle superblock |
3450 | + * version numbers so as to assemble a faulty array. |
3451 | + * 3/ Build |
3452 | + * This is for building legacy arrays without superblocks |
3453 | + * 4/ Manage |
3454 | + * This is for doing something to one or more devices |
3455 | + * in an array, such as add,remove,fail. |
3456 | + * run/stop/readonly/readwrite are also available |
3457 | + * 5/ Misc |
3458 | + * This is for doing things to individual devices. |
3459 | + * They might be parts of an array so |
3460 | + * zero-superblock, examine might be appropriate |
3461 | + * They might be md arrays so |
3462 | + * run,stop,rw,ro,detail might be appropriate |
3463 | + * Also query will treat it as either |
3464 | + * 6/ Monitor |
3465 | + * This mode never exits but just monitors arrays and reports changes. |
3466 | + * 7/ Grow |
3467 | + * This mode allows for changing of key attributes of a raid array, such |
3468 | + * as size, number of devices, and possibly even layout. |
3469 | + * At the time if writing, there is only minimal support. |
3470 | + */ |
3471 | + |
3472 | +char short_options[]="-ABCDEFGIQhVXYWZ:vqbc:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:"; |
3473 | +char short_bitmap_options[]= |
3474 | + "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:"; |
3475 | +char short_bitmap_auto_options[]= |
3476 | + "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sa:rfRSow1tye:"; |
3477 | + |
3478 | +struct option long_options[] = { |
3479 | + {"manage", 0, 0, ManageOpt}, |
3480 | + {"misc", 0, 0, MiscOpt}, |
3481 | + {"assemble", 0, 0, 'A'}, |
3482 | + {"build", 0, 0, 'B'}, |
3483 | + {"create", 0, 0, 'C'}, |
3484 | + {"detail", 0, 0, 'D'}, |
3485 | + {"examine", 0, 0, 'E'}, |
3486 | + {"follow", 0, 0, 'F'}, |
3487 | + {"grow", 0, 0, 'G'}, |
3488 | + {"incremental",0,0, 'I'}, |
3489 | + {"zero-superblock", 0, 0, 'K'}, /* deliberately no a short_option */ |
3490 | + {"query", 0, 0, 'Q'}, |
3491 | + {"examine-bitmap", 0, 0, 'X'}, |
3492 | + {"auto-detect", 0, 0, AutoDetect}, |
3493 | + {"detail-platform", 0, 0, DetailPlatform}, |
3494 | + {"kill-subarray", 1, 0, KillSubarray}, |
3495 | + {"update-subarray", 1, 0, UpdateSubarray}, |
3496 | + {"udev-rules", 2, 0, UdevRules}, |
3497 | + {"offroot", 0, 0, OffRootOpt}, |
3498 | + |
3499 | + /* synonyms */ |
3500 | + {"monitor", 0, 0, 'F'}, |
3501 | + |
3502 | + /* after those will normally come the name of the md device */ |
3503 | + {"help", 0, 0, 'h'}, |
3504 | + {"help-options",0,0, HelpOptions}, |
3505 | + {"version", 0, 0, 'V'}, |
3506 | + {"verbose", 0, 0, 'v'}, |
3507 | + {"quiet", 0, 0, 'q'}, |
3508 | + |
3509 | + /* For create or build: */ |
3510 | + {"chunk", 1, 0, ChunkSize}, |
3511 | + {"rounding", 1, 0, ChunkSize}, /* for linear, chunk is really a |
3512 | + * rounding number */ |
3513 | + {"level", 1, 0, 'l'}, /* 0,1,4,5,6,linear */ |
3514 | + {"parity", 1, 0, Layout}, /* {left,right}-{a,}symmetric */ |
3515 | + {"layout", 1, 0, Layout}, |
3516 | + {"raid-disks",1, 0, 'n'}, |
3517 | + {"raid-devices",1, 0, 'n'}, |
3518 | + {"spare-disks",1,0, 'x'}, |
3519 | + {"spare-devices",1,0, 'x'}, |
3520 | + {"size", 1, 0, 'z'}, |
3521 | + {"auto", 1, 0, Auto}, /* also for --assemble */ |
3522 | + {"assume-clean",0,0, AssumeClean }, |
3523 | + {"metadata", 1, 0, 'e'}, /* superblock format */ |
3524 | + {"bitmap", 1, 0, Bitmap}, |
3525 | + {"bitmap-chunk", 1, 0, BitmapChunk}, |
3526 | + {"write-behind", 2, 0, WriteBehind}, |
3527 | + {"write-mostly",0, 0, WriteMostly}, |
3528 | + {"re-add", 0, 0, ReAdd}, |
3529 | + {"homehost", 1, 0, HomeHost}, |
3530 | + {"symlinks", 1, 0, Symlinks}, |
3531 | + |
3532 | + /* For assemble */ |
3533 | + {"uuid", 1, 0, 'u'}, |
3534 | + {"super-minor",1,0, SuperMinor}, |
3535 | + {"name", 1, 0, 'N'}, |
3536 | + {"config", 1, 0, ConfigFile}, |
3537 | + {"scan", 0, 0, 's'}, |
3538 | + {"force", 0, 0, Force}, |
3539 | + {"update", 1, 0, 'U'}, |
3540 | + {"freeze-reshape", 0, 0, FreezeReshape}, |
3541 | + |
3542 | + /* Management */ |
3543 | + {"add", 0, 0, Add}, |
3544 | + {"remove", 0, 0, Remove}, |
3545 | + {"fail", 0, 0, Fail}, |
3546 | + {"set-faulty",0, 0, Fail}, |
3547 | + {"run", 0, 0, 'R'}, |
3548 | + {"stop", 0, 0, 'S'}, |
3549 | + {"readonly", 0, 0, 'o'}, |
3550 | + {"readwrite", 0, 0, 'w'}, |
3551 | + {"no-degraded",0,0, NoDegraded }, |
3552 | + {"wait", 0, 0, WaitOpt}, |
3553 | + {"wait-clean", 0, 0, Waitclean }, |
3554 | + |
3555 | + /* For Detail/Examine */ |
3556 | + {"brief", 0, 0, Brief}, |
3557 | + {"export", 0, 0, 'Y'}, |
3558 | + {"sparc2.2", 0, 0, Sparc22}, |
3559 | + {"test", 0, 0, 't'}, |
3560 | + {"prefer", 1, 0, Prefer}, |
3561 | + |
3562 | + /* For Follow/monitor */ |
3563 | + {"mail", 1, 0, EMail}, |
3564 | + {"program", 1, 0, ProgramOpt}, |
3565 | + {"alert", 1, 0, ProgramOpt}, |
3566 | + {"increment", 1, 0, Increment}, |
3567 | + {"delay", 1, 0, 'd'}, |
3568 | + {"daemonise", 0, 0, Fork}, |
3569 | + {"daemonize", 0, 0, Fork}, |
3570 | + {"oneshot", 0, 0, '1'}, |
3571 | + {"pid-file", 1, 0, 'i'}, |
3572 | + {"syslog", 0, 0, 'y'}, |
3573 | + {"no-sharing", 0, 0, NoSharing}, |
3574 | + |
3575 | + /* For Grow */ |
3576 | + {"backup-file", 1,0, BackupFile}, |
3577 | + {"invalid-backup",0,0,InvalidBackup}, |
3578 | + {"array-size", 1, 0, 'Z'}, |
3579 | + {"continue", 0, 0, Continue}, |
3580 | + |
3581 | + /* For Incremental */ |
3582 | + {"rebuild-map", 0, 0, RebuildMapOpt}, |
3583 | + {"path", 1, 0, IncrementalPath}, |
3584 | + |
3585 | + {0, 0, 0, 0} |
3586 | +}; |
3587 | + |
3588 | +char Usage[] = |
3589 | +"Usage: mdadm --help\n" |
3590 | +" for help\n" |
3591 | +; |
3592 | + |
3593 | +char Help[] = |
3594 | +"mdadm is used for building, managing, and monitoring\n" |
3595 | +"Linux md devices (aka RAID arrays)\n" |
3596 | +"Usage: mdadm --create device options...\n" |
3597 | +" Create a new array from unused devices.\n" |
3598 | +" mdadm --assemble device options...\n" |
3599 | +" Assemble a previously created array.\n" |
3600 | +" mdadm --build device options...\n" |
3601 | +" Create or assemble an array without metadata.\n" |
3602 | +" mdadm --manage device options...\n" |
3603 | +" make changes to an existing array.\n" |
3604 | +" mdadm --misc options... devices\n" |
3605 | +" report on or modify various md related devices.\n" |
3606 | +" mdadm --grow options device\n" |
3607 | +" resize/reshape an active array\n" |
3608 | +" mdadm --incremental device\n" |
3609 | +" add/remove a device to/from an array as appropriate\n" |
3610 | +" mdadm --monitor options...\n" |
3611 | +" Monitor one or more array for significant changes.\n" |
3612 | +" mdadm device options...\n" |
3613 | +" Shorthand for --manage.\n" |
3614 | +"Any parameter that does not start with '-' is treated as a device name\n" |
3615 | +"or, for --examine-bitmap, a file name.\n" |
3616 | +"The first such name is often the name of an md device. Subsequent\n" |
3617 | +"names are often names of component devices.\n" |
3618 | +"\n" |
3619 | +" For detailed help on the above major modes use --help after the mode\n" |
3620 | +" e.g.\n" |
3621 | +" mdadm --assemble --help\n" |
3622 | +" For general help on options use\n" |
3623 | +" mdadm --help-options\n" |
3624 | +; |
3625 | + |
3626 | +char OptionHelp[] = |
3627 | +"Any parameter that does not start with '-' is treated as a device name\n" |
3628 | +"or, for --examine-bitmap, a file name.\n" |
3629 | +"The first such name is often the name of an md device. Subsequent\n" |
3630 | +"names are often names of component devices.\n" |
3631 | +"\n" |
3632 | +"Some common options are:\n" |
3633 | +" --help -h : General help message or, after above option,\n" |
3634 | +" mode specific help message\n" |
3635 | +" --help-options : This help message\n" |
3636 | +" --version -V : Print version information for mdadm\n" |
3637 | +" --verbose -v : Be more verbose about what is happening\n" |
3638 | +" --quiet -q : Don't print un-necessary messages\n" |
3639 | +" --brief -b : Be less verbose, more brief\n" |
3640 | +" --export -Y : With --detail, use key=value format for easy\n" |
3641 | +" import into environment\n" |
3642 | +" --force -f : Override normal checks and be more forceful\n" |
3643 | +"\n" |
3644 | +" --assemble -A : Assemble an array\n" |
3645 | +" --build -B : Build an array without metadata\n" |
3646 | +" --create -C : Create a new array\n" |
3647 | +" --detail -D : Display details of an array\n" |
3648 | +" --examine -E : Examine superblock on an array component\n" |
3649 | +" --examine-bitmap -X: Display the detail of a bitmap file\n" |
3650 | +" --monitor -F : monitor (follow) some arrays\n" |
3651 | +" --grow -G : resize/ reshape and array\n" |
3652 | +" --incremental -I : add/remove a single device to/from an array as appropriate\n" |
3653 | +" --query -Q : Display general information about how a\n" |
3654 | +" device relates to the md driver\n" |
3655 | +" --auto-detect : Start arrays auto-detected by the kernel\n" |
3656 | +" --offroot : Set first character of argv[0] to @ to indicate the\n" |
3657 | +" application was launched from initrd/initramfs and\n" |
3658 | +" should not be shutdown by systemd as part of the\n" |
3659 | +" regular shutdown process.\n" |
3660 | +; |
3661 | +/* |
3662 | +"\n" |
3663 | +" For create or build:\n" |
3664 | +" --bitmap= -b : File to store bitmap in - may pre-exist for --build\n" |
3665 | +" --chunk= -c : chunk size of kibibytes\n" |
3666 | +" --rounding= : rounding factor for linear array (==chunk size)\n" |
3667 | +" --level= -l : raid level: 0,1,4,5,6,linear,mp. 0 or linear for build\n" |
3668 | +" --parity= -p : raid5/6 parity algorithm: {left,right}-{,a}symmetric\n" |
3669 | +" --layout= : same as --parity\n" |
3670 | +" --raid-devices= -n : number of active devices in array\n" |
3671 | +" --spare-devices= -x: number of spares (eXtras) devices in initial array\n" |
3672 | +" --size= -z : Size (in K) of each drive in RAID1/4/5/6/10 - optional\n" |
3673 | +" --force -f : Honour devices as listed on command line. Don't\n" |
3674 | +" : insert a missing drive for RAID5.\n" |
3675 | +" --assume-clean : Assume the array is already in-sync. This is dangerous.\n" |
3676 | +" --bitmap-chunk= : chunksize of bitmap in bitmap file (Kilobytes)\n" |
3677 | +" --delay= -d : seconds between bitmap updates\n" |
3678 | +" --write-behind= : number of simultaneous write-behind requests to allow (requires bitmap)\n" |
3679 | +" --name= -N : Textual name for array - max 32 characters\n" |
3680 | +"\n" |
3681 | +" For assemble:\n" |
3682 | +" --bitmap= -b : File to find bitmap information in\n" |
3683 | +" --uuid= -u : uuid of array to assemble. Devices which don't\n" |
3684 | +" have this uuid are excluded\n" |
3685 | +" --super-minor= -m : minor number to look for in super-block when\n" |
3686 | +" choosing devices to use.\n" |
3687 | +" --name= -N : Array name to look for in super-block.\n" |
3688 | +" --config= -c : config file\n" |
3689 | +" --scan -s : scan config file for missing information\n" |
3690 | +" --force -f : Assemble the array even if some superblocks appear out-of-date\n" |
3691 | +" --update= -U : Update superblock: try '-A --update=?' for list of options.\n" |
3692 | +" --no-degraded : Do not start any degraded arrays - default unless --scan.\n" |
3693 | +"\n" |
3694 | +" For detail or examine:\n" |
3695 | +" --brief -b : Just print device name and UUID\n" |
3696 | +"\n" |
3697 | +" For follow/monitor:\n" |
3698 | +" --mail= -m : Address to mail alerts of failure to\n" |
3699 | +" --program= -p : Program to run when an event is detected\n" |
3700 | +" --alert= : same as --program\n" |
3701 | +" --delay= -d : seconds of delay between polling state. default=60\n" |
3702 | +"\n" |
3703 | +" General management:\n" |
3704 | +" --add -a : add, or hotadd subsequent devices\n" |
3705 | +" --remove -r : remove subsequent devices\n" |
3706 | +" --fail -f : mark subsequent devices a faulty\n" |
3707 | +" --set-faulty : same as --fail\n" |
3708 | +" --run -R : start a partially built array\n" |
3709 | +" --stop -S : deactivate array, releasing all resources\n" |
3710 | +" --readonly -o : mark array as readonly\n" |
3711 | +" --readwrite -w : mark array as readwrite\n" |
3712 | +" --zero-superblock : erase the MD superblock from a device.\n" |
3713 | +" --wait -W : wait for recovery/resync/reshape to finish.\n" |
3714 | +; |
3715 | +*/ |
3716 | + |
3717 | +char Help_create[] = |
3718 | +"Usage: mdadm --create device -chunk=X --level=Y --raid-devices=Z devices\n" |
3719 | +"\n" |
3720 | +" This usage will initialise a new md array, associate some\n" |
3721 | +" devices with it, and activate the array. In order to create an\n" |
3722 | +" array with some devices missing, use the special word 'missing' in\n" |
3723 | +" place of the relevant device name.\n" |
3724 | +"\n" |
3725 | +" Before devices are added, they are checked to see if they already contain\n" |
3726 | +" raid superblocks or filesystems. They are also checked to see if\n" |
3727 | +" the variance in device size exceeds 1%.\n" |
3728 | +" If any discrepancy is found, the user will be prompted for confirmation\n" |
3729 | +" before the array is created. The presence of a '--run' can override this\n" |
3730 | +" caution.\n" |
3731 | +"\n" |
3732 | +" If the --size option is given then only that many kilobytes of each\n" |
3733 | +" device is used, no matter how big each device is.\n" |
3734 | +" If no --size is given, the apparent size of the smallest drive given\n" |
3735 | +" is used for raid level 1 and greater, and the full device is used for\n" |
3736 | +" other levels.\n" |
3737 | +"\n" |
3738 | +" Options that are valid with --create (-C) are:\n" |
3739 | +" --bitmap= : Create a bitmap for the array with the given filename\n" |
3740 | +" --chunk= -c : chunk size of kibibytes\n" |
3741 | +" --rounding= : rounding factor for linear array (==chunk size)\n" |
3742 | +" --level= -l : raid level: 0,1,4,5,6,linear,multipath and synonyms\n" |
3743 | +" --parity= -p : raid5/6 parity algorithm: {left,right}-{,a}symmetric\n" |
3744 | +" --layout= : same as --parity\n" |
3745 | +" --raid-devices= -n : number of active devices in array\n" |
3746 | +" --spare-devices= -x: number of spares (eXtras) devices in initial array\n" |
3747 | +" --size= -z : Size (in K) of each drive in RAID1/4/5/6/10 - optional\n" |
3748 | +" --force -f : Honour devices as listed on command line. Don't\n" |
3749 | +" : insert a missing drive for RAID5.\n" |
3750 | +" --run -R : insist of running the array even if not all\n" |
3751 | +" : devices are present or some look odd.\n" |
3752 | +" --readonly -o : start the array readonly - not supported yet.\n" |
3753 | +" --name= -N : Textual name for array - max 32 characters\n" |
3754 | +" --bitmap-chunk= : bitmap chunksize in Kilobytes.\n" |
3755 | +" --delay= -d : bitmap update delay in seconds.\n" |
3756 | +"\n" |
3757 | +; |
3758 | + |
3759 | +char Help_build[] = |
3760 | +"Usage: mdadm --build device -chunk=X --level=Y --raid-devices=Z devices\n" |
3761 | +"\n" |
3762 | +" This usage is similar to --create. The difference is that it creates\n" |
3763 | +" a legacy array without a superblock. With these arrays there is no\n" |
3764 | +" different between initially creating the array and subsequently\n" |
3765 | +" assembling the array, except that hopefully there is useful data\n" |
3766 | +" there in the second case.\n" |
3767 | +"\n" |
3768 | +" The level may only be 0, raid0, or linear.\n" |
3769 | +" All devices must be listed and the array will be started once complete.\n" |
3770 | +" Options that are valid with --build (-B) are:\n" |
3771 | +" --bitmap= : file to store/find bitmap information in.\n" |
3772 | +" --chunk= -c : chunk size of kibibytes\n" |
3773 | +" --rounding= : rounding factor for linear array (==chunk size)\n" |
3774 | +" --level= -l : 0, raid0, or linear\n" |
3775 | +" --raid-devices= -n : number of active devices in array\n" |
3776 | +" --bitmap-chunk= : bitmap chunksize in Kilobytes.\n" |
3777 | +" --delay= -d : bitmap update delay in seconds.\n" |
3778 | +; |
3779 | + |
3780 | +char Help_assemble[] = |
3781 | +"Usage: mdadm --assemble device options...\n" |
3782 | +" mdadm --assemble --scan options...\n" |
3783 | +"\n" |
3784 | +"This usage assembles one or more raid arrays from pre-existing\n" |
3785 | +"components.\n" |
3786 | +"For each array, mdadm needs to know the md device, the identity of\n" |
3787 | +"the array, and a number of sub devices. These can be found in a number\n" |
3788 | +"of ways.\n" |
3789 | +"\n" |
3790 | +"The md device is either given on the command line or is found listed\n" |
3791 | +"in the config file. The array identity is determined either from the\n" |
3792 | +"--uuid or --super-minor commandline arguments, from the config file,\n" |
3793 | +"or from the first component device on the command line.\n" |
3794 | +"\n" |
3795 | +"The different combinations of these are as follows:\n" |
3796 | +" If the --scan option is not given, then only devices and identities\n" |
3797 | +" listed on the command line are considered.\n" |
3798 | +" The first device will be the array device, and the remainder will be\n" |
3799 | +" examined when looking for components.\n" |
3800 | +" If an explicit identity is given with --uuid or --super-minor, then\n" |
3801 | +" only devices with a superblock which matches that identity is considered,\n" |
3802 | +" otherwise every device listed is considered.\n" |
3803 | +"\n" |
3804 | +" If the --scan option is given, and no devices are listed, then\n" |
3805 | +" every array listed in the config file is considered for assembly.\n" |
3806 | +" The identity of candidate devices are determined from the config file.\n" |
3807 | +"\n" |
3808 | +" If the --scan option is given as well as one or more devices, then\n" |
3809 | +" Those devices are md devices that are to be assembled. Their identity\n" |
3810 | +" and components are determined from the config file.\n" |
3811 | +"\n" |
3812 | +" If mdadm can not find all of the components for an array, it will assemble\n" |
3813 | +" it but not activate it unless --run or --scan is given. To preserve this\n" |
3814 | +" behaviour even with --scan, add --no-degraded. Note that \"all of the\n" |
3815 | +" components\" means as many as were present the last time the array was running\n" |
3816 | +" as recorded in the superblock. If the array was already degraded, and\n" |
3817 | +" the missing device is not a new problem, it will still be assembled. It\n" |
3818 | +" is only newly missing devices that cause the array not to be started.\n" |
3819 | +"\n" |
3820 | +"Options that are valid with --assemble (-A) are:\n" |
3821 | +" --bitmap= : bitmap file to use wit the array\n" |
3822 | +" --uuid= -u : uuid of array to assemble. Devices which don't\n" |
3823 | +" have this uuid are excluded\n" |
3824 | +" --super-minor= -m : minor number to look for in super-block when\n" |
3825 | +" choosing devices to use.\n" |
3826 | +" --name= -N : Array name to look for in super-block.\n" |
3827 | +" --config= -c : config file\n" |
3828 | +" --scan -s : scan config file for missing information\n" |
3829 | +" --run -R : Try to start the array even if not enough devices\n" |
3830 | +" for a full array are present\n" |
3831 | +" --force -f : Assemble the array even if some superblocks appear\n" |
3832 | +" : out-of-date. This involves modifying the superblocks.\n" |
3833 | +" --update= -U : Update superblock: try '-A --update=?' for option list.\n" |
3834 | +" --no-degraded : Assemble but do not start degraded arrays.\n" |
3835 | +; |
3836 | + |
3837 | +char Help_manage[] = |
3838 | +"Usage: mdadm arraydevice options component devices...\n" |
3839 | +"\n" |
3840 | +"This usage is for managing the component devices within an array.\n" |
3841 | +"The --manage option is not needed and is assumed if the first argument\n" |
3842 | +"is a device name or a management option.\n" |
3843 | +"The first device listed will be taken to be an md array device, and\n" |
3844 | +"subsequent devices are (potential) components of that array.\n" |
3845 | +"\n" |
3846 | +"Options that are valid with management mode are:\n" |
3847 | +" --add -a : hotadd subsequent devices to the array\n" |
3848 | +" --remove -r : remove subsequent devices, which must not be active\n" |
3849 | +" --fail -f : mark subsequent devices a faulty\n" |
3850 | +" --set-faulty : same as --fail\n" |
3851 | +" --run -R : start a partially built array\n" |
3852 | +" --stop -S : deactivate array, releasing all resources\n" |
3853 | +" --readonly -o : mark array as readonly\n" |
3854 | +" --readwrite -w : mark array as readwrite\n" |
3855 | +; |
3856 | + |
3857 | +char Help_misc[] = |
3858 | +"Usage: mdadm misc_option devices...\n" |
3859 | +"\n" |
3860 | +"This usage is for performing some task on one or more devices, which\n" |
3861 | +"may be arrays or components, depending on the task.\n" |
3862 | +"The --misc option is not needed (though it is allowed) and is assumed\n" |
3863 | +"if the first argument in a misc option.\n" |
3864 | +"\n" |
3865 | +"Options that are valid with the miscellaneous mode are:\n" |
3866 | +" --query -Q : Display general information about how a\n" |
3867 | +" device relates to the md driver\n" |
3868 | +" --detail -D : Display details of an array\n" |
3869 | +" --detail-platform : Display hardware/firmware details\n" |
3870 | +" --examine -E : Examine superblock on an array component\n" |
3871 | +" --examine-bitmap -X: Display contents of a bitmap file\n" |
3872 | +" --zero-superblock : erase the MD superblock from a device.\n" |
3873 | +" --run -R : start a partially built array\n" |
3874 | +" --stop -S : deactivate array, releasing all resources\n" |
3875 | +" --readonly -o : mark array as readonly\n" |
3876 | +" --readwrite -w : mark array as readwrite\n" |
3877 | +" --test -t : exit status 0 if ok, 1 if degrade, 2 if dead, 4 if missing\n" |
3878 | +" --wait -W : wait for resync/rebuild/recovery to finish\n" |
3879 | +; |
3880 | + |
3881 | +char Help_monitor[] = |
3882 | +"Usage: mdadm --monitor options devices\n" |
3883 | +"\n" |
3884 | +"This usage causes mdadm to monitor a number of md arrays by periodically\n" |
3885 | +"polling their status and acting on any changes.\n" |
3886 | +"If any devices are listed then those devices are monitored, otherwise\n" |
3887 | +"all devices listed in the config file are monitored.\n" |
3888 | +"The address for mailing advisories to, and the program to handle\n" |
3889 | +"each change can be specified in the config file or on the command line.\n" |
3890 | +"If no mail address or program are specified, then mdadm reports all\n" |
3891 | +"state changes to stdout.\n" |
3892 | +"\n" |
3893 | +"Options that are valid with the monitor (-F --follow) mode are:\n" |
3894 | +" --mail= -m : Address to mail alerts of failure to\n" |
3895 | +" --program= -p : Program to run when an event is detected\n" |
3896 | +" --alert= : same as --program\n" |
3897 | +" --syslog -y : Report alerts via syslog\n" |
3898 | +" --increment= -r : Report RebuildNN events in the given increment. default=20\n" |
3899 | +" --delay= -d : seconds of delay between polling state. default=60\n" |
3900 | +" --config= -c : specify a different config file\n" |
3901 | +" --scan -s : find mail-address/program in config file\n" |
3902 | +" --daemonise -f : Fork and continue in child, parent exits\n" |
3903 | +" --pid-file= -i : In daemon mode write pid to specified file instead of stdout\n" |
3904 | +" --oneshot -1 : Check for degraded arrays, then exit\n" |
3905 | +" --test -t : Generate a TestMessage event against each array at startup\n" |
3906 | +; |
3907 | + |
3908 | +char Help_grow[] = |
3909 | +"Usage: mdadm --grow device options\n" |
3910 | +"\n" |
3911 | +"This usage causes mdadm to attempt to reconfigure a running array.\n" |
3912 | +"This is only possibly if the kernel being used supports a particular\n" |
3913 | +"reconfiguration. This version supports changing the number of\n" |
3914 | +"devices in a RAID1/5/6, changing the active size of all devices in\n" |
3915 | +"a RAID1/4/5/6, adding or removing a write-intent bitmap, and changing\n" |
3916 | +"the error mode for a 'FAULTY' array.\n" |
3917 | +"\n" |
3918 | +"Options that are valid with the grow (-G --grow) mode are:\n" |
3919 | +" --level= -l : Tell mdadm what level the array is so that it can\n" |
3920 | +" : interpret '--layout' properly.\n" |
3921 | +" --layout= -p : For a FAULTY array, set/change the error mode.\n" |
3922 | +" --size= -z : Change the active size of devices in an array.\n" |
3923 | +" : This is useful if all devices have been replaced\n" |
3924 | +" : with larger devices. Value is in Kilobytes, or\n" |
3925 | +" : the special word 'max' meaning 'as large as possible'.\n" |
3926 | +" --raid-devices= -n : Change the number of active devices in an array.\n" |
3927 | +" --bitmap= -b : Add or remove a write-intent bitmap.\n" |
3928 | +" --backup-file= file : A file on a differt device to store data for a\n" |
3929 | +" : short time while increasing raid-devices on a\n" |
3930 | +" : RAID4/5/6 array. Not needed when a spare is present.\n" |
3931 | +" --array-size= -Z : Change visible size of array. This does not change\n" |
3932 | +" : any data on the device, and is not stable across restarts.\n" |
3933 | +; |
3934 | + |
3935 | +char Help_incr[] = |
3936 | +"Usage: mdadm --incremental [-Rqrsf] device\n" |
3937 | +"\n" |
3938 | +"This usage allows for incremental assembly of md arrays. Devices can be\n" |
3939 | +"added one at a time as they are discovered. Once an array has all expected\n" |
3940 | +"devices, it will be started.\n" |
3941 | +"\n" |
3942 | +"Optionally, the process can be reversed by using the fail option.\n" |
3943 | +"When fail mode is invoked, mdadm will see if the device belongs to an array\n" |
3944 | +"and then both fail (if needed) and remove the device from that array.\n" |
3945 | +"\n" |
3946 | +"Options that are valid with incremental assembly (-I --incremental) are:\n" |
3947 | +" --run -R : Run arrays as soon as a minimal number of devices are\n" |
3948 | +" : present rather than waiting for all expected.\n" |
3949 | +" --quiet -q : Don't print any information messages, just errors.\n" |
3950 | +" --rebuild-map -r : Rebuild the 'map' file that mdadm uses for tracking\n" |
3951 | +" : partial arrays.\n" |
3952 | +" --scan -s : Use with -R to start any arrays that have the minimal\n" |
3953 | +" : required number of devices, but are not yet started.\n" |
3954 | +" --fail -f : First fail (if needed) and then remove device from\n" |
3955 | +" : any array that it is a member of.\n" |
3956 | +; |
3957 | + |
3958 | +char Help_config[] = |
3959 | +"The /etc/mdadm/mdadm.conf config file:\n\n" |
3960 | +" The config file contains, apart from blank lines and comment lines that\n" |
3961 | +" start with a hash(#), four sorts of configuration lines: array lines, \n" |
3962 | +" device lines, mailaddr lines and program lines.\n" |
3963 | +" Each configuration line is constructed of a number of space separated\n" |
3964 | +" words, and can be continued on subsequent physical lines by indenting\n" |
3965 | +" those lines.\n" |
3966 | +"\n" |
3967 | +" A device line starts with the word 'device' and then has a number of words\n" |
3968 | +" which identify devices. These words should be names of devices in the\n" |
3969 | +" filesystem, and can contain wildcards. There can be multiple words or each\n" |
3970 | +" device line, and multiple device lines. All devices so listed are checked\n" |
3971 | +" for relevant super blocks when assembling arrays.\n" |
3972 | +"\n" |
3973 | +" An array line start with the word 'array'. This is followed by the name of\n" |
3974 | +" the array device in the filesystem, e.g. '/dev/md2'. Subsequent words\n" |
3975 | +" describe the identity of the array, used to recognise devices to include in the\n" |
3976 | +" array. The identity can be given as a UUID with a word starting 'uuid=', or\n" |
3977 | +" as a minor-number stored in the superblock using 'super-minor=', or as a list\n" |
3978 | +" of devices. This is given as a comma separated list of names, possibly\n" |
3979 | +" containing wildcards, preceded by 'devices='. If multiple critea are given,\n" |
3980 | +" than a device must match all of them to be considered.\n" |
3981 | +"\n" |
3982 | +" A mailaddr line starts with the word 'mailaddr' and should contain exactly\n" |
3983 | +" one Email address. 'mdadm --monitor --scan' will send alerts of failed drives\n" |
3984 | +" to this Email address." |
3985 | +"\n" |
3986 | +" A program line starts with the word 'program' and should contain exactly\n" |
3987 | +" one program name. 'mdadm --monitor --scan' will run this program when any\n" |
3988 | +" event is detected.\n" |
3989 | +"\n" |
3990 | +; |
3991 | + |
3992 | |
3993 | === removed file '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/ReadMe.c' |
3994 | --- .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/ReadMe.c 2012-02-09 16:53:02 +0000 |
3995 | +++ .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/ReadMe.c 1970-01-01 00:00:00 +0000 |
3996 | @@ -1,602 +0,0 @@ |
3997 | -/* |
3998 | - * mdadm - manage Linux "md" devices aka RAID arrays. |
3999 | - * |
4000 | - * Copyright (C) 2001-2010 Neil Brown <neilb@suse.de> |
4001 | - * |
4002 | - * |
4003 | - * This program is free software; you can redistribute it and/or modify |
4004 | - * it under the terms of the GNU General Public License as published by |
4005 | - * the Free Software Foundation; either version 2 of the License, or |
4006 | - * (at your option) any later version. |
4007 | - * |
4008 | - * This program is distributed in the hope that it will be useful, |
4009 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4010 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4011 | - * GNU General Public License for more details. |
4012 | - * |
4013 | - * You should have received a copy of the GNU General Public License |
4014 | - * along with this program; if not, write to the Free Software |
4015 | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
4016 | - * |
4017 | - * Author: Neil Brown |
4018 | - * Email: <neilb@suse.de> |
4019 | - */ |
4020 | - |
4021 | -#include "mdadm.h" |
4022 | - |
4023 | -char Version[] = Name " - v3.2.3 - 23rd December 2011\n"; |
4024 | - |
4025 | -/* |
4026 | - * File: ReadMe.c |
4027 | - * |
4028 | - * This file contains general comments about the implementation |
4029 | - * and the various usage messages that can be displayed by mdadm |
4030 | - * |
4031 | - * mdadm is a single program that can be used to control Linux md devices. |
4032 | - * It is intended to provide all the functionality of the mdtools and |
4033 | - * raidtools but with a very different interface. |
4034 | - * mdadm can perform all functions without a configuration file. |
4035 | - * There is the option of using a configuration file, but not in the same |
4036 | - * way that raidtools uses one |
4037 | - * raidtools uses a configuration file to describe how to create a RAID |
4038 | - * array, and also uses this file partially to start a previously |
4039 | - * created RAID array. Further, raidtools requires the configuration |
4040 | - * file for such things as stopping a raid array which needs to know |
4041 | - * nothing about the array. |
4042 | - * |
4043 | - * The configuration file that can be used by mdadm lists two |
4044 | - * different things: |
4045 | - * 1/ a mapping from uuid to md device to identify which arrays are |
4046 | - * expect and what names (numbers) they should be given |
4047 | - * 2/ a list of devices that should be scanned for md sub-devices |
4048 | - * |
4049 | - * |
4050 | - */ |
4051 | - |
4052 | -/* |
4053 | - * mdadm has 7 major modes of operation: |
4054 | - * 1/ Create |
4055 | - * This mode is used to create a new array with a superblock |
4056 | - * It can progress in several step create-add-add-run |
4057 | - * or it can all happen with one command |
4058 | - * 2/ Assemble |
4059 | - * This mode is used to assemble the parts of a previously created |
4060 | - * array into an active array. Components can be explicitly given |
4061 | - * or can be searched for. mdadm (optionally) check that the components |
4062 | - * do form a bona-fide array, and can, on request, fiddle superblock |
4063 | - * version numbers so as to assemble a faulty array. |
4064 | - * 3/ Build |
4065 | - * This is for building legacy arrays without superblocks |
4066 | - * 4/ Manage |
4067 | - * This is for doing something to one or more devices |
4068 | - * in an array, such as add,remove,fail. |
4069 | - * run/stop/readonly/readwrite are also available |
4070 | - * 5/ Misc |
4071 | - * This is for doing things to individual devices. |
4072 | - * They might be parts of an array so |
4073 | - * zero-superblock, examine might be appropriate |
4074 | - * They might be md arrays so |
4075 | - * run,stop,rw,ro,detail might be appropriate |
4076 | - * Also query will treat it as either |
4077 | - * 6/ Monitor |
4078 | - * This mode never exits but just monitors arrays and reports changes. |
4079 | - * 7/ Grow |
4080 | - * This mode allows for changing of key attributes of a raid array, such |
4081 | - * as size, number of devices, and possibly even layout. |
4082 | - * At the time if writing, there is only minimal support. |
4083 | - */ |
4084 | - |
4085 | -char short_options[]="-ABCDEFGIQhVXYWZ:vqbc:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:"; |
4086 | -char short_bitmap_options[]= |
4087 | - "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:"; |
4088 | -char short_bitmap_auto_options[]= |
4089 | - "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sa:rfRSow1tye:"; |
4090 | - |
4091 | -struct option long_options[] = { |
4092 | - {"manage", 0, 0, ManageOpt}, |
4093 | - {"misc", 0, 0, MiscOpt}, |
4094 | - {"assemble", 0, 0, 'A'}, |
4095 | - {"build", 0, 0, 'B'}, |
4096 | - {"create", 0, 0, 'C'}, |
4097 | - {"detail", 0, 0, 'D'}, |
4098 | - {"examine", 0, 0, 'E'}, |
4099 | - {"follow", 0, 0, 'F'}, |
4100 | - {"grow", 0, 0, 'G'}, |
4101 | - {"incremental",0,0, 'I'}, |
4102 | - {"zero-superblock", 0, 0, 'K'}, /* deliberately no a short_option */ |
4103 | - {"query", 0, 0, 'Q'}, |
4104 | - {"examine-bitmap", 0, 0, 'X'}, |
4105 | - {"auto-detect", 0, 0, AutoDetect}, |
4106 | - {"detail-platform", 0, 0, DetailPlatform}, |
4107 | - {"kill-subarray", 1, 0, KillSubarray}, |
4108 | - {"update-subarray", 1, 0, UpdateSubarray}, |
4109 | - {"udev-rules", 2, 0, UdevRules}, |
4110 | - |
4111 | - /* synonyms */ |
4112 | - {"monitor", 0, 0, 'F'}, |
4113 | - |
4114 | - /* after those will normally come the name of the md device */ |
4115 | - {"help", 0, 0, 'h'}, |
4116 | - {"help-options",0,0, HelpOptions}, |
4117 | - {"version", 0, 0, 'V'}, |
4118 | - {"verbose", 0, 0, 'v'}, |
4119 | - {"quiet", 0, 0, 'q'}, |
4120 | - |
4121 | - /* For create or build: */ |
4122 | - {"chunk", 1, 0, ChunkSize}, |
4123 | - {"rounding", 1, 0, ChunkSize}, /* for linear, chunk is really a |
4124 | - * rounding number */ |
4125 | - {"level", 1, 0, 'l'}, /* 0,1,4,5,6,linear */ |
4126 | - {"parity", 1, 0, Layout}, /* {left,right}-{a,}symmetric */ |
4127 | - {"layout", 1, 0, Layout}, |
4128 | - {"raid-disks",1, 0, 'n'}, |
4129 | - {"raid-devices",1, 0, 'n'}, |
4130 | - {"spare-disks",1,0, 'x'}, |
4131 | - {"spare-devices",1,0, 'x'}, |
4132 | - {"size", 1, 0, 'z'}, |
4133 | - {"auto", 1, 0, Auto}, /* also for --assemble */ |
4134 | - {"assume-clean",0,0, AssumeClean }, |
4135 | - {"metadata", 1, 0, 'e'}, /* superblock format */ |
4136 | - {"bitmap", 1, 0, Bitmap}, |
4137 | - {"bitmap-chunk", 1, 0, BitmapChunk}, |
4138 | - {"write-behind", 2, 0, WriteBehind}, |
4139 | - {"write-mostly",0, 0, WriteMostly}, |
4140 | - {"re-add", 0, 0, ReAdd}, |
4141 | - {"homehost", 1, 0, HomeHost}, |
4142 | - {"symlinks", 1, 0, Symlinks}, |
4143 | - |
4144 | - /* For assemble */ |
4145 | - {"uuid", 1, 0, 'u'}, |
4146 | - {"super-minor",1,0, SuperMinor}, |
4147 | - {"name", 1, 0, 'N'}, |
4148 | - {"config", 1, 0, ConfigFile}, |
4149 | - {"scan", 0, 0, 's'}, |
4150 | - {"force", 0, 0, Force}, |
4151 | - {"update", 1, 0, 'U'}, |
4152 | - {"freeze-reshape", 0, 0, FreezeReshape}, |
4153 | - |
4154 | - /* Management */ |
4155 | - {"add", 0, 0, Add}, |
4156 | - {"remove", 0, 0, Remove}, |
4157 | - {"fail", 0, 0, Fail}, |
4158 | - {"set-faulty",0, 0, Fail}, |
4159 | - {"run", 0, 0, 'R'}, |
4160 | - {"stop", 0, 0, 'S'}, |
4161 | - {"readonly", 0, 0, 'o'}, |
4162 | - {"readwrite", 0, 0, 'w'}, |
4163 | - {"no-degraded",0,0, NoDegraded }, |
4164 | - {"wait", 0, 0, WaitOpt}, |
4165 | - {"wait-clean", 0, 0, Waitclean }, |
4166 | - |
4167 | - /* For Detail/Examine */ |
4168 | - {"brief", 0, 0, Brief}, |
4169 | - {"export", 0, 0, 'Y'}, |
4170 | - {"sparc2.2", 0, 0, Sparc22}, |
4171 | - {"test", 0, 0, 't'}, |
4172 | - |
4173 | - /* For Follow/monitor */ |
4174 | - {"mail", 1, 0, EMail}, |
4175 | - {"program", 1, 0, ProgramOpt}, |
4176 | - {"alert", 1, 0, ProgramOpt}, |
4177 | - {"increment", 1, 0, Increment}, |
4178 | - {"delay", 1, 0, 'd'}, |
4179 | - {"daemonise", 0, 0, Fork}, |
4180 | - {"daemonize", 0, 0, Fork}, |
4181 | - {"oneshot", 0, 0, '1'}, |
4182 | - {"pid-file", 1, 0, 'i'}, |
4183 | - {"syslog", 0, 0, 'y'}, |
4184 | - {"no-sharing", 0, 0, NoSharing}, |
4185 | - |
4186 | - /* For Grow */ |
4187 | - {"backup-file", 1,0, BackupFile}, |
4188 | - {"invalid-backup",0,0,InvalidBackup}, |
4189 | - {"array-size", 1, 0, 'Z'}, |
4190 | - {"continue", 0, 0, Continue}, |
4191 | - |
4192 | - /* For Incremental */ |
4193 | - {"rebuild-map", 0, 0, RebuildMapOpt}, |
4194 | - {"path", 1, 0, IncrementalPath}, |
4195 | - |
4196 | - {0, 0, 0, 0} |
4197 | -}; |
4198 | - |
4199 | -char Usage[] = |
4200 | -"Usage: mdadm --help\n" |
4201 | -" for help\n" |
4202 | -; |
4203 | - |
4204 | -char Help[] = |
4205 | -"mdadm is used for building, managing, and monitoring\n" |
4206 | -"Linux md devices (aka RAID arrays)\n" |
4207 | -"Usage: mdadm --create device options...\n" |
4208 | -" Create a new array from unused devices.\n" |
4209 | -" mdadm --assemble device options...\n" |
4210 | -" Assemble a previously created array.\n" |
4211 | -" mdadm --build device options...\n" |
4212 | -" Create or assemble an array without metadata.\n" |
4213 | -" mdadm --manage device options...\n" |
4214 | -" make changes to an existing array.\n" |
4215 | -" mdadm --misc options... devices\n" |
4216 | -" report on or modify various md related devices.\n" |
4217 | -" mdadm --grow options device\n" |
4218 | -" resize/reshape an active array\n" |
4219 | -" mdadm --incremental device\n" |
4220 | -" add/remove a device to/from an array as appropriate\n" |
4221 | -" mdadm --monitor options...\n" |
4222 | -" Monitor one or more array for significant changes.\n" |
4223 | -" mdadm device options...\n" |
4224 | -" Shorthand for --manage.\n" |
4225 | -"Any parameter that does not start with '-' is treated as a device name\n" |
4226 | -"or, for --examine-bitmap, a file name.\n" |
4227 | -"The first such name is often the name of an md device. Subsequent\n" |
4228 | -"names are often names of component devices.\n" |
4229 | -"\n" |
4230 | -" For detailed help on the above major modes use --help after the mode\n" |
4231 | -" e.g.\n" |
4232 | -" mdadm --assemble --help\n" |
4233 | -" For general help on options use\n" |
4234 | -" mdadm --help-options\n" |
4235 | -; |
4236 | - |
4237 | -char OptionHelp[] = |
4238 | -"Any parameter that does not start with '-' is treated as a device name\n" |
4239 | -"or, for --examine-bitmap, a file name.\n" |
4240 | -"The first such name is often the name of an md device. Subsequent\n" |
4241 | -"names are often names of component devices.\n" |
4242 | -"\n" |
4243 | -"Some common options are:\n" |
4244 | -" --help -h : General help message or, after above option,\n" |
4245 | -" mode specific help message\n" |
4246 | -" --help-options : This help message\n" |
4247 | -" --version -V : Print version information for mdadm\n" |
4248 | -" --verbose -v : Be more verbose about what is happening\n" |
4249 | -" --quiet -q : Don't print un-necessary messages\n" |
4250 | -" --brief -b : Be less verbose, more brief\n" |
4251 | -" --export -Y : With --detail, use key=value format for easy\n" |
4252 | -" import into environment\n" |
4253 | -" --force -f : Override normal checks and be more forceful\n" |
4254 | -"\n" |
4255 | -" --assemble -A : Assemble an array\n" |
4256 | -" --build -B : Build an array without metadata\n" |
4257 | -" --create -C : Create a new array\n" |
4258 | -" --detail -D : Display details of an array\n" |
4259 | -" --examine -E : Examine superblock on an array component\n" |
4260 | -" --examine-bitmap -X: Display the detail of a bitmap file\n" |
4261 | -" --monitor -F : monitor (follow) some arrays\n" |
4262 | -" --grow -G : resize/ reshape and array\n" |
4263 | -" --incremental -I : add/remove a single device to/from an array as appropriate\n" |
4264 | -" --query -Q : Display general information about how a\n" |
4265 | -" device relates to the md driver\n" |
4266 | -" --auto-detect : Start arrays auto-detected by the kernel\n" |
4267 | -; |
4268 | -/* |
4269 | -"\n" |
4270 | -" For create or build:\n" |
4271 | -" --bitmap= -b : File to store bitmap in - may pre-exist for --build\n" |
4272 | -" --chunk= -c : chunk size of kibibytes\n" |
4273 | -" --rounding= : rounding factor for linear array (==chunk size)\n" |
4274 | -" --level= -l : raid level: 0,1,4,5,6,linear,mp. 0 or linear for build\n" |
4275 | -" --parity= -p : raid5/6 parity algorithm: {left,right}-{,a}symmetric\n" |
4276 | -" --layout= : same as --parity\n" |
4277 | -" --raid-devices= -n : number of active devices in array\n" |
4278 | -" --spare-devices= -x: number of spares (eXtras) devices in initial array\n" |
4279 | -" --size= -z : Size (in K) of each drive in RAID1/4/5/6/10 - optional\n" |
4280 | -" --force -f : Honour devices as listed on command line. Don't\n" |
4281 | -" : insert a missing drive for RAID5.\n" |
4282 | -" --assume-clean : Assume the array is already in-sync. This is dangerous.\n" |
4283 | -" --bitmap-chunk= : chunksize of bitmap in bitmap file (Kilobytes)\n" |
4284 | -" --delay= -d : seconds between bitmap updates\n" |
4285 | -" --write-behind= : number of simultaneous write-behind requests to allow (requires bitmap)\n" |
4286 | -" --name= -N : Textual name for array - max 32 characters\n" |
4287 | -"\n" |
4288 | -" For assemble:\n" |
4289 | -" --bitmap= -b : File to find bitmap information in\n" |
4290 | -" --uuid= -u : uuid of array to assemble. Devices which don't\n" |
4291 | -" have this uuid are excluded\n" |
4292 | -" --super-minor= -m : minor number to look for in super-block when\n" |
4293 | -" choosing devices to use.\n" |
4294 | -" --name= -N : Array name to look for in super-block.\n" |
4295 | -" --config= -c : config file\n" |
4296 | -" --scan -s : scan config file for missing information\n" |
4297 | -" --force -f : Assemble the array even if some superblocks appear out-of-date\n" |
4298 | -" --update= -U : Update superblock: try '-A --update=?' for list of options.\n" |
4299 | -" --no-degraded : Do not start any degraded arrays - default unless --scan.\n" |
4300 | -"\n" |
4301 | -" For detail or examine:\n" |
4302 | -" --brief -b : Just print device name and UUID\n" |
4303 | -"\n" |
4304 | -" For follow/monitor:\n" |
4305 | -" --mail= -m : Address to mail alerts of failure to\n" |
4306 | -" --program= -p : Program to run when an event is detected\n" |
4307 | -" --alert= : same as --program\n" |
4308 | -" --delay= -d : seconds of delay between polling state. default=60\n" |
4309 | -"\n" |
4310 | -" General management:\n" |
4311 | -" --add -a : add, or hotadd subsequent devices\n" |
4312 | -" --remove -r : remove subsequent devices\n" |
4313 | -" --fail -f : mark subsequent devices a faulty\n" |
4314 | -" --set-faulty : same as --fail\n" |
4315 | -" --run -R : start a partially built array\n" |
4316 | -" --stop -S : deactivate array, releasing all resources\n" |
4317 | -" --readonly -o : mark array as readonly\n" |
4318 | -" --readwrite -w : mark array as readwrite\n" |
4319 | -" --zero-superblock : erase the MD superblock from a device.\n" |
4320 | -" --wait -W : wait for recovery/resync/reshape to finish.\n" |
4321 | -; |
4322 | -*/ |
4323 | - |
4324 | -char Help_create[] = |
4325 | -"Usage: mdadm --create device -chunk=X --level=Y --raid-devices=Z devices\n" |
4326 | -"\n" |
4327 | -" This usage will initialise a new md array, associate some\n" |
4328 | -" devices with it, and activate the array. In order to create an\n" |
4329 | -" array with some devices missing, use the special word 'missing' in\n" |
4330 | -" place of the relevant device name.\n" |
4331 | -"\n" |
4332 | -" Before devices are added, they are checked to see if they already contain\n" |
4333 | -" raid superblocks or filesystems. They are also checked to see if\n" |
4334 | -" the variance in device size exceeds 1%.\n" |
4335 | -" If any discrepancy is found, the user will be prompted for confirmation\n" |
4336 | -" before the array is created. The presence of a '--run' can override this\n" |
4337 | -" caution.\n" |
4338 | -"\n" |
4339 | -" If the --size option is given then only that many kilobytes of each\n" |
4340 | -" device is used, no matter how big each device is.\n" |
4341 | -" If no --size is given, the apparent size of the smallest drive given\n" |
4342 | -" is used for raid level 1 and greater, and the full device is used for\n" |
4343 | -" other levels.\n" |
4344 | -"\n" |
4345 | -" Options that are valid with --create (-C) are:\n" |
4346 | -" --bitmap= : Create a bitmap for the array with the given filename\n" |
4347 | -" --chunk= -c : chunk size of kibibytes\n" |
4348 | -" --rounding= : rounding factor for linear array (==chunk size)\n" |
4349 | -" --level= -l : raid level: 0,1,4,5,6,linear,multipath and synonyms\n" |
4350 | -" --parity= -p : raid5/6 parity algorithm: {left,right}-{,a}symmetric\n" |
4351 | -" --layout= : same as --parity\n" |
4352 | -" --raid-devices= -n : number of active devices in array\n" |
4353 | -" --spare-devices= -x: number of spares (eXtras) devices in initial array\n" |
4354 | -" --size= -z : Size (in K) of each drive in RAID1/4/5/6/10 - optional\n" |
4355 | -" --force -f : Honour devices as listed on command line. Don't\n" |
4356 | -" : insert a missing drive for RAID5.\n" |
4357 | -" --run -R : insist of running the array even if not all\n" |
4358 | -" : devices are present or some look odd.\n" |
4359 | -" --readonly -o : start the array readonly - not supported yet.\n" |
4360 | -" --name= -N : Textual name for array - max 32 characters\n" |
4361 | -" --bitmap-chunk= : bitmap chunksize in Kilobytes.\n" |
4362 | -" --delay= -d : bitmap update delay in seconds.\n" |
4363 | -"\n" |
4364 | -; |
4365 | - |
4366 | -char Help_build[] = |
4367 | -"Usage: mdadm --build device -chunk=X --level=Y --raid-devices=Z devices\n" |
4368 | -"\n" |
4369 | -" This usage is similar to --create. The difference is that it creates\n" |
4370 | -" a legacy array without a superblock. With these arrays there is no\n" |
4371 | -" different between initially creating the array and subsequently\n" |
4372 | -" assembling the array, except that hopefully there is useful data\n" |
4373 | -" there in the second case.\n" |
4374 | -"\n" |
4375 | -" The level may only be 0, raid0, or linear.\n" |
4376 | -" All devices must be listed and the array will be started once complete.\n" |
4377 | -" Options that are valid with --build (-B) are:\n" |
4378 | -" --bitmap= : file to store/find bitmap information in.\n" |
4379 | -" --chunk= -c : chunk size of kibibytes\n" |
4380 | -" --rounding= : rounding factor for linear array (==chunk size)\n" |
4381 | -" --level= -l : 0, raid0, or linear\n" |
4382 | -" --raid-devices= -n : number of active devices in array\n" |
4383 | -" --bitmap-chunk= : bitmap chunksize in Kilobytes.\n" |
4384 | -" --delay= -d : bitmap update delay in seconds.\n" |
4385 | -; |
4386 | - |
4387 | -char Help_assemble[] = |
4388 | -"Usage: mdadm --assemble device options...\n" |
4389 | -" mdadm --assemble --scan options...\n" |
4390 | -"\n" |
4391 | -"This usage assembles one or more raid arrays from pre-existing\n" |
4392 | -"components.\n" |
4393 | -"For each array, mdadm needs to know the md device, the identity of\n" |
4394 | -"the array, and a number of sub devices. These can be found in a number\n" |
4395 | -"of ways.\n" |
4396 | -"\n" |
4397 | -"The md device is either given on the command line or is found listed\n" |
4398 | -"in the config file. The array identity is determined either from the\n" |
4399 | -"--uuid or --super-minor commandline arguments, from the config file,\n" |
4400 | -"or from the first component device on the command line.\n" |
4401 | -"\n" |
4402 | -"The different combinations of these are as follows:\n" |
4403 | -" If the --scan option is not given, then only devices and identities\n" |
4404 | -" listed on the command line are considered.\n" |
4405 | -" The first device will be the array device, and the remainder will be\n" |
4406 | -" examined when looking for components.\n" |
4407 | -" If an explicit identity is given with --uuid or --super-minor, then\n" |
4408 | -" only devices with a superblock which matches that identity is considered,\n" |
4409 | -" otherwise every device listed is considered.\n" |
4410 | -"\n" |
4411 | -" If the --scan option is given, and no devices are listed, then\n" |
4412 | -" every array listed in the config file is considered for assembly.\n" |
4413 | -" The identity of candidate devices are determined from the config file.\n" |
4414 | -"\n" |
4415 | -" If the --scan option is given as well as one or more devices, then\n" |
4416 | -" Those devices are md devices that are to be assembled. Their identity\n" |
4417 | -" and components are determined from the config file.\n" |
4418 | -"\n" |
4419 | -" If mdadm can not find all of the components for an array, it will assemble\n" |
4420 | -" it but not activate it unless --run or --scan is given. To preserve this\n" |
4421 | -" behaviour even with --scan, add --no-degraded. Note that \"all of the\n" |
4422 | -" components\" means as many as were present the last time the array was running\n" |
4423 | -" as recorded in the superblock. If the array was already degraded, and\n" |
4424 | -" the missing device is not a new problem, it will still be assembled. It\n" |
4425 | -" is only newly missing devices that cause the array not to be started.\n" |
4426 | -"\n" |
4427 | -"Options that are valid with --assemble (-A) are:\n" |
4428 | -" --bitmap= : bitmap file to use wit the array\n" |
4429 | -" --uuid= -u : uuid of array to assemble. Devices which don't\n" |
4430 | -" have this uuid are excluded\n" |
4431 | -" --super-minor= -m : minor number to look for in super-block when\n" |
4432 | -" choosing devices to use.\n" |
4433 | -" --name= -N : Array name to look for in super-block.\n" |
4434 | -" --config= -c : config file\n" |
4435 | -" --scan -s : scan config file for missing information\n" |
4436 | -" --run -R : Try to start the array even if not enough devices\n" |
4437 | -" for a full array are present\n" |
4438 | -" --force -f : Assemble the array even if some superblocks appear\n" |
4439 | -" : out-of-date. This involves modifying the superblocks.\n" |
4440 | -" --update= -U : Update superblock: try '-A --update=?' for option list.\n" |
4441 | -" --no-degraded : Assemble but do not start degraded arrays.\n" |
4442 | -; |
4443 | - |
4444 | -char Help_manage[] = |
4445 | -"Usage: mdadm arraydevice options component devices...\n" |
4446 | -"\n" |
4447 | -"This usage is for managing the component devices within an array.\n" |
4448 | -"The --manage option is not needed and is assumed if the first argument\n" |
4449 | -"is a device name or a management option.\n" |
4450 | -"The first device listed will be taken to be an md array device, and\n" |
4451 | -"subsequent devices are (potential) components of that array.\n" |
4452 | -"\n" |
4453 | -"Options that are valid with management mode are:\n" |
4454 | -" --add -a : hotadd subsequent devices to the array\n" |
4455 | -" --remove -r : remove subsequent devices, which must not be active\n" |
4456 | -" --fail -f : mark subsequent devices a faulty\n" |
4457 | -" --set-faulty : same as --fail\n" |
4458 | -" --run -R : start a partially built array\n" |
4459 | -" --stop -S : deactivate array, releasing all resources\n" |
4460 | -" --readonly -o : mark array as readonly\n" |
4461 | -" --readwrite -w : mark array as readwrite\n" |
4462 | -; |
4463 | - |
4464 | -char Help_misc[] = |
4465 | -"Usage: mdadm misc_option devices...\n" |
4466 | -"\n" |
4467 | -"This usage is for performing some task on one or more devices, which\n" |
4468 | -"may be arrays or components, depending on the task.\n" |
4469 | -"The --misc option is not needed (though it is allowed) and is assumed\n" |
4470 | -"if the first argument in a misc option.\n" |
4471 | -"\n" |
4472 | -"Options that are valid with the miscellaneous mode are:\n" |
4473 | -" --query -Q : Display general information about how a\n" |
4474 | -" device relates to the md driver\n" |
4475 | -" --detail -D : Display details of an array\n" |
4476 | -" --detail-platform : Display hardware/firmware details\n" |
4477 | -" --examine -E : Examine superblock on an array component\n" |
4478 | -" --examine-bitmap -X: Display contents of a bitmap file\n" |
4479 | -" --zero-superblock : erase the MD superblock from a device.\n" |
4480 | -" --run -R : start a partially built array\n" |
4481 | -" --stop -S : deactivate array, releasing all resources\n" |
4482 | -" --readonly -o : mark array as readonly\n" |
4483 | -" --readwrite -w : mark array as readwrite\n" |
4484 | -" --test -t : exit status 0 if ok, 1 if degrade, 2 if dead, 4 if missing\n" |
4485 | -" --wait -W : wait for resync/rebuild/recovery to finish\n" |
4486 | -; |
4487 | - |
4488 | -char Help_monitor[] = |
4489 | -"Usage: mdadm --monitor options devices\n" |
4490 | -"\n" |
4491 | -"This usage causes mdadm to monitor a number of md arrays by periodically\n" |
4492 | -"polling their status and acting on any changes.\n" |
4493 | -"If any devices are listed then those devices are monitored, otherwise\n" |
4494 | -"all devices listed in the config file are monitored.\n" |
4495 | -"The address for mailing advisories to, and the program to handle\n" |
4496 | -"each change can be specified in the config file or on the command line.\n" |
4497 | -"If no mail address or program are specified, then mdadm reports all\n" |
4498 | -"state changes to stdout.\n" |
4499 | -"\n" |
4500 | -"Options that are valid with the monitor (-F --follow) mode are:\n" |
4501 | -" --mail= -m : Address to mail alerts of failure to\n" |
4502 | -" --program= -p : Program to run when an event is detected\n" |
4503 | -" --alert= : same as --program\n" |
4504 | -" --syslog -y : Report alerts via syslog\n" |
4505 | -" --increment= -r : Report RebuildNN events in the given increment. default=20\n" |
4506 | -" --delay= -d : seconds of delay between polling state. default=60\n" |
4507 | -" --config= -c : specify a different config file\n" |
4508 | -" --scan -s : find mail-address/program in config file\n" |
4509 | -" --daemonise -f : Fork and continue in child, parent exits\n" |
4510 | -" --pid-file= -i : In daemon mode write pid to specified file instead of stdout\n" |
4511 | -" --oneshot -1 : Check for degraded arrays, then exit\n" |
4512 | -" --test -t : Generate a TestMessage event against each array at startup\n" |
4513 | -; |
4514 | - |
4515 | -char Help_grow[] = |
4516 | -"Usage: mdadm --grow device options\n" |
4517 | -"\n" |
4518 | -"This usage causes mdadm to attempt to reconfigure a running array.\n" |
4519 | -"This is only possibly if the kernel being used supports a particular\n" |
4520 | -"reconfiguration. This version supports changing the number of\n" |
4521 | -"devices in a RAID1/5/6, changing the active size of all devices in\n" |
4522 | -"a RAID1/4/5/6, adding or removing a write-intent bitmap, and changing\n" |
4523 | -"the error mode for a 'FAULTY' array.\n" |
4524 | -"\n" |
4525 | -"Options that are valid with the grow (-G --grow) mode are:\n" |
4526 | -" --level= -l : Tell mdadm what level the array is so that it can\n" |
4527 | -" : interpret '--layout' properly.\n" |
4528 | -" --layout= -p : For a FAULTY array, set/change the error mode.\n" |
4529 | -" --size= -z : Change the active size of devices in an array.\n" |
4530 | -" : This is useful if all devices have been replaced\n" |
4531 | -" : with larger devices. Value is in Kilobytes, or\n" |
4532 | -" : the special word 'max' meaning 'as large as possible'.\n" |
4533 | -" --raid-devices= -n : Change the number of active devices in an array.\n" |
4534 | -" --bitmap= -b : Add or remove a write-intent bitmap.\n" |
4535 | -" --backup-file= file : A file on a differt device to store data for a\n" |
4536 | -" : short time while increasing raid-devices on a\n" |
4537 | -" : RAID4/5/6 array. Not needed when a spare is present.\n" |
4538 | -" --array-size= -Z : Change visible size of array. This does not change\n" |
4539 | -" : any data on the device, and is not stable across restarts.\n" |
4540 | -; |
4541 | - |
4542 | -char Help_incr[] = |
4543 | -"Usage: mdadm --incremental [-Rqrsf] device\n" |
4544 | -"\n" |
4545 | -"This usage allows for incremental assembly of md arrays. Devices can be\n" |
4546 | -"added one at a time as they are discovered. Once an array has all expected\n" |
4547 | -"devices, it will be started.\n" |
4548 | -"\n" |
4549 | -"Optionally, the process can be reversed by using the fail option.\n" |
4550 | -"When fail mode is invoked, mdadm will see if the device belongs to an array\n" |
4551 | -"and then both fail (if needed) and remove the device from that array.\n" |
4552 | -"\n" |
4553 | -"Options that are valid with incremental assembly (-I --incremental) are:\n" |
4554 | -" --run -R : Run arrays as soon as a minimal number of devices are\n" |
4555 | -" : present rather than waiting for all expected.\n" |
4556 | -" --quiet -q : Don't print any information messages, just errors.\n" |
4557 | -" --rebuild-map -r : Rebuild the 'map' file that mdadm uses for tracking\n" |
4558 | -" : partial arrays.\n" |
4559 | -" --scan -s : Use with -R to start any arrays that have the minimal\n" |
4560 | -" : required number of devices, but are not yet started.\n" |
4561 | -" --fail -f : First fail (if needed) and then remove device from\n" |
4562 | -" : any array that it is a member of.\n" |
4563 | -; |
4564 | - |
4565 | -char Help_config[] = |
4566 | -"The /etc/mdadm/mdadm.conf config file:\n\n" |
4567 | -" The config file contains, apart from blank lines and comment lines that\n" |
4568 | -" start with a hash(#), four sorts of configuration lines: array lines, \n" |
4569 | -" device lines, mailaddr lines and program lines.\n" |
4570 | -" Each configuration line is constructed of a number of space separated\n" |
4571 | -" words, and can be continued on subsequent physical lines by indenting\n" |
4572 | -" those lines.\n" |
4573 | -"\n" |
4574 | -" A device line starts with the word 'device' and then has a number of words\n" |
4575 | -" which identify devices. These words should be names of devices in the\n" |
4576 | -" filesystem, and can contain wildcards. There can be multiple words or each\n" |
4577 | -" device line, and multiple device lines. All devices so listed are checked\n" |
4578 | -" for relevant super blocks when assembling arrays.\n" |
4579 | -"\n" |
4580 | -" An array line start with the word 'array'. This is followed by the name of\n" |
4581 | -" the array device in the filesystem, e.g. '/dev/md2'. Subsequent words\n" |
4582 | -" describe the identity of the array, used to recognise devices to include in the\n" |
4583 | -" array. The identity can be given as a UUID with a word starting 'uuid=', or\n" |
4584 | -" as a minor-number stored in the superblock using 'super-minor=', or as a list\n" |
4585 | -" of devices. This is given as a comma separated list of names, possibly\n" |
4586 | -" containing wildcards, preceded by 'devices='. If multiple critea are given,\n" |
4587 | -" than a device must match all of them to be considered.\n" |
4588 | -"\n" |
4589 | -" A mailaddr line starts with the word 'mailaddr' and should contain exactly\n" |
4590 | -" one Email address. 'mdadm --monitor --scan' will send alerts of failed drives\n" |
4591 | -" to this Email address." |
4592 | -"\n" |
4593 | -" A program line starts with the word 'program' and should contain exactly\n" |
4594 | -" one program name. 'mdadm --monitor --scan' will run this program when any\n" |
4595 | -" event is detected.\n" |
4596 | -"\n" |
4597 | -; |
4598 | - |
4599 | |
4600 | === added directory '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/check.d' |
4601 | === removed directory '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/check.d' |
4602 | === added file '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/check.d/_numbers' |
4603 | === removed file '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/check.d/_numbers' |
4604 | === added file '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/check.d/root_on_raid' |
4605 | === removed file '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/check.d/root_on_raid' |
4606 | === added file '.pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/config.c' |
4607 | --- .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/config.c 1970-01-01 00:00:00 +0000 |
4608 | +++ .pc/debian-changes-3.1.4-1+8efb9d1ubuntu4/config.c 2012-06-18 08:55:05 +0000 |
4609 | @@ -0,0 +1,1131 @@ |
4610 | +/* |
4611 | + * mdadm - manage Linux "md" devices aka RAID arrays. |
4612 | + * |
4613 | + * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de> |
4614 | + * |
4615 | + * |
4616 | + * This program is free software; you can redistribute it and/or modify |
4617 | + * it under the terms of the GNU General Public License as published by |
4618 | + * the Free Software Foundation; either version 2 of the License, or |
4619 | + * (at your option) any later version. |
4620 | + * |
4621 | + * This program is distributed in the hope that it will be useful, |
4622 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4623 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4624 | + * GNU General Public License for more details. |
4625 | + * |
4626 | + * You should have received a copy of the GNU General Public License |
4627 | + * along with this program; if not, write to the Free Software |
4628 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
4629 | + * |
4630 | + * Author: Neil Brown |
4631 | + * Email: <neilb@suse.de> |
4632 | + */ |
4633 | + |
4634 | +#include "mdadm.h" |
4635 | +#include "dlink.h" |
4636 | +#include <dirent.h> |
4637 | +#include <glob.h> |
4638 | +#include <fnmatch.h> |
4639 | +#include <ctype.h> |
4640 | +#include <pwd.h> |
4641 | +#include <grp.h> |
4642 | + |
4643 | +/* |
4644 | + * Read the config file |
4645 | + * |
4646 | + * conf_get_uuids gets a list of devicename+uuid pairs |
4647 | + * conf_get_devs gets device names after expanding wildcards |
4648 | + * |
4649 | + * Each keeps the returned list and frees it when asked to make |
4650 | + * a new list. |
4651 | + * |
4652 | + * The format of the config file needs to be fairly extensible. |
4653 | + * Now, arrays only have names and uuids and devices merely are. |
4654 | + * But later arrays might want names, and devices might want superblock |
4655 | + * versions, and who knows what else. |
4656 | + * I like free format, abhore backslash line continuation, adore |
4657 | + * indentation for structure and am ok about # comments. |
4658 | + * |
4659 | + * So, each line that isn't blank or a #comment must either start |
4660 | + * with a key word, and not be indented, or must start with a |
4661 | + * non-key-word and must be indented. |
4662 | + * |
4663 | + * Keywords are DEVICE and ARRAY ... and several others. |
4664 | + * DEV{ICE} introduces some devices that might contain raid components. |
4665 | + * e.g. |
4666 | + * DEV style=0 /dev/sda* /dev/hd* |
4667 | + * DEV style=1 /dev/sd[b-f]* |
4668 | + * ARR{AY} describes an array giving md device and attributes like uuid=whatever |
4669 | + * e.g. |
4670 | + * ARRAY /dev/md0 uuid=whatever name=something |
4671 | + * Spaces separate words on each line. Quoting, with "" or '' protects them, |
4672 | + * but may not wrap over lines |
4673 | + * |
4674 | + */ |
4675 | + |
4676 | +#ifndef CONFFILE |
4677 | +#define CONFFILE "/etc/mdadm.conf" |
4678 | +#endif |
4679 | +#ifndef CONFFILE2 |
4680 | +/* for Debian compatibility .... */ |
4681 | +#define CONFFILE2 "/etc/mdadm/mdadm.conf" |
4682 | +#endif |
4683 | +char DefaultConfFile[] = CONFFILE; |
4684 | +char DefaultAltConfFile[] = CONFFILE2; |
4685 | + |
4686 | +enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev, |
4687 | + Homehost, AutoMode, Policy, PartPolicy, LTEnd }; |
4688 | +char *keywords[] = { |
4689 | + [Devices] = "devices", |
4690 | + [Array] = "array", |
4691 | + [Mailaddr] = "mailaddr", |
4692 | + [Mailfrom] = "mailfrom", |
4693 | + [Program] = "program", |
4694 | + [CreateDev]= "create", |
4695 | + [Homehost] = "homehost", |
4696 | + [AutoMode] = "auto", |
4697 | + [Policy] = "policy", |
4698 | + [PartPolicy]="part-policy", |
4699 | + [LTEnd] = NULL |
4700 | +}; |
4701 | + |
4702 | +/* |
4703 | + * match_keyword returns an index into the keywords array, or -1 for no match |
4704 | + * case is ignored, and at least three characters must be given |
4705 | + */ |
4706 | + |
4707 | +int match_keyword(char *word) |
4708 | +{ |
4709 | + int len = strlen(word); |
4710 | + int n; |
4711 | + |
4712 | + if (len < 3) return -1; |
4713 | + for (n=0; keywords[n]; n++) { |
4714 | + if (strncasecmp(word, keywords[n], len)==0) |
4715 | + return n; |
4716 | + } |
4717 | + return -1; |
4718 | +} |
4719 | + |
4720 | +/* |
4721 | + * conf_line reads one logical line from the conffile. |
4722 | + * It skips comments and continues until it finds a line that starts |
4723 | + * with a non blank/comment. This character is pushed back for the next call |
4724 | + * A doubly linked list of words is returned. |
4725 | + * the first word will be a keyword. Other words will have had quotes removed. |
4726 | + */ |
4727 | + |
4728 | +char *conf_line(FILE *file) |
4729 | +{ |
4730 | + char *w; |
4731 | + char *list; |
4732 | + |
4733 | + w = conf_word(file, 1); |
4734 | + if (w == NULL) return NULL; |
4735 | + |
4736 | + list = dl_strdup(w); |
4737 | + free(w); |
4738 | + dl_init(list); |
4739 | + |
4740 | + while ((w = conf_word(file,0))){ |
4741 | + char *w2 = dl_strdup(w); |
4742 | + free(w); |
4743 | + dl_add(list, w2); |
4744 | + } |
4745 | +/* printf("got a line\n");*/ |
4746 | + return list; |
4747 | +} |
4748 | + |
4749 | +void free_line(char *line) |
4750 | +{ |
4751 | + char *w; |
4752 | + for (w=dl_next(line); w != line; w=dl_next(line)) { |
4753 | + dl_del(w); |
4754 | + dl_free(w); |
4755 | + } |
4756 | + dl_free(line); |
4757 | +} |
4758 | + |
4759 | + |
4760 | +struct conf_dev { |
4761 | + struct conf_dev *next; |
4762 | + char *name; |
4763 | +} *cdevlist = NULL; |
4764 | + |
4765 | +struct mddev_dev *load_partitions(void) |
4766 | +{ |
4767 | + FILE *f = fopen("/proc/partitions", "r"); |
4768 | + char buf[1024]; |
4769 | + struct mddev_dev *rv = NULL; |
4770 | + if (f == NULL) { |
4771 | + fprintf(stderr, Name ": cannot open /proc/partitions\n"); |
4772 | + return NULL; |
4773 | + } |
4774 | + while (fgets(buf, 1024, f)) { |
4775 | + int major, minor; |
4776 | + char *name, *mp; |
4777 | + struct mddev_dev *d; |
4778 | + |
4779 | + buf[1023] = '\0'; |
4780 | + if (buf[0] != ' ') |
4781 | + continue; |
4782 | + major = strtoul(buf, &mp, 10); |
4783 | + if (mp == buf || *mp != ' ') |
4784 | + continue; |
4785 | + minor = strtoul(mp, NULL, 10); |
4786 | + |
4787 | + name = map_dev(major, minor, 1); |
4788 | + if (!name) |
4789 | + continue; |
4790 | + d = malloc(sizeof(*d)); |
4791 | + d->devname = strdup(name); |
4792 | + d->next = rv; |
4793 | + d->used = 0; |
4794 | + rv = d; |
4795 | + } |
4796 | + fclose(f); |
4797 | + return rv; |
4798 | +} |
4799 | + |
4800 | +struct mddev_dev *load_containers(void) |
4801 | +{ |
4802 | + struct mdstat_ent *mdstat = mdstat_read(1, 0); |
4803 | + struct mdstat_ent *ent; |
4804 | + struct mddev_dev *d; |
4805 | + struct mddev_dev *rv = NULL; |
4806 | + |
4807 | + if (!mdstat) |
4808 | + return NULL; |
4809 | + |
4810 | + for (ent = mdstat; ent; ent = ent->next) |
4811 | + if (ent->metadata_version && |
4812 | + strncmp(ent->metadata_version, "external:", 9) == 0 && |
4813 | + !is_subarray(&ent->metadata_version[9])) { |
4814 | + d = malloc(sizeof(*d)); |
4815 | + if (!d) |
4816 | + continue; |
4817 | + if (asprintf(&d->devname, "/dev/%s", ent->dev) < 0) { |
4818 | + free(d); |
4819 | + continue; |
4820 | + } |
4821 | + d->next = rv; |
4822 | + d->used = 0; |
4823 | + rv = d; |
4824 | + } |
4825 | + free_mdstat(mdstat); |
4826 | + |
4827 | + return rv; |
4828 | +} |
4829 | + |
4830 | +struct createinfo createinfo = { |
4831 | + .autof = 2, /* by default, create devices with standard names */ |
4832 | + .symlinks = 1, |
4833 | +#ifdef DEBIAN |
4834 | + .gid = 6, /* disk */ |
4835 | + .mode = 0660, |
4836 | +#else |
4837 | + .mode = 0600, |
4838 | +#endif |
4839 | +}; |
4840 | + |
4841 | +int parse_auto(char *str, char *msg, int config) |
4842 | +{ |
4843 | + int autof; |
4844 | + if (str == NULL || *str == 0) |
4845 | + autof = 2; |
4846 | + else if (strcasecmp(str,"no")==0) |
4847 | + autof = 1; |
4848 | + else if (strcasecmp(str,"yes")==0) |
4849 | + autof = 2; |
4850 | + else if (strcasecmp(str,"md")==0) |
4851 | + autof = config?5:3; |
4852 | + else { |
4853 | + /* There might be digits, and maybe a hypen, at the end */ |
4854 | + char *e = str + strlen(str); |
4855 | + int num = 4; |
4856 | + int len; |
4857 | + while (e > str && isdigit(e[-1])) |
4858 | + e--; |
4859 | + if (*e) { |
4860 | + num = atoi(e); |
4861 | + if (num <= 0) num = 1; |
4862 | + } |
4863 | + if (e > str && e[-1] == '-') |
4864 | + e--; |
4865 | + len = e - str; |
4866 | + if ((len == 2 && strncasecmp(str,"md",2)==0)) { |
4867 | + autof = config ? 5 : 3; |
4868 | + } else if ((len == 3 && strncasecmp(str,"yes",3)==0)) { |
4869 | + autof = 2; |
4870 | + } else if ((len == 3 && strncasecmp(str,"mdp",3)==0)) { |
4871 | + autof = config ? 6 : 4; |
4872 | + } else if ((len == 1 && strncasecmp(str,"p",1)==0) || |
4873 | + (len >= 4 && strncasecmp(str,"part",4)==0)) { |
4874 | + autof = 6; |
4875 | + } else { |
4876 | + fprintf(stderr, Name ": %s arg of \"%s\" unrecognised: use no,yes,md,mdp,part\n" |
4877 | + " optionally followed by a number.\n", |
4878 | + msg, str); |
4879 | + exit(2); |
4880 | + } |
4881 | + autof |= num << 3; |
4882 | + } |
4883 | + return autof; |
4884 | +} |
4885 | + |
4886 | +static void createline(char *line) |
4887 | +{ |
4888 | + char *w; |
4889 | + char *ep; |
4890 | + |
4891 | + for (w=dl_next(line); w!=line; w=dl_next(w)) { |
4892 | + if (strncasecmp(w, "auto=", 5) == 0) |
4893 | + createinfo.autof = parse_auto(w+5, "auto=", 1); |
4894 | + else if (strncasecmp(w, "owner=", 6) == 0) { |
4895 | + if (w[6] == 0) { |
4896 | + fprintf(stderr, Name ": missing owner name\n"); |
4897 | + continue; |
4898 | + } |
4899 | + createinfo.uid = strtoul(w+6, &ep, 10); |
4900 | + if (*ep != 0) { |
4901 | + struct passwd *pw; |
4902 | + /* must be a name */ |
4903 | + pw = getpwnam(w+6); |
4904 | + if (pw) |
4905 | + createinfo.uid = pw->pw_uid; |
4906 | + else |
4907 | + fprintf(stderr, Name ": CREATE user %s not found\n", w+6); |
4908 | + } |
4909 | + } else if (strncasecmp(w, "group=", 6) == 0) { |
4910 | + if (w[6] == 0) { |
4911 | + fprintf(stderr, Name ": missing group name\n"); |
4912 | + continue; |
4913 | + } |
4914 | + createinfo.gid = strtoul(w+6, &ep, 10); |
4915 | + if (*ep != 0) { |
4916 | + struct group *gr; |
4917 | + /* must be a name */ |
4918 | + gr = getgrnam(w+6); |
4919 | + if (gr) |
4920 | + createinfo.gid = gr->gr_gid; |
4921 | + else |
4922 | + fprintf(stderr, Name ": CREATE group %s not found\n", w+6); |
4923 | + } |
4924 | + } else if (strncasecmp(w, "mode=", 5) == 0) { |
4925 | + if (w[5] == 0) { |
4926 | + fprintf(stderr, Name ": missing CREATE mode\n"); |
4927 | + continue; |
4928 | + } |
4929 | + createinfo.mode = strtoul(w+5, &ep, 8); |
4930 | + if (*ep != 0) { |
4931 | + createinfo.mode = 0600; |
4932 | + fprintf(stderr, Name ": unrecognised CREATE mode %s\n", |
4933 | + w+5); |
4934 | + } |
4935 | + } else if (strncasecmp(w, "metadata=", 9) == 0) { |
4936 | + /* style of metadata to use by default */ |
4937 | + int i; |
4938 | + for (i=0; superlist[i] && !createinfo.supertype; i++) |
4939 | + createinfo.supertype = |
4940 | + superlist[i]->match_metadata_desc(w+9); |
4941 | + if (!createinfo.supertype) |
4942 | + fprintf(stderr, Name ": metadata format %s unknown, ignoring\n", |
4943 | + w+9); |
4944 | + } else if (strncasecmp(w, "symlinks=yes", 12) == 0) |
4945 | + createinfo.symlinks = 1; |
4946 | + else if (strncasecmp(w, "symlinks=no", 11) == 0) |
4947 | + createinfo.symlinks = 0; |
4948 | + else { |
4949 | + fprintf(stderr, Name ": unrecognised word on CREATE line: %s\n", |
4950 | + w); |
4951 | + } |
4952 | + } |
4953 | +} |
4954 | + |
4955 | +void devline(char *line) |
4956 | +{ |
4957 | + char *w; |
4958 | + struct conf_dev *cd; |
4959 | + |
4960 | + for (w=dl_next(line); w != line; w=dl_next(w)) { |
4961 | + if (w[0] == '/' || strcasecmp(w, "partitions") == 0 || |
4962 | + strcasecmp(w, "containers") == 0) { |
4963 | + cd = malloc(sizeof(*cd)); |
4964 | + cd->name = strdup(w); |
4965 | + cd->next = cdevlist; |
4966 | + cdevlist = cd; |
4967 | + } else { |
4968 | + fprintf(stderr, Name ": unreconised word on DEVICE line: %s\n", |
4969 | + w); |
4970 | + } |
4971 | + } |
4972 | +} |
4973 | + |
4974 | +struct mddev_ident *mddevlist = NULL; |
4975 | +struct mddev_ident **mddevlp = &mddevlist; |
4976 | + |
4977 | +static int is_number(char *w) |
4978 | +{ |
4979 | + /* check if there are 1 or more digits and nothing else */ |
4980 | + int digits = 0; |
4981 | + while (*w && isdigit(*w)) { |
4982 | + digits++; |
4983 | + w++; |
4984 | + } |
4985 | + return (digits && ! *w); |
4986 | +} |
4987 | + |
4988 | +void arrayline(char *line) |
4989 | +{ |
4990 | + char *w; |
4991 | + |
4992 | + struct mddev_ident mis; |
4993 | + struct mddev_ident *mi; |
4994 | + |
4995 | + mis.uuid_set = 0; |
4996 | + mis.super_minor = UnSet; |
4997 | + mis.level = UnSet; |
4998 | + mis.raid_disks = UnSet; |
4999 | + mis.spare_disks = 0; |
5000 | + mis.devices = NULL; |
The diff has been truncated for viewing.