Codebase list mdadm / cd29a5c
mdctl-0.6 Neil Brown 22 years ago
19 changed file(s) with 2106 addition(s) and 613 deletion(s). Raw diff Collapse all Expand all
00 /*
11 * mdctl - manage Linux "md" devices aka RAID arrays.
22 *
3 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 *
55 *
66 * This program is free software; you can redistribute it and/or modify
3232
3333 int Assemble(char *mddev, int mdfd,
3434 mddev_ident_t ident, char *conffile,
35 int subdevs, char **subdev,
35 mddev_dev_t devlist,
3636 int readonly, int runstop,
3737 int verbose, int force)
3838 {
6666 *
6767 * If !uuidset and scan, look in conf-file for uuid
6868 * If not found, give up
69 * If !subdevs and scan and uuidset, get list of devs from conf-file
69 * If !devlist and scan and uuidset, get list of devs from conf-file
7070 *
7171 * For each device:
7272 * Check superblock - discard if bad
9393 int old_linux = 0;
9494 int vers;
9595 mdu_array_info_t array;
96 mddev_dev_t devlist = NULL;
9796 mdp_super_t first_super, super;
9897 struct {
9998 char *devname;
107106 int devcnt = 0, okcnt, sparecnt;
108107 int i;
109108 int most_recent = 0;
110 int chosen_drive = -1;
109 int chosen_drive;
111110 int change = 0;
111 int inargv = 0;
112 int start_partial_ok = force || devlist==NULL;
112113
113114 vers = md_get_version(mdfd);
114115 if (vers <= 0) {
138139 * there must be something in the identity
139140 */
140141
141 if (subdevs == 0 &&
142 if (!devlist &&
142143 ident->uuid_set == 0 &&
143144 ident->super_minor < 0 &&
144145 ident->devices == NULL) {
146147 mddev);
147148 return 1;
148149 }
149 if (subdevs==0)
150 if (devlist == NULL)
150151 devlist = conf_get_devs(conffile);
152 else inargv = 1;
151153
152154 first_super.md_magic = 0;
153155 for (i=0; i<MD_SB_DISKS; i++)
157159 fprintf(stderr, Name ": looking for devices for %s\n",
158160 mddev);
159161
160 while (subdevs || devlist) {
162 while ( devlist) {
161163 char *devname;
162164 int this_uuid[4];
163165 int dfd;
164166 struct stat stb;
165 int inargv;
166167 int havesuper=0;
167168
168 if (subdevs) {
169 devname = *subdev++;
170 subdevs--;
171 inargv=1;
172 } else {
173 devname = devlist->devname;
174 devlist = devlist->next;
175 inargv=0;
176 }
169 devname = devlist->devname;
170 devlist = devlist->next;
177171
178172 if (ident->devices &&
179173 !match_oneof(ident->devices, devname))
189183 fprintf(stderr, Name ": fstat failed for %s: %s\n",
190184 devname, strerror(errno));
191185 close(dfd);
192 } if ((stb.st_mode & S_IFMT) != S_IFBLK) {
193 fprintf(stderr, Name ": %d is not a block device.\n",
186 } else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
187 fprintf(stderr, Name ": %s is not a block device.\n",
194188 devname);
195189 close(dfd);
196 } if (load_super(dfd, &super)) {
190 } else if (load_super(dfd, &super)) {
197191 if (inargv || verbose)
198192 fprintf( stderr, Name ": no RAID superblock on %s\n",
199193 devname);
218212 devname);
219213 continue;
220214 }
215 if (ident->level != -10 &&
216 (!havesuper|| ident->level != super.level)) {
217 if (inargv || verbose)
218 fprintf(stderr, Name ": %s has wrong raid level.\n",
219 devname);
220 continue;
221 }
222 if (ident->raid_disks != -1 &&
223 (!havesuper || ident->raid_disks!= super.raid_disks)) {
224 if (inargv || verbose)
225 fprintf(stderr, Name ": %s requires wrong number of drives.\n",
226 devname);
227 continue;
228 }
221229
222230 /* If we are this far, then we are commited to this device.
223231 * If the super_block doesn't exist, or doesn't match others,
224232 * then we cannot continue
225233 */
226 if (verbose)
227 fprintf(stderr, Name ": %s is identified as a member of %s.\n",
228 devname, mddev);
229234
230235 if (!havesuper) {
231236 fprintf(stderr, Name ": %s has no superblock - assembly aborted\n",
243248 devname);
244249 continue;
245250 }
251 if (verbose)
252 fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
253 devname, mddev, super.this_disk.raid_disk);
246254 devices[devcnt].devname = devname;
247255 devices[devcnt].major = MAJOR(stb.st_rdev);
248256 devices[devcnt].minor = MINOR(stb.st_rdev);
276284 sparecnt=0;
277285 for (i=0; i< MD_SB_DISKS;i++) {
278286 int j = best[i];
287 int event_margin = !force;
279288 if (j < 0) continue;
280 if (devices[j].events+1 >=
289 if (devices[j].events+event_margin >=
281290 devices[most_recent].events) {
282291 devices[j].uptodate = 1;
283292 if (i < first_super.raid_disks)
292301 * and add it.
293302 */
294303 int fd;
304 chosen_drive = -1;
295305 for (i=0; i<first_super.raid_disks; i++) {
296306 int j = best[i];
297307 if (j>=0 &&
343353 * If there are differences and --force is given, then update this chosen
344354 * superblock.
345355 */
356 chosen_drive = -1;
346357 for (i=0; chosen_drive < 0 && i<MD_SB_DISKS; i++) {
347358 int j = best[i];
348359 int fd;
367378
368379 for (i=0; i<MD_SB_DISKS; i++) {
369380 int j = best[i];
381 int active_sync = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
370382 if (j<0)
371383 continue;
372384 if (!devices[j].uptodate)
378390 super.disks[j].minor = devices[j].minor;
379391 }
380392 if (devices[j].uptodate &&
381 (super.disks[i].state & (1 << MD_DISK_FAULTY))) {
393 (super.disks[i].state != active_sync)) {
382394 if (force) {
383395 fprintf(stderr, Name ": "
384 "clearing FAULT flag for device %d in %s for %s\n",
396 "clearing FAULTY flag for device %d in %s for %s\n",
385397 j, mddev, devices[j].devname);
386 super.disks[i].state &= ~(1<<MD_DISK_FAULTY);
398 super.disks[i].state = active_sync;
387399 change |= 2;
388400 } else {
389401 fprintf(stderr, Name ": "
459471
460472 if (runstop == 1 ||
461473 (runstop == 0 &&
462 enough(first_super.level, first_super.raid_disks, okcnt))) {
474 ( first_super.raid_disks == okcnt
475 || start_partial_ok && enough(first_super.level, first_super.raid_disks, okcnt))
476 )) {
463477 if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
464478 fprintf(stderr, Name ": %s has been started with %d drive%s",
465479 mddev, okcnt, okcnt==1?"":"s");
477491 mddev, okcnt, okcnt==1?"":"s");
478492 return 0;
479493 }
480 fprintf(stderr, Name ": %s assembled from %d drive%s - not enough to start it.\n",
494 fprintf(stderr, Name ": %s assembled from %d drive%s - not enough to start it (use --run to insist).\n",
481495 mddev, okcnt, okcnt==1?"":"s");
482496 return 1;
483497 } else {
485499 * been updated to point to the current locations of devices.
486500 * so we can just start the array
487501 */
488 int dev;
502 unsigned long dev;
489503 dev = MKDEV(devices[chosen_drive].major,
490504 devices[chosen_drive].minor);
491505 if (ioctl(mdfd, START_ARRAY, dev)) {
00 /*
11 * mdctl - manage Linux "md" devices aka RAID arrays.
22 *
3 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 *
55 *
66 * This program is free software; you can redistribute it and/or modify
3434
3535 int Build(char *mddev, int mdfd, int chunk, int level,
3636 int raiddisks,
37 int subdevs, char *subdev[])
37 mddev_dev_t devlist)
3838 {
3939 /* Build a linear or raid0 arrays without superblocks
4040 * We cannot really do any checks, we just do it.
5252 int i;
5353 int vers;
5454 struct stat stb;
55 int subdevs = 0;
56 mddev_dev_t dv;
57
58 /* scan all devices, make sure they really are block devices */
59 for (dv = devlist; dv; dv=dv->next) {
60 if (stat(dv->devname, &stb)) {
61 fprintf(stderr, Name ": Cannot find %s: %s\n",
62 dv->devname, strerror(errno));
63 return 1;
64 }
65 if ((stb.st_mode & S_IFMT) != S_IFBLK) {
66 fprintf(stderr, Name ": %s is not a block device.\n",
67 dv->devname);
68 return 1;
69 }
70 subdevs++;
71 }
72
5573 if (raiddisks != subdevs) {
5674 fprintf(stderr, Name ": requested %d devices in array but listed %d\n",
5775 raiddisks, subdevs);
5876 return 1;
5977 }
6078
61 /* scan all devices, make sure they really are block devices */
62 for (i=0; i<subdevs; i++) {
63 if (stat(subdev[i], &stb)) {
64 fprintf(stderr, Name ": Cannot find %s: %s\n",
65 subdev[i], strerror(errno));
66 return 1;
67 }
68 if ((stb.st_mode & S_IFMT) != S_IFBLK) {
69 fprintf(stderr, Name ": %s is not a block device.\n",
70 subdev[i]);
71 return 1;
72 }
73 }
74
7579 vers = md_get_version(mdfd);
7680
7781 /* looks Ok, go for it */
78 if (vers >= 90000) {
82 if (vers >= 9000) {
7983 mdu_array_info_t array;
8084 array.level = level;
8185 array.size = 0;
8488 array.md_minor = 0;
8589 if (fstat(mdfd, &stb)==0)
8690 array.md_minor = MINOR(stb.st_rdev);
87 array.not_persistent = 0;
91 array.not_persistent = 1;
8892 array.state = 0; /* not clean, but no errors */
8993 array.active_disks = raiddisks;
9094 array.working_disks = raiddisks;
9195 array.spare_disks = 0;
9296 array.failed_disks = 0;
97 if (chunk == 0)
98 chunk = 64;
9399 array.chunk_size = chunk*1024;
94100 if (ioctl(mdfd, SET_ARRAY_INFO, &array)) {
95101 fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
98104 }
99105 }
100106 /* now add the devices */
101 for (i=0; i<subdevs; i++) {
102 if (stat(subdev[i], &stb)) {
107 for ((i=0), (dv = devlist) ; dv ; i++, dv=dv->next) {
108 if (stat(dv->devname, &stb)) {
103109 fprintf(stderr, Name ": Wierd: %s has disappeared.\n",
104 subdev[i]);
110 dv->devname);
105111 goto abort;
106112 }
107 if ((stb.st_rdev & S_IFMT)!= S_IFBLK) {
113 if ((stb.st_mode & S_IFMT)!= S_IFBLK) {
108114 fprintf(stderr, Name ": Wierd: %s is no longer a block device.\n",
109 subdev[i]);
115 dv->devname);
110116 goto abort;
111117 }
112 if (vers> 90000) {
118 if (vers>= 9000) {
113119 mdu_disk_info_t disk;
114120 disk.number = i;
115121 disk.raid_disk = i;
118124 disk.minor = MINOR(stb.st_rdev);
119125 if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
120126 fprintf(stderr, Name ": ADD_NEW_DISK failed for %s: %s\n",
121 subdev[i], strerror(errno));
127 dv->devname, strerror(errno));
122128 goto abort;
123129 }
124130 } else {
125131 if (ioctl(mdfd, REGISTER_DEV, &stb.st_rdev)) {
126132 fprintf(stderr, Name ": REGISTER_DEV failed for %s.\n",
127 subdev[i], strerror(errno));
133 dv->devname, strerror(errno));
128134 goto abort;
129135 }
130136 }
131137 }
132138 /* now to start it */
133 if (vers > 90000) {
139 if (vers >= 9000) {
134140 mdu_param_t param; /* not used by syscall */
135 if (ioctl(mdfd, RUN_ARRAY, param)) {
141 if (ioctl(mdfd, RUN_ARRAY, &param)) {
136142 fprintf(stderr, Name ": RUN_ARRAY failed: %s\n",
137143 strerror(errno));
138144 goto abort;
139145 }
140146 } else {
141 int arg;
147 unsigned long arg;
142148 arg=0;
143149 while (chunk > 4096) {
144150 arg++;
158164 return 0;
159165
160166 abort:
161 if (vers > 900000)
167 if (vers >= 9000)
162168 ioctl(mdfd, STOP_ARRAY, 0);
163169 else
164170 ioctl(mdfd, STOP_MD, 0);
0 GNU GENERAL PUBLIC LICENSE
1 Version 2, June 1991
2
3 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
4 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5 Everyone is permitted to copy and distribute verbatim copies
6 of this license document, but changing it is not allowed.
7
8 Preamble
9
10 The licenses for most software are designed to take away your
11 freedom to share and change it. By contrast, the GNU General Public
12 License is intended to guarantee your freedom to share and change free
13 software--to make sure the software is free for all its users. This
14 General Public License applies to most of the Free Software
15 Foundation's software and to any other program whose authors commit to
16 using it. (Some other Free Software Foundation software is covered by
17 the GNU Library General Public License instead.) You can apply it to
18 your programs, too.
19
20 When we speak of free software, we are referring to freedom, not
21 price. Our General Public Licenses are designed to make sure that you
22 have the freedom to distribute copies of free software (and charge for
23 this service if you wish), that you receive source code or can get it
24 if you want it, that you can change the software or use pieces of it
25 in new free programs; and that you know you can do these things.
26
27 To protect your rights, we need to make restrictions that forbid
28 anyone to deny you these rights or to ask you to surrender the rights.
29 These restrictions translate to certain responsibilities for you if you
30 distribute copies of the software, or if you modify it.
31
32 For example, if you distribute copies of such a program, whether
33 gratis or for a fee, you must give the recipients all the rights that
34 you have. You must make sure that they, too, receive or can get the
35 source code. And you must show them these terms so they know their
36 rights.
37
38 We protect your rights with two steps: (1) copyright the software, and
39 (2) offer you this license which gives you legal permission to copy,
40 distribute and/or modify the software.
41
42 Also, for each author's protection and ours, we want to make certain
43 that everyone understands that there is no warranty for this free
44 software. If the software is modified by someone else and passed on, we
45 want its recipients to know that what they have is not the original, so
46 that any problems introduced by others will not reflect on the original
47 authors' reputations.
48
49 Finally, any free program is threatened constantly by software
50 patents. We wish to avoid the danger that redistributors of a free
51 program will individually obtain patent licenses, in effect making the
52 program proprietary. To prevent this, we have made it clear that any
53 patent must be licensed for everyone's free use or not licensed at all.
54
55 The precise terms and conditions for copying, distribution and
56 modification follow.
57
58 GNU GENERAL PUBLIC LICENSE
59 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
60
61 0. This License applies to any program or other work which contains
62 a notice placed by the copyright holder saying it may be distributed
63 under the terms of this General Public License. The "Program", below,
64 refers to any such program or work, and a "work based on the Program"
65 means either the Program or any derivative work under copyright law:
66 that is to say, a work containing the Program or a portion of it,
67 either verbatim or with modifications and/or translated into another
68 language. (Hereinafter, translation is included without limitation in
69 the term "modification".) Each licensee is addressed as "you".
70
71 Activities other than copying, distribution and modification are not
72 covered by this License; they are outside its scope. The act of
73 running the Program is not restricted, and the output from the Program
74 is covered only if its contents constitute a work based on the
75 Program (independent of having been made by running the Program).
76 Whether that is true depends on what the Program does.
77
78 1. You may copy and distribute verbatim copies of the Program's
79 source code as you receive it, in any medium, provided that you
80 conspicuously and appropriately publish on each copy an appropriate
81 copyright notice and disclaimer of warranty; keep intact all the
82 notices that refer to this License and to the absence of any warranty;
83 and give any other recipients of the Program a copy of this License
84 along with the Program.
85
86 You may charge a fee for the physical act of transferring a copy, and
87 you may at your option offer warranty protection in exchange for a fee.
88
89 2. You may modify your copy or copies of the Program or any portion
90 of it, thus forming a work based on the Program, and copy and
91 distribute such modifications or work under the terms of Section 1
92 above, provided that you also meet all of these conditions:
93
94 a) You must cause the modified files to carry prominent notices
95 stating that you changed the files and the date of any change.
96
97 b) You must cause any work that you distribute or publish, that in
98 whole or in part contains or is derived from the Program or any
99 part thereof, to be licensed as a whole at no charge to all third
100 parties under the terms of this License.
101
102 c) If the modified program normally reads commands interactively
103 when run, you must cause it, when started running for such
104 interactive use in the most ordinary way, to print or display an
105 announcement including an appropriate copyright notice and a
106 notice that there is no warranty (or else, saying that you provide
107 a warranty) and that users may redistribute the program under
108 these conditions, and telling the user how to view a copy of this
109 License. (Exception: if the Program itself is interactive but
110 does not normally print such an announcement, your work based on
111 the Program is not required to print an announcement.)
112
113 These requirements apply to the modified work as a whole. If
114 identifiable sections of that work are not derived from the Program,
115 and can be reasonably considered independent and separate works in
116 themselves, then this License, and its terms, do not apply to those
117 sections when you distribute them as separate works. But when you
118 distribute the same sections as part of a whole which is a work based
119 on the Program, the distribution of the whole must be on the terms of
120 this License, whose permissions for other licensees extend to the
121 entire whole, and thus to each and every part regardless of who wrote it.
122
123 Thus, it is not the intent of this section to claim rights or contest
124 your rights to work written entirely by you; rather, the intent is to
125 exercise the right to control the distribution of derivative or
126 collective works based on the Program.
127
128 In addition, mere aggregation of another work not based on the Program
129 with the Program (or with a work based on the Program) on a volume of
130 a storage or distribution medium does not bring the other work under
131 the scope of this License.
132
133 3. You may copy and distribute the Program (or a work based on it,
134 under Section 2) in object code or executable form under the terms of
135 Sections 1 and 2 above provided that you also do one of the following:
136
137 a) Accompany it with the complete corresponding machine-readable
138 source code, which must be distributed under the terms of Sections
139 1 and 2 above on a medium customarily used for software interchange; or,
140
141 b) Accompany it with a written offer, valid for at least three
142 years, to give any third party, for a charge no more than your
143 cost of physically performing source distribution, a complete
144 machine-readable copy of the corresponding source code, to be
145 distributed under the terms of Sections 1 and 2 above on a medium
146 customarily used for software interchange; or,
147
148 c) Accompany it with the information you received as to the offer
149 to distribute corresponding source code. (This alternative is
150 allowed only for noncommercial distribution and only if you
151 received the program in object code or executable form with such
152 an offer, in accord with Subsection b above.)
153
154 The source code for a work means the preferred form of the work for
155 making modifications to it. For an executable work, complete source
156 code means all the source code for all modules it contains, plus any
157 associated interface definition files, plus the scripts used to
158 control compilation and installation of the executable. However, as a
159 special exception, the source code distributed need not include
160 anything that is normally distributed (in either source or binary
161 form) with the major components (compiler, kernel, and so on) of the
162 operating system on which the executable runs, unless that component
163 itself accompanies the executable.
164
165 If distribution of executable or object code is made by offering
166 access to copy from a designated place, then offering equivalent
167 access to copy the source code from the same place counts as
168 distribution of the source code, even though third parties are not
169 compelled to copy the source along with the object code.
170
171 4. You may not copy, modify, sublicense, or distribute the Program
172 except as expressly provided under this License. Any attempt
173 otherwise to copy, modify, sublicense or distribute the Program is
174 void, and will automatically terminate your rights under this License.
175 However, parties who have received copies, or rights, from you under
176 this License will not have their licenses terminated so long as such
177 parties remain in full compliance.
178
179 5. You are not required to accept this License, since you have not
180 signed it. However, nothing else grants you permission to modify or
181 distribute the Program or its derivative works. These actions are
182 prohibited by law if you do not accept this License. Therefore, by
183 modifying or distributing the Program (or any work based on the
184 Program), you indicate your acceptance of this License to do so, and
185 all its terms and conditions for copying, distributing or modifying
186 the Program or works based on it.
187
188 6. Each time you redistribute the Program (or any work based on the
189 Program), the recipient automatically receives a license from the
190 original licensor to copy, distribute or modify the Program subject to
191 these terms and conditions. You may not impose any further
192 restrictions on the recipients' exercise of the rights granted herein.
193 You are not responsible for enforcing compliance by third parties to
194 this License.
195
196 7. If, as a consequence of a court judgment or allegation of patent
197 infringement or for any other reason (not limited to patent issues),
198 conditions are imposed on you (whether by court order, agreement or
199 otherwise) that contradict the conditions of this License, they do not
200 excuse you from the conditions of this License. If you cannot
201 distribute so as to satisfy simultaneously your obligations under this
202 License and any other pertinent obligations, then as a consequence you
203 may not distribute the Program at all. For example, if a patent
204 license would not permit royalty-free redistribution of the Program by
205 all those who receive copies directly or indirectly through you, then
206 the only way you could satisfy both it and this License would be to
207 refrain entirely from distribution of the Program.
208
209 If any portion of this section is held invalid or unenforceable under
210 any particular circumstance, the balance of the section is intended to
211 apply and the section as a whole is intended to apply in other
212 circumstances.
213
214 It is not the purpose of this section to induce you to infringe any
215 patents or other property right claims or to contest validity of any
216 such claims; this section has the sole purpose of protecting the
217 integrity of the free software distribution system, which is
218 implemented by public license practices. Many people have made
219 generous contributions to the wide range of software distributed
220 through that system in reliance on consistent application of that
221 system; it is up to the author/donor to decide if he or she is willing
222 to distribute software through any other system and a licensee cannot
223 impose that choice.
224
225 This section is intended to make thoroughly clear what is believed to
226 be a consequence of the rest of this License.
227
228 8. If the distribution and/or use of the Program is restricted in
229 certain countries either by patents or by copyrighted interfaces, the
230 original copyright holder who places the Program under this License
231 may add an explicit geographical distribution limitation excluding
232 those countries, so that distribution is permitted only in or among
233 countries not thus excluded. In such case, this License incorporates
234 the limitation as if written in the body of this License.
235
236 9. The Free Software Foundation may publish revised and/or new versions
237 of the General Public License from time to time. Such new versions will
238 be similar in spirit to the present version, but may differ in detail to
239 address new problems or concerns.
240
241 Each version is given a distinguishing version number. If the Program
242 specifies a version number of this License which applies to it and "any
243 later version", you have the option of following the terms and conditions
244 either of that version or of any later version published by the Free
245 Software Foundation. If the Program does not specify a version number of
246 this License, you may choose any version ever published by the Free Software
247 Foundation.
248
249 10. If you wish to incorporate parts of the Program into other free
250 programs whose distribution conditions are different, write to the author
251 to ask for permission. For software which is copyrighted by the Free
252 Software Foundation, write to the Free Software Foundation; we sometimes
253 make exceptions for this. Our decision will be guided by the two goals
254 of preserving the free status of all derivatives of our free software and
255 of promoting the sharing and reuse of software generally.
256
257 NO WARRANTY
258
259 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
260 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
261 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
262 PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
263 OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
264 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
265 TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
266 PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
267 REPAIR OR CORRECTION.
268
269 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
270 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
271 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
272 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
273 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
274 TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
275 YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
276 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
277 POSSIBILITY OF SUCH DAMAGES.
278
279 END OF TERMS AND CONDITIONS
280
281 How to Apply These Terms to Your New Programs
282
283 If you develop a new program, and you want it to be of the greatest
284 possible use to the public, the best way to achieve this is to make it
285 free software which everyone can redistribute and change under these terms.
286
287 To do so, attach the following notices to the program. It is safest
288 to attach them to the start of each source file to most effectively
289 convey the exclusion of warranty; and each file should have at least
290 the "copyright" line and a pointer to where the full notice is found.
291
292 <one line to give the program's name and a brief idea of what it does.>
293 Copyright (C) 19yy <name of author>
294
295 This program is free software; you can redistribute it and/or modify
296 it under the terms of the GNU General Public License as published by
297 the Free Software Foundation; either version 2 of the License, or
298 (at your option) any later version.
299
300 This program is distributed in the hope that it will be useful,
301 but WITHOUT ANY WARRANTY; without even the implied warranty of
302 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
303 GNU General Public License for more details.
304
305 You should have received a copy of the GNU General Public License
306 along with this program; if not, write to the Free Software
307 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
308
309
310 Also add information on how to contact you by electronic and paper mail.
311
312 If the program is interactive, make it output a short notice like this
313 when it starts in an interactive mode:
314
315 Gnomovision version 69, Copyright (C) 19yy name of author
316 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 This is free software, and you are welcome to redistribute it
318 under certain conditions; type `show c' for details.
319
320 The hypothetical commands `show w' and `show c' should show the appropriate
321 parts of the General Public License. Of course, the commands you use may
322 be called something other than `show w' and `show c'; they could even be
323 mouse-clicks or menu items--whatever suits your program.
324
325 You should also get your employer (if you work as a programmer) or your
326 school, if any, to sign a "copyright disclaimer" for the program, if
327 necessary. Here is a sample; alter the names:
328
329 Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
332 <signature of Ty Coon>, 1 April 1989
333 Ty Coon, President of Vice
334
335 This General Public License does not permit incorporating your program into
336 proprietary programs. If your program is a subroutine library, you may
337 consider it more useful to permit linking proprietary applications with the
338 library. If this is what you want to do, use the GNU Library General
339 Public License instead of this License.
0
1 Changes Prior to 0.6 release
2
3 - Remove the limit on the number of device names that can be
4 given on the command line.
5 - Fix bug in --assemble --force where it would only update a
6 single superblock.
7 - Fix bogus printing of big numbers not being block devices
8 when given names of devices that don't exist.
9 - When --assemble --force, consider superblocks with an event
10 count that is 1 behind as out-of-date. Normally they are
11 considered up-to-date (as the kernel assumes this too).
12 - When marking drives as not-failed in the superblock,
13 we also mark them as ACTIVE and SYNC.
14 - Don't start arrays for which not all drives are available unless:
15 --scan which implies that all drives were found automatically
16 --run which means the user knows what they want
17 --force which means that we are fixing something broken
18 - Make sure all device numbers passed as 3rd arg of ioctl
19 are passed as unsigned lock, so that it works on SPARC
20 - If HOT_ADD_DISK failes for -a, then only try ADD_NEW_DISK
21 if we cannot read from the array, i.e. if the array is
22 not started yet.
23 - man page update
24 - Taught Examine to handle --scan. It examines all devices listed
25 on DEVICE lines in the config file.
26 - Added --brief (-b) flag for Examine and Detail to print out
27 and mdctl.conf compatible description with uuid=, level=,
28 disks= and - for Examine - devices=
29 --examine --brief collects all devices the make the one array and
30 list them as one entry.
31 - Added level= and disks= options to ARRAY lines in config files
32 so --brief output could be used as-is.
33 - Make parity style ({left,right}-{,a}symmetric) consistantly use -,
34 never _.
35 - Add "Array Size" to --detail output
36 - Change "Size" to "Device Size" and exclude from Detail of arrays
37 that do not have a consistent device size.
38 - Add Human readable MiB or GiB value on size lines of Detail and Examine
39 - --assemble --scan doesn't complain about active drives
40 - require number of spares given in -x to be listed.
41 - Made --build actually work.
42 Changes Prior to 0.5 release
43
44 --assemble:
45 spare drives are handled properly.
46
47 --force can be used to recover from 2-drive failures on RAID5
48 If you belive that /dev/hda1 /dev/hdb1 /dev/hdc1 /dev/hdd1 should
49 make a raid5 array, but it has experienced multiple failures and
50 wont start, then
51
52 mdctl --assemble --force /dev/md0 /dev/hd[abcd]1
53
54 Should update the superblock on the newest failed drive and
55 restart the array in degraded mode. You should then remove the
56 remaining failed drive and re-add it (if you are happy that it
57 might work).
58
59 Ofcourse whenever you have a 2-drive failure, you have a risk
60 of corruption in data that hasn't be changed for a long time. So
61 this doesn't give you your array back all nice and happy, but it
62 does allow you to recover data that might not be corrupt.
63
64 More flexibility in identifying a RAID array in the mdctl.conf
65 e.g.
66 array /dev/md4 super-minor=4
67
68 assembles /dev/md4 from all devices found that have a raid
69 superblock that says the minor number of the array is 4.
70 If the blocks with the right minor number do not all have the
71 same UUID, an error is flags and no assembly happens.
72
73 array /dev/md3 devices=/dev/hd[abc]2
74
75 Assembles /dev/md3 drom /dev/hda2 /dev/hdb2 and/dev/hdc2. All
76 devices must exist and have raid superblock with the same uuid.
77
78 If two identity specifiers are used, only devices that match all
79 of them are considered, so
80
81 array /dev/md2 devices=/dev/hd?2 super-minor=2
82
83 will assemble /dev/md2 using all /dev/hd?2 devices which have a
84 raid superblock with minor number 2.
85
86 --create:
87 When listing devices for --create, the word "missing" can be
88 used to indicate that the respective slot does not have a
89 working drive currently. This is similar to the "failed-disk"
90 directive in mkraid/raidtab.
91 e.g.
92 mdctl --create --level=5 -raid-disks=4 --spare-disks=2
93 /dev/md0 /dev/sda /dev/sdb missing /dev/sdc /dev/sdd /dev/sde
94
95 will create a raid5 array with the third slot empty, and two
96 spares.
97
98 By default, raid5 arrays are created with the last slot empty
99 and drive listed for the last slot added as a spare. If a
100 "missing" slot is given, or if --force is given, then --create
101 does exactly what you ask and doesn't try to be clever.
102
103
104 --follow / --monitor:
105
106 This is a new mode. I couldn't stop my self from picking a name
107 starting with F (as current modes start A,B,C,D,E) but I
108 relented and provided an alternate name that is somewhat more
109 meaningful.
110
111 In this mode, mdctl does not exit, but runs continuously and
112 periodically polls all the md devices to see if they have had
113 any interested state change.
114 The changes that it currently notices are:
115 Fail - an active disc fails
116 FailSpare - a spare, that was presumably being build, fails
117 ActiveSpare - a spare becomes active, presumably after a rebuild.
118
119 Options:
120 --mail mailaddress - send Email on any Fail* event
121 --program program - run the program on any event.
122 Args are: eventname mddevice subdevice(if-known)
123 --delay seconds - change from the default 60second pause
124 between polls.
125
126 I plan to add functionality to this mode to allow sharing of
127 spare drives. If an array is marks "spare-group=fred", and it
128 has a failed drive and no spares, and if some other array is
129 also "spare-group=fred" and it has no failed drives, but does
130 have a spare drive that is big enough, the spare will be moved
131 to the first array.
132
133 I also have the idea of adding a --grow mode which will re-organise
134 the data on an N disk raid0/4/5 array to be on an N+M disk array.
135 I have no concrete plans for this though.
136
137 I got rid of the "v" in the archive file name, and include the
138 version number in the directory created by the archive.
139
140 There is now a man page and mdctl.spec (for rpm) thanks to
141 Danilo Godec <danci@agenda.si>.
142
143 Ofcourse, the man page is now out of date and despite being based on
144 the --help output, is not wholy correct. After I get --follow
145 working properly, I plan to revise the various documentation and/or
146 the code to make sure the two match.
147
00 /*
11 * mdctl - manage Linux "md" devices aka RAID arrays.
22 *
3 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 *
55 *
66 * This program is free software; you can redistribute it and/or modify
3232
3333 int Create(char *mddev, int mdfd,
3434 int chunk, int level, int layout, int size, int raiddisks, int sparedisks,
35 int subdevs, char *subdev[],
35 int subdevs, mddev_dev_t devlist,
3636 int runstop, int verbose, int force)
3737 {
3838 /*
5252 * RUN_ARRAY
5353 */
5454 int minsize, maxsize;
55 int maxdisc= -1, mindisc = -1;
55 char *mindisc = NULL;
56 char *maxdisc = NULL;
5657 int i;
58 mddev_dev_t dv;
5759 int fail=0, warn=0;
5860 struct stat stb;
5961 int first_missing = MD_SB_DISKS*2;
9294 fprintf(stderr, Name ": You have listed more disks (%d) than are in the array(%d)!\n", subdevs, raiddisks+sparedisks);
9395 return 1;
9496 }
95 if (subdevs < raiddisks) {
97 if (subdevs < raiddisks+sparedisks) {
9698 fprintf(stderr, Name ": You haven't given enough devices (real or missing) to create this array\n");
9799 return 1;
98100 }
120122 /* now look at the subdevs */
121123 array.active_disks = 0;
122124 array.working_disks = 0;
123 for (i=0; i<subdevs; i++) {
124 char *dname = subdev[i];
125 for (dv=devlist; dv; dv=dv->next) {
126 char *dname = dv->devname;
125127 int dsize, freesize;
126128 int fd;
127 if (strcasecmp(subdev[i], "missing")==0) {
129 if (strcasecmp(dname, "missing")==0) {
128130 if (first_missing > i)
129131 first_missing = i;
130132 missing_disks ++;
164166 close(fd);
165167 continue;
166168 }
167 if (maxdisc< 0 || (maxdisc>=0 && freesize > maxsize)) {
168 maxdisc = i;
169 if (maxdisc == NULL || (maxdisc && freesize > maxsize)) {
170 maxdisc = dname;
169171 maxsize = freesize;
170172 }
171 if (mindisc < 0 || (mindisc >=0 && freesize < minsize)) {
172 mindisc = i;
173 if (mindisc ==NULL || (mindisc && freesize < minsize)) {
174 mindisc = dname;
173175 minsize = freesize;
174176 }
175177 warn |= check_ext2(fd, dname);
182184 return 1;
183185 }
184186 if (size == 0) {
185 if (mindisc == -1) {
187 if (mindisc == NULL) {
186188 fprintf(stderr, Name ": no size and no drives given - aborting create.\n");
187189 return 1;
188190 }
192194 }
193195 if ((maxsize-size)*100 > maxsize) {
194196 fprintf(stderr, Name ": largest drive (%s) exceed size (%dK) by more than 1%\n",
195 subdev[maxdisc], size);
197 maxdisc, size);
196198 warn = 1;
197199 }
198200
266268 return 1;
267269 }
268270
269 for (i=0; i<subdevs; i++) {
271 for (i=0, dv = devlist ; dv ; dv=dv->next, i++) {
270272 int fd;
271273 struct stat stb;
272274 mdu_disk_info_t disk;
279281 disk.state = 6; /* active and in sync */
280282 else
281283 disk.state = 0;
282 if (strcasecmp(subdev[i], "missing")==0) {
284 if (strcasecmp(dv->devname, "missing")==0) {
283285 disk.major = 0;
284286 disk.minor = 0;
285287 disk.state = 1; /* faulty */
286288 } else {
287 fd = open(subdev[i], O_RDONLY, 0);
289 fd = open(dv->devname, O_RDONLY, 0);
288290 if (fd < 0) {
289291 fprintf(stderr, Name ": failed to open %s after earlier success - aborting\n",
290 subdev[i]);
292 dv->devname);
291293 return 1;
292294 }
293295 fstat(fd, &stb);
297299 }
298300 if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
299301 fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
300 subdev[i], strerror(errno));
302 dv->devname, strerror(errno));
301303 return 1;
302304 }
303305 }
00 /*
11 * mdctl - manage Linux "md" devices aka RAID arrays.
22 *
3 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 *
55 *
66 * This program is free software; you can redistribute it and/or modify
3030 #include "md_p.h"
3131 #include "md_u.h"
3232
33 int Detail(char *dev)
33 int Detail(char *dev, int brief)
3434 {
3535 /*
3636 * Print out details for an md array by using
7676 return 1;
7777 }
7878 /* Ok, we have some info to print... */
79 printf("%s:\n", dev);
80 printf(" Version : %02d.%02d.%02d\n",
81 array.major_version, array.minor_version, array.patch_version);
82 atime = array.ctime;
83 printf(" Creation Time : %.24s\n", ctime(&atime));
8479 c = map_num(pers, array.level);
85 printf(" Raid Level : %s\n", c?c:"-unknown-");
86 printf(" Size : %d\n", array.size);
87 printf(" Raid Disks : %d\n", array.raid_disks);
88 printf(" Total Disks : %d\n", array.nr_disks);
89 printf("Preferred Minor : %d\n", array.md_minor);
90 printf(" Persistance : Superblock is %spersistant\n",
91 array.not_persistent?"not ":"");
92 printf("\n");
93 atime = array.utime;
94 printf(" Update Time : %.24s\n", ctime(&atime));
95 printf(" State : %s, %serrors\n",
96 (array.state&(1<<MD_SB_CLEAN))?"clean":"dirty",
97 (array.state&(1<<MD_SB_ERRORS))?"":"no-");
98 printf(" Active Drives : %d\n", array.active_disks);
99 printf(" Working Drives : %d\n", array.working_disks);
100 printf(" Failed Drives : %d\n", array.failed_disks);
101 printf(" Spare Drives : %d\n", array.spare_disks);
102 printf("\n");
103 if (array.level == 5) {
104 c = map_num(r5layout, array.layout);
105 printf(" Layout : %s\n", c?c:"-unknown-");
80 if (brief)
81 printf("ARRAY %s level=%s disks=%d", dev, c?c:"-unknown-",array.raid_disks );
82 else {
83 int array_size;
84 if (ioctl(fd, BLKGETSIZE, &array_size))
85 array_size = 0;
86 else array_size>>= 1;
87 printf("%s:\n", dev);
88 printf(" Version : %02d.%02d.%02d\n",
89 array.major_version, array.minor_version, array.patch_version);
90 atime = array.ctime;
91 printf(" Creation Time : %.24s\n", ctime(&atime));
92 printf(" Raid Level : %s\n", c?c:"-unknown-");
93 if (array_size)
94 printf(" Array Size : %d%s\n", array_size, human_size(array_size));
95 if (array.level >= 1)
96 printf(" Device Size : %d%s\n", array.size, human_size(array.size));
97 printf(" Raid Disks : %d\n", array.raid_disks);
98 printf(" Total Disks : %d\n", array.nr_disks);
99 printf("Preferred Minor : %d\n", array.md_minor);
100 printf(" Persistance : Superblock is %spersistant\n",
101 array.not_persistent?"not ":"");
102 printf("\n");
103 atime = array.utime;
104 printf(" Update Time : %.24s\n", ctime(&atime));
105 printf(" State : %s, %serrors\n",
106 (array.state&(1<<MD_SB_CLEAN))?"clean":"dirty",
107 (array.state&(1<<MD_SB_ERRORS))?"":"no-");
108 printf(" Active Drives : %d\n", array.active_disks);
109 printf(" Working Drives : %d\n", array.working_disks);
110 printf(" Failed Drives : %d\n", array.failed_disks);
111 printf(" Spare Drives : %d\n", array.spare_disks);
112 printf("\n");
113 if (array.level == 5) {
114 c = map_num(r5layout, array.layout);
115 printf(" Layout : %s\n", c?c:"-unknown-");
116 }
117 switch (array.level) {
118 case 0:
119 case 4:
120 case 5:
121 printf(" Chunk Size : %dK\n", array.chunk_size/1024);
122 break;
123 case -1:
124 printf(" Rounding : %dK\n", array.chunk_size/1024);
125 break;
126 default: break;
127 }
128
129 printf("\n");
130 printf(" Number Major Minor RaidDisk State\n");
106131 }
107 switch (array.level) {
108 case 0:
109 case 4:
110 case 5:
111 printf(" Chunk Size : %dK\n", array.chunk_size/1024);
112 break;
113 case -1:
114 printf(" Rounding : %dK\n", array.chunk_size/1024);
115 break;
116 default: break;
117 }
118
119 printf("\n");
120 printf(" Number Major Minor RaidDisk State\n");
121132 for (d= 0; d<array.raid_disks+array.spare_disks; d++) {
122133 mdu_disk_info_t disk;
123134 char *dv;
127138 d, strerror(errno));
128139 continue;
129140 }
130 printf(" %5d %5d %5d %5d ",
131 disk.number, disk.major, disk.minor, disk.raid_disk);
132 if (disk.state & (1<<MD_DISK_FAULTY)) printf(" faulty");
133 if (disk.state & (1<<MD_DISK_ACTIVE)) printf(" active");
134 if (disk.state & (1<<MD_DISK_SYNC)) printf(" sync");
135 if (disk.state & (1<<MD_DISK_REMOVED)) printf(" removed");
141 if (!brief) {
142 printf(" %5d %5d %5d %5d ",
143 disk.number, disk.major, disk.minor, disk.raid_disk);
144 if (disk.state & (1<<MD_DISK_FAULTY)) printf(" faulty");
145 if (disk.state & (1<<MD_DISK_ACTIVE)) printf(" active");
146 if (disk.state & (1<<MD_DISK_SYNC)) printf(" sync");
147 if (disk.state & (1<<MD_DISK_REMOVED)) printf(" removed");
148 }
136149 if ((dv=map_dev(disk.major, disk.minor))) {
137 printf(" %s", dv);
138 if (!have_super) {
139 /* try to read the superblock from this device
140 * to get more info
141 */
142 int fd = open(dv, O_RDONLY);
143 if (fd >=0 &&
144 load_super(fd, &super) ==0 &&
145 super.ctime == array.ctime &&
146 super.level == array.level)
147 have_super = 1;
148 }
150 if (!brief) printf(" %s", dv);
151 if (!have_super) {
152 /* try to read the superblock from this device
153 * to get more info
154 */
155 int fd = open(dv, O_RDONLY);
156 if (fd >=0 &&
157 load_super(fd, &super) ==0 &&
158 super.ctime == array.ctime &&
159 super.level == array.level)
160 have_super = 1;
161 }
149162 }
150 printf("\n");
163 if (!brief) printf("\n");
151164 }
152165 if (have_super) {
166 if (brief) printf(" UUID=");
167 else printf(" UUID : ");
153168 if (super.minor_version >= 90)
154 printf(" UUID : %08x:%08x:%08x:%08x\n", super.set_uuid0, super.set_uuid1,
155 super.set_uuid2, super.set_uuid3);
156 else
157 printf(" UUID : %08x\n", super.set_uuid0);
169 printf("%08x:%08x:%08x:%08x", super.set_uuid0, super.set_uuid1,
170 super.set_uuid2, super.set_uuid3);
171 else
172 printf("%08x", super.set_uuid0);
173 if (!brief) printf("\n");
158174 }
175 if (brief) printf("\n");
159176 return 0;
160177 }
00 /*
11 * mdctl - manage Linux "md" devices aka RAID arrays.
22 *
3 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 *
55 *
66 * This program is free software; you can redistribute it and/or modify
2727 */
2828
2929 #include "mdctl.h"
30 #include "dlink.h"
3031
3132 #if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
3233 #error no endian defined
3334 #endif
3435 #include "md_u.h"
3536 #include "md_p.h"
36 int Examine(char *dev)
37 int Examine(mddev_dev_t devlist, int brief, char *conffile)
3738 {
3839
3940 /* Read the raid superblock from a device and
4849 *
4950 * utime, state etc
5051 *
52 * If (brief) gather devices for same array and just print a mdctl.conf line including devices=
53 * if devlist==NULL, use conf_get_devs(
5154 */
52 int fd = open(dev, O_RDONLY);
55 int fd;
5356 time_t atime;
5457 mdp_super_t super;
5558 int d;
5659 char *c;
57 int rv;
58
59 if (fd < 0) {
60 fprintf(stderr,Name ": cannot open %s: %s\n",
61 dev, strerror(errno));
60 int rv = 0;
61 int err;
62 int scan= 0;
63
64 struct array {
65 mdp_super_t super;
66 void *devs;
67 struct array *next;
68 } *arrays = NULL;
69
70 if (devlist == NULL) {
71 devlist = conf_get_devs(conffile);
72 scan=1;
73 }
74 if (devlist == NULL) {
75 fprintf(stderr, Name ": No devices listed in %s\n", conffile);
6276 return 1;
6377 }
6478
65 rv = load_super(fd, &super);
66 close(fd);
67 switch(rv) {
68 case 1:
69 fprintf(stderr, Name ": cannot find device size for %s: %s\n",
70 dev, strerror(errno));
71 return 1;
72 case 2:
79 for (; devlist ; devlist=devlist->next) {
80 fd = open(devlist->devname, O_RDONLY);
81 if (fd < 0) {
82 if (!scan)
83 fprintf(stderr,Name ": cannot open %s: %s\n",
84 devlist->devname, strerror(errno));
85 err = 1;
86 }
87 else {
88 err = load_super(fd, &super);
89 close(fd);
90 }
91 if (err && (brief||scan))
92 continue;
93 if (err) rv =1;
94 switch(err) {
95 case 1:
96 fprintf(stderr, Name ": cannot find device size for %s: %s\n",
97 devlist->devname, strerror(errno));
98 continue;
99 case 2:
73100 /* fprintf(stderr, Name ": %s is too small for md: size is %ld sectors\n",
74 dev, size);
101 devlist->devname, size);
75102 */
76 fprintf(stderr, Name ": %s is too small for md\n",
77 dev);
78 return 1;
79 case 3:
80 fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
81 dev, strerror(errno));
82 return 1;
83 case 4:
84 fprintf(stderr, Name ": Cannot read superblock on %s\n",
85 dev);
86 return 1;
87 case 5:
88 fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
89 dev, MD_SB_MAGIC, super.md_magic);
90 return 1;
91 case 6:
92 fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
93 dev, super.major_version);
94 return 1;
95 }
103 fprintf(stderr, Name ": %s is too small for md\n",
104 devlist->devname);
105 continue;
106 case 3:
107 fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
108 devlist->devname, strerror(errno));
109 continue;
110 case 4:
111 fprintf(stderr, Name ": Cannot read superblock on %s\n",
112 devlist->devname);
113 continue;
114 case 5:
115 fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
116 devlist->devname, MD_SB_MAGIC, super.md_magic);
117 continue;
118 case 6:
119 fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
120 devlist->devname, super.major_version);
121 continue;
122 }
96123
97 /* Ok, its good enough to try, though the checksum could be wrong */
98 printf("%s:\n",dev);
99 printf(" Magic : %08x\n", super.md_magic);
100 printf(" Version : %02d.%02d.%02d\n", super.major_version, super.minor_version,
101 super.patch_version);
102 if (super.minor_version >= 90)
103 printf(" UUID : %08x:%08x:%08x:%08x\n", super.set_uuid0, super.set_uuid1,
104 super.set_uuid2, super.set_uuid3);
105 else
106 printf(" UUID : %08x\n", super.set_uuid0);
107
108 atime = super.ctime;
109 printf(" Creation Time : %.24s\n", ctime(&atime));
110 c=map_num(pers, super.level);
111 printf(" Raid Level : %s\n", c?c:"-unknown-");
112 printf(" Size : %d\n", super.size);
113 printf(" Raid Disks : %d\n", super.raid_disks);
114 printf(" Total Disks : %d\n", super.nr_disks);
115 printf("Preferred Minor : %d\n", super.md_minor);
116 printf("\n");
117 atime = super.utime;
118 printf(" Update Time : %.24s\n", ctime(&atime));
119 printf(" State : %s, %serrors\n",
120 (super.state&(1<<MD_SB_CLEAN))?"clean":"dirty",
121 (super.state&(1<<MD_SB_ERRORS))?"":"no-");
122 printf(" Active Drives : %d\n", super.active_disks);
123 printf(" Working Drives : %d\n", super.working_disks);
124 printf(" Failed Drives : %d\n", super.failed_disks);
125 printf(" Spare Drives : %d\n", super.spare_disks);
126 if (calc_sb_csum(&super) == super.sb_csum)
127 printf(" Checksum : %x - correct\n", super.sb_csum);
128 else
129 printf(" Checksum : %x - expected %x\n", super.sb_csum, calc_sb_csum(&super));
130 printf(" Events : %d.%d\n", super.events_hi, super.events_lo);
131 printf("\n");
132 if (super.level == 5) {
133 c = map_num(r5layout, super.layout);
134 printf(" Layout : %s\n", c?c:"-unknown-");
135 }
136 switch(super.level) {
137 case 0:
138 case 4:
139 case 5:
140 printf(" Chunk Size : %dK\n", super.chunk_size/1024);
141 break;
142 case -1:
143 printf(" Rounding : %dK\n", super.chunk_size/1024);
144 break;
145 default: break;
146 }
147 printf("\n");
148 printf(" Number Major Minor RaidDisk State\n");
149 for (d= -1; d<(signed int)(super.raid_disks+super.spare_disks); d++) {
150 mdp_disk_t *dp;
151 char *dv;
152 char nb[5];
153 if (d>=0) dp = &super.disks[d];
154 else dp = &super.this_disk;
155 sprintf(nb, "%4d", d);
156 printf("%4s %5d %5d %5d %5d ", d < 0 ? "this" : nb,
157 dp->number, dp->major, dp->minor, dp->raid_disk);
158 if (dp->state & (1<<MD_DISK_FAULTY)) printf(" faulty");
159 if (dp->state & (1<<MD_DISK_ACTIVE)) printf(" active");
160 if (dp->state & (1<<MD_DISK_SYNC)) printf(" sync");
161 if (dp->state & (1<<MD_DISK_REMOVED)) printf(" removed");
162 if ((dv=map_dev(dp->major, dp->minor)))
163 printf(" %s", dv);
164 printf("\n");
165 }
166 return 0;
124 /* Ok, its good enough to try, though the checksum could be wrong */
125 if (brief) {
126 struct array *ap;
127 char *d;
128 for (ap=arrays; ap; ap=ap->next) {
129 if (compare_super(&ap->super, &super)==0)
130 break;
131 }
132 if (!ap) {
133 ap = malloc(sizeof(*ap));
134 ap->super = super;
135 ap->devs = dl_head();
136 ap->next = arrays;
137 arrays = ap;
138 }
139 d = dl_strdup(devlist->devname);
140 dl_add(ap->devs, d);
141 } else {
142 printf("%s:\n",devlist->devname);
143 printf(" Magic : %08x\n", super.md_magic);
144 printf(" Version : %02d.%02d.%02d\n", super.major_version, super.minor_version,
145 super.patch_version);
146 if (super.minor_version >= 90)
147 printf(" UUID : %08x:%08x:%08x:%08x\n", super.set_uuid0, super.set_uuid1,
148 super.set_uuid2, super.set_uuid3);
149 else
150 printf(" UUID : %08x\n", super.set_uuid0);
151
152 atime = super.ctime;
153 printf(" Creation Time : %.24s\n", ctime(&atime));
154 c=map_num(pers, super.level);
155 printf(" Raid Level : %s\n", c?c:"-unknown-");
156 printf(" Device Size : %d%s\n", super.size, human_size(super.size));
157 printf(" Raid Disks : %d\n", super.raid_disks);
158 printf(" Total Disks : %d\n", super.nr_disks);
159 printf("Preferred Minor : %d\n", super.md_minor);
160 printf("\n");
161 atime = super.utime;
162 printf(" Update Time : %.24s\n", ctime(&atime));
163 printf(" State : %s, %serrors\n",
164 (super.state&(1<<MD_SB_CLEAN))?"clean":"dirty",
165 (super.state&(1<<MD_SB_ERRORS))?"":"no-");
166 printf(" Active Drives : %d\n", super.active_disks);
167 printf(" Working Drives : %d\n", super.working_disks);
168 printf(" Failed Drives : %d\n", super.failed_disks);
169 printf(" Spare Drives : %d\n", super.spare_disks);
170 if (calc_sb_csum(&super) == super.sb_csum)
171 printf(" Checksum : %x - correct\n", super.sb_csum);
172 else
173 printf(" Checksum : %x - expected %x\n", super.sb_csum, calc_sb_csum(&super));
174 printf(" Events : %d.%d\n", super.events_hi, super.events_lo);
175 printf("\n");
176 if (super.level == 5) {
177 c = map_num(r5layout, super.layout);
178 printf(" Layout : %s\n", c?c:"-unknown-");
179 }
180 switch(super.level) {
181 case 0:
182 case 4:
183 case 5:
184 printf(" Chunk Size : %dK\n", super.chunk_size/1024);
185 break;
186 case -1:
187 printf(" Rounding : %dK\n", super.chunk_size/1024);
188 break;
189 default: break;
190 }
191 printf("\n");
192 printf(" Number Major Minor RaidDisk State\n");
193 for (d= -1; d<(signed int)(super.raid_disks+super.spare_disks); d++) {
194 mdp_disk_t *dp;
195 char *dv;
196 char nb[5];
197 if (d>=0) dp = &super.disks[d];
198 else dp = &super.this_disk;
199 sprintf(nb, "%4d", d);
200 printf("%4s %5d %5d %5d %5d ", d < 0 ? "this" : nb,
201 dp->number, dp->major, dp->minor, dp->raid_disk);
202 if (dp->state & (1<<MD_DISK_FAULTY)) printf(" faulty");
203 if (dp->state & (1<<MD_DISK_ACTIVE)) printf(" active");
204 if (dp->state & (1<<MD_DISK_SYNC)) printf(" sync");
205 if (dp->state & (1<<MD_DISK_REMOVED)) printf(" removed");
206 if ((dv=map_dev(dp->major, dp->minor)))
207 printf(" %s", dv);
208 printf("\n");
209 }
210 }
211 }
212 if (brief) {
213 struct array *ap;
214 for (ap=arrays; ap; ap=ap->next) {
215 char sep='=';
216 char *c=map_num(pers, ap->super.level);
217 char *d;
218 printf("ARRAY /dev/md%d level=%s disks=%d UUID=",
219 ap->super.md_minor, c?c:"-unknown-", ap->super.raid_disks);
220 if (ap->super.minor_version >= 90)
221 printf("%08x:%08x:%08x:%08x", ap->super.set_uuid0, ap->super.set_uuid1,
222 ap->super.set_uuid2, ap->super.set_uuid3);
223 else
224 printf("%08x", ap->super.set_uuid0);
225 printf("\n devices");
226 for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) {
227 printf("%c%s", sep, d);
228 sep=',';
229 }
230 printf("\n");
231 }
232 }
233 return rv;
167234 }
00 #
11 # mdctl - manage Linux "md" devices aka RAID arrays.
22 #
3 # Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 # Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 #
55 #
66 # This program is free software; you can redistribute it and/or modify
2626 # Australia
2727 #
2828
29 CC = gcc
2930 CFLAGS = -Wall,error,strict-prototypes -ggdb
3031
32 INSTALL = /usr/bin/install
33 DESTDIR = /sbin
34
3135 OBJS = mdctl.o config.o ReadMe.o util.o Manage.o Assemble.o Build.o Create.o Detail.o Examine.o Monitor.o dlink.o
32 all : mdctl
36
37 all : mdctl mdctl.man
3338
3439 mdctl : $(OBJS)
3540 $(CC) -o mdctl $^
3641
42 mdctl.man : mdctl.8
43 nroff -man mdctl.8 > mdctl.man
44
3745 $(OBJS) : mdctl.h
3846
47 install : mdctl
48 $(INSTALL) -m 755 mdctl $(DESTDIR)/sbin
49
3950 clean :
40 rm -f mdctl $(OBJS) core
51 rm -f mdctl $(OBJS) core mdctl.man
4152
4253 dist : clean
4354 ./makedist
00 /*
11 * mdctl - manage Linux "md" devices aka RAID arrays.
22 *
3 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 *
55 *
66 * This program is free software; you can redistribute it and/or modify
115115 }
116116
117117 int Manage_subdevs(char *devname, int fd,
118 int devcnt, char *devnames[], int devmodes[])
119 {
118 mddev_dev_t devlist)
119 {
120120 /* do something to each dev.
121121 * devmode can be
122122 * 'a' - add the device
127127 */
128128 mdu_array_info_t array;
129129 mdu_disk_info_t disc;
130 mddev_dev_t dv;
130131 struct stat stb;
131132 int i,j;
133 int save_errno;
134 static buf[4096];
132135
133136 if (ioctl(fd, GET_ARRAY_INFO, &array)) {
134137 fprintf(stderr, Name ": cannot get array info for %s\n",
135138 devname);
136139 return 1;
137140 }
138 for (i=0 ; i<devcnt; i++) {
139 if (stat(devnames[i], &stb)) {
141 for (dv = devlist ; dv; dv=dv->next) {
142 if (stat(dv->devname, &stb)) {
140143 fprintf(stderr, Name ": cannot find %s: %s\n",
141 devnames[i], strerror(errno));
144 dv->devname, strerror(errno));
142145 return 1;
143146 }
144147 if ((stb.st_mode & S_IFMT) != S_IFBLK) {
145148 fprintf(stderr, Name ": %s is not a block device.\n",
146 devnames[i]);
147 return 1;
148 }
149 switch(devmodes[i]){
149 dv->devname);
150 return 1;
151 }
152 switch(dv->disposition){
150153 default:
151154 fprintf(stderr, Name ": internal error - devmode[%d]=%d\n",
152 i, devmodes[i]);
155 i, dv->disposition);
153156 return 1;
154157 case 'a':
155158 /* add the device - hot or cold */
156 if (ioctl(fd, HOT_ADD_DISK, stb.st_rdev)==0) {
159 if (ioctl(fd, HOT_ADD_DISK, (unsigned long)stb.st_rdev)==0) {
157160 fprintf(stderr, Name ": hot added %s\n",
158 devnames[i]);
161 dv->devname);
159162 continue;
163 }
164 save_errno = errno;
165 if (read(fd, buf, sizeof(buf)) > 0) {
166 /* array is active, so don't try to add.
167 * i.e. something is wrong
168 */
169 fprintf(stderr, Name ": hot add failed for %s: %s\n",
170 dv->devname, strerror(save_errno));
171 return 1;
160172 }
161173 /* try ADD_NEW_DISK.
162174 * we might be creating, we might be assembling,
179191 disc.minor = MINOR(stb.st_rdev);
180192 if (ioctl(fd,ADD_NEW_DISK, &disc)) {
181193 fprintf(stderr, Name ": add new disk failed for %s: %s\n",
182 devnames[i], strerror(errno));
183 return 1;
184 }
185 fprintf(stderr, Name ": added %s\n", devnames[i]);
194 dv->devname, strerror(errno));
195 return 1;
196 }
197 fprintf(stderr, Name ": added %s\n", dv->devname);
186198 break;
187199
188200 case 'r':
189201 /* hot remove */
190202 /* FIXME check that it is a current member */
191 if (ioctl(fd, HOT_REMOVE_DISK, stb.st_rdev)) {
203 if (ioctl(fd, HOT_REMOVE_DISK, (unsigned long)stb.st_rdev)) {
192204 fprintf(stderr, Name ": hot remove failed for %s: %s\n",
193 devnames[i], strerror(errno));
194 return 1;
195 }
196 fprintf(stderr, Name ": hot removed %s\n", devnames[i]);
205 dv->devname, strerror(errno));
206 return 1;
207 }
208 fprintf(stderr, Name ": hot removed %s\n", dv->devname);
197209 break;
198210
199211 case 'f': /* set faulty */
200212 /* FIXME check current member */
201 if (ioctl(fd, SET_DISK_FAULTY, stb.st_rdev)) {
213 if (ioctl(fd, SET_DISK_FAULTY, (unsigned long) stb.st_rdev)) {
202214 fprintf(stderr, Name ": set disk faulty failed for %s: %s\n",
203 devnames[i], strerror(errno));
215 dv->devname, strerror(errno));
204216 return 1;
205217 }
206218 fprintf(stderr, Name ": set %s faulty in %s\n",
207 devnames[i], devname);
219 dv->devname, devname);
208220 break;
209221 }
210222 }
00 /*
11 * mdctl - manage Linux "md" devices aka RAID arrays.
22 *
3 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 *
55 *
66 * This program is free software; you can redistribute it and/or modify
3333
3434 static void alert(char *event, char *dev, char *disc, char *mailaddr, char *cmd);
3535
36 int Monitor(int num_devs, char *devlist[],
36 int Monitor(mddev_dev_t devlist,
3737 char *mailaddr, char *alert_cmd,
3838 int period,
3939 char *config)
7474 int finished = 0;
7575 while (! finished) {
7676 mddev_ident_t mdlist = NULL;
77 mddev_dev_t dv;
7778 int dnum=0;
78 if (num_devs == 0)
79 if (devlist== NULL)
7980 mdlist = conf_get_ident(config, NULL);
80 while (dnum < num_devs || mdlist) {
81 dv = devlist;
82 while (dv || mdlist) {
8183 mddev_ident_t mdident;
8284 struct state *st;
8385 mdu_array_info_t array;
8688 char *event = NULL;
8789 int i;
8890 char *event_disc = NULL;
89 if (num_devs) {
90 dev = devlist[dnum++];
91 if (dv) {
92 dev = dv->devname;
9193 mdident = conf_get_ident(config, dev);
94 dv = dv->next;
9295 } else {
9396 mdident = mdlist;
9497 dev = mdident->devname;
170173
171174 static void alert(char *event, char *dev, char *disc, char *mailaddr, char *cmd)
172175 {
176 if (!cmd && !mailaddr) {
177 time_t now = time(0);
178
179 printf("%0.15s: %s on %s %s\n", ctime(&now)+4, event, dev, disc?disc:"unknown device");
180 }
173181 if (cmd) {
174182 int pid = fork();
175183 switch(pid) {
00 /*
11 * mdctl - manage Linux "md" devices aka RAID arrays.
22 *
3 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 *
55 *
66 * This program is free software; you can redistribute it and/or modify
2828
2929 #include "mdctl.h"
3030
31 char Version[] = Name " - v0.5 - 23 August 2001\n";
31 char Version[] = Name " - v0.6 - 7 March 2002\n";
3232 /*
3333 * File: ReadMe.c
3434 *
7777 * command, subsequent Manage commands can finish the job.
7878 */
7979
80 char short_options[]="-ABCDEFhVvc:l:p:m:n:x:u:c:d:z:sarfRSow";
80 char short_options[]="-ABCDEFhVvbc:l:p:m:n:x:u:c:d:z:sarfRSow";
8181 struct option long_options[] = {
8282 {"manage", 0, 0, '@'},
8383 {"assemble", 0, 0, 'A'},
121121 {"readonly", 0, 0, 'o'},
122122 {"readwrite", 0, 0, 'w'},
123123
124 /* For Detail/Examine */
125 {"brief", 0, 0, 'b'},
126
124127 /* For Follow/monitor */
125128 {"mail", 1, 0, 'm'},
126129 {"program", 1, 0, 'p'},
173176 " --paritiy= -p : raid5 parity algorith: {left,right}-{,a}symmetric\n"
174177 " --layout= : same as --parity\n"
175178 " --raid-disks= -n : number of active devices in array\n"
176 " --spare-disks= -x : number of spares (eXtras) to allow space for\n"
179 " --spare-disks= -x : number of spares (eXtras) devices in initial array\n"
177180 " --size= -z : Size (in K) of each drive in RAID1/4/5 - optional\n"
178181 " --force -f : Honour devices as listed on command line. Don't\n"
179182 " : insert a missing drive for RAID5.\n"
186189 " --config= -c : config file\n"
187190 " --scan -s : scan config file for missing information\n"
188191 " --force -f : Assemble the array even if some superblocks appear out-of-date\n"
192 "\n"
193 " For detail or examine:\n"
194 " --brief -b : Just print device name and UUID\n"
189195 "\n"
190196 " For follow/monitor:\n"
191197 " --mail= -m : Address to mail alerts of failure to\n"
305311 /* name/number mappings */
306312
307313 mapping_t r5layout[] = {
308 { "left_asymmetric", 0},
309 { "right_asymmetric", 1},
310 { "left_symmetric", 2},
311 { "right_symmetric", 3},
314 { "left-asymmetric", 0},
315 { "right-asymmetric", 1},
316 { "left-symmetric", 2},
317 { "right-symmetric", 3},
312318
313319 { "default", 2},
314320 { "la", 0},
0
1
2 ?? Allow -S /dev/md? - current complains subsequent not a/d/r
3
4 * write proc.c to parse /proc/mdstat file, and maybe /proc/partitions too.
5 Build list of arrays: name, rebuild-percent
6
7 * --detail --scan to read mdctl.conf, and then iterate over these,
8 but assume --brief. --verbose can override
9 check each subdevice to see if it is in conf_get_devs.
10 Warn if not.
11
12 * Support multipath ... maybe...
13
14 * --follow to syslog
15
16 * --follow to move spares around
17
18 * --follow to notice other events:
19 rebuild started
20 spare activated
21 spare removed
22 spare added
23
24 ------------------------------------
25 - --examine --scan scans all drives and build an mdctl.conf file DONE
026
127 - check superblock checksum in examine DONE
228 - report "chunk" or "rounding" depending on raid level DONE
329 - report "linear" instead of "-1" for raid level DONE
430 - decode ayout depending on raid level DONE
5 - --verbose and --force flags.
31 - --verbose and --force flags. DONE
632
733 - set md_minor, *_disks for Create - DONE
834 - for create raid5, how to choose between
935 all working, but not insync
10 one missing, one spare, insync
11 - and for raid1 - some failed drives...
36 one missing, one spare, insync DONE (--force)
37 - and for raid1 - some failed drives... (missing)
1238
1339 - when RUN_ARRAY, make sure *_disks counts are right
1440
1541 - get --detail to extract extra stuff from superblock,
1642 like uuid DONE
17 - --detail --brief to give a config file line
43 - --detail --brief to give a config file line DONE
1844 - parse config file. DONE
1945 - test...
2046
2248 then try to assemble that device first.
2349
2450
25 - mdctl -S /dev/md0 /dev/md1 gives internal error
51 - mdctl -S /dev/md0 /dev/md1 gives internal error FIXED
2652
2753 - mdctl --detail --scan print summary of what it can find?
2854
7399 rebuild started
74100 spare activated
75101 spare removed
76 spare added
102 spare added
00 /*
11 * mdctl - manage Linux "md" devices aka RAID arrays.
22 *
3 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 *
55 *
66 * This program is free software; you can redistribute it and/or modify
228228
229229 mis.uuid_set = 0;
230230 mis.super_minor = -1;
231 mis.level = -10;
232 mis.raid_disks = -1;
231233 mis.devices = NULL;
232234 mis.devname = NULL;
233235
272274 w);
273275 else
274276 mis.spare_group = strdup(w+12);
277 } else if (strncasecmp(w, "level=", 6) == 0 ) {
278 /* this is mainly for compatability with --brief output */
279 mis.level = map_name(pers, w+6);
280 } else if (strncasecmp(w, "disks=", 6) == 0 ) {
281 /* again, for compat */
282 mis.raid_disks = atoi(w+6);
275283 } else {
276284 fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n",
277285 w);
1515 exit 1
1616 fi
1717 trap "rm $target/$base; exit" 1 2 3
18 ( cd .. ; ln -s mdctl mdctl-$version ; tar czhvf - --exclude='*,v' --exclude='*.o' --exclude=RCS mdctl-$version ; rm mdctl-$version ) > $target/$base
18 ( cd .. ; ln -s mdctl mdctl-$version ; tar czhvf - --exclude='*,v' --exclude='*.o' --exclude mdctl --exclude=RCS mdctl-$version ; rm mdctl-$version ) > $target/$base
1919 chmod a+r $target/$base
2020 ls -l $target/$base
+553
-265
mdctl.8 less more
00 .\" -*- nroff -*-
11 .TH mdctl 8
22 .SH NAME
3 mdctl \- a single program that can be used to control Linux md devices
3 mdctl \- manage MD devices
4 .I aka
5 Linux Software Raid.
6
47 .SH SYNOPSIS
58
6 .BI mdctl
7 [mode] <raiddevice> [options]
9 .BI mdctl " [mode] <raiddevice> [options] <subdevices>"
810
911 .SH DESCRIPTION
1012 RAID devices are virtual devices created from two or more
11 real block devices. This allows multiple disks to be combined into a single
12 filesystem, possibly with integrated redundancy to survive drive failure.. Linux RAID devices
13 are implemented through the md device driver.
13 real block devices. This allows multiple devices (typically disk
14 drives or partitions there-of) to be combined into a single device to
15 hold (for example) a single filesystem.
16 Some RAID levels included redundancy and so can survive some degree of
17 device failure.
18
19 Linux Software RAID devices are implemented through the md (Multiple Devices) device driver.
20
21 Currently, Linux supports
22 .B LINEAR
23 md devices,
24 .B RAID0
25 (striping),
26 .B RAID1
27 (mirroring),
28 .B RAID4
29 and
30 .B RAID5.
31
32 Recent kernels (2002) also support a mode known as
33 .BR MULTIPATH .
34 .B mdctl
35 does not support MULTIPATH as yet.
36
37 .B mdctl
38 is a program that can be used to create and manage MD devices. As
39 such it provides a similar set of functionality to the
40 .B raidtools
41 packages.
42 The key differences between
43 .B mdctl
44 and
45 .B raidtools
46 are:
47 .IP \(bu 4
48 .B mdctl
49 is a single program and not a collection of programs.
50 .IP \(bu 4
51 .B mdctl
52 can perform (almost) all of its functions without having a
53 configuration file. Also mdctl helps with management of the configuration
54 file.
55 .IP \(bu 4
56 .B mdctl
57 can provide information about your arrays (through Detail and Examine)
58 that
59 .B raidtools
60 cannot.
61 .IP \(bu 4
62 .B raidtools
63 can manage MULTIPATH devices which
64 .B mdctl
65 cannot yet manage.
66
67 .SH MODES
68 mdctl has 7 major modes of operation:
69 .TP
70 .B Assemble
71 Assemble the parts of a previously created
72 array into an active array. Components can be explicitly given
73 or can be searched for.
74 .B mdctl
75 checks that the components
76 do form a bona fide array, and can, on request, fiddle superblock
77 information so as to assemble a faulty array.
78
79 .TP
80 .B Build
81 Build a legacy array without per-device superblocks.
82
83 .TP
84 .B Create
85 Create a new array with per-device superblocks.
86 '''It can progress
87 '''in several step create-add-add-run or it can all happen with one command.
88
89 .TP
90 .B Detail
91 Display the details of a given md device. Details include the RAID
92 level, the number of devices, which ones are faulty (if any), and the
93 array UUID.
94
95 .TP
96 .B Examine
97 Examine a device to see if it is part of an md array, and print out
98 the details of that array.
99 This mode can also be used to examine a large number of devices and to
100 print out a summary of the arrays found in a format suitable for the
101 .B mdctl.conf
102 configuration file.
103
104 .TP
105 .B "Follow or Monitor"
106 Monitor one or more md devices and act on any state changes.
107
108 .TP
109 .B Manage
110 This is for odd bits an pieces like hotadd, hotremove, setfaulty, stop,
111 readonly, readwrite.
112 '''If an array is only partially setup by the
113 '''Create or Assemble commands, subsequent Manage commands can finish the
114 '''job.
115
116 .SH OPTIONS
117
118 Available options are:
119
120 .TP
121 .BR -A ", " --assemble
122 Assemble an existing array.
123
124 .TP
125 .BR -B ", " --build
126 Build a legacy array without superblocks.
127
128 .TP
129 .BR -C ", " --create
130 Create a new array.
131
132 .TP
133 .BR -D ", " --detail
134 Print detail of one or more md devices.
135
136 .TP
137 .BR -E ", " --examine
138 Print content of md superblock on device(s).
139
140 .TP
141 .BR -F ", " --follow ", " --monitor
142 Select
143 .B Monitor
144 mode.
145
146 .TP
147 .BR -h ", " --help
148 Display help message or, after above option, mode specific help message.
149
150 .TP
151 .BR -V ", " --version
152 Print version information for mdctl.
153
154 .TP
155 .BR -v ", " --verbose
156 Be more verbose about what is happening.
157
158 .TP
159 .BR -b ", " --brief
160 Be less verbose. This is used with
161 .B --detail
162 and
163 .BR --examine .
164
165 .SH For create or build:
166
167 .TP
168 .BR -c ", " --chunk=
169 Specify chunk size of kibibytes. The default is 64.
170
171 .TP
172 .BR --rounding=
173 Specify rounding factor for linear array (==chunk size)
174
175 .TP
176 .BR -l ", " --level=
177 Set raid level. Options are: linear, raid0, 0, stripe, raid1, 1, mirror, raid5, 4,
178 raid5, 5. Obviously some of these are synonymous.
179 Only the first 4 are valid when Building.
180
181 .TP
182 .BR -p ", " --parity=
183 Set raid5 parity algorithm. Options are:
184 {left,right}-{,a}symmetric, la, ra, ls, rs. The default is left-symmetric.
185
186 .TP
187 .BR --layout=
188 same as --parity
189
190 .TP
191 .BR -n ", " --raid-disks=
192 number of active devices in array.
193
194 .TP
195 .BR -x ", " --spare-disks=
196 number of spare (eXtra) disks in initial array. Spares can be added
197 and removed later.
198
199 .TP
200 .BR -z ", " --size=
201 Amount (in Kibibytes) of space to use from each drive in RAID1/4/5.
202 This must be a multiple of the chunk size, and must leave about 128Kb
203 of space at the end of the drive for the RAID superblock.
204 If this is not specified
205 (as it normally is not) the smallest drive (or partition) sets the
206 size, though if there is a variance among the drives of greater than 1%, a warning is
207 issued.
208
209 .SH For assemble:
210
211 .TP
212 .BR -u ", " --uuid=
213 uuid of array to assemble. Devices which don't have this uuid are
214 excluded
215
216 .TP
217 .BR -m ", " --super-minor=
218 Minor number of device that array was created for. Devices which
219 don't have this minor number are excluded. If you create an array as
220 /dev/md1, then all superblock will contain the minor number 1, even if
221 the array is later assembled as /dev/md2.
222
223 .TP
224 .BR -c ", " --config=
225 config file. Default is
226 .BR /etc/mdctl.conf .
227
228 .TP
229 .BR -s ", " --scan
230 scan config file for missing information
231
232 .TP
233 .BR -f ", " --force
234 Assemble the array even if some superblocks appear out-of-date
235
236 .TP
237 .BR -R ", " --run
238 Attempt to start the array even if fewer drives were given than are
239 needed for a full array. Normally if not all drives are found and
240 .B --scan
241 is not used, then the array will be assembled but not started.
242 With
243 .B --run
244 an attempt will be made to start it anyway.
245
246 .SH General management
247
248 .TP
249 .BR -a ", " --add
250 '''add, or
251 hotadd listed devices.
252
253 .TP
254 .BR -r ", " --remove
255 remove listed devices. The must not be active. i.e. they should
256 be failed or spare devices.
257
258 .TP
259 .BR -f ", " --fail
260 mark listed devices as faulty.
261
262 .TP
263 .BR --set-faulty
264 same as --fail.
265
266 .TP
267 .BR -R ", " --run
268 start a partially built array.
269
270 .TP
271 .BR -S ", " --stop
272 deactivate array, releasing all resources.
273
274 .TP
275 .BR -o ", " --readonly
276 mark array as readonly.
277
278 .TP
279 .BR -w ", " --readwrite
280 mark array as readwrite.
281
282
283 .SH ASSEMBLY MODE
284
285 .HP 12
286 Usage:
287 .B mdctl --assemble
288 .I device options...
289 .HP 12
290 Usage:
291 .B mdctl --assemble --scan
292 .I options...
293
294 .PP
295 This usage assembles one or more raid arrays from pre-existing components.
296 For each array, mdctl needs to know the md device, the identity of the
297 array, and a number of sub devices. These can be found in a number of ways.
298
299 The md device is either given before
300 .B --scan
301 or is found from the config file. In the latter case, multiple md devices
302 can be started with a single mdctl command.
303
304 The identity can be given with the
305 .B --uuid
306 option, with the
307 .B --super-minor
308 option, can be found in in the config file, or will be taken from the
309 super block on the first subdevice listed on the command line.
310
311 Devices can be given on the
312 .B --assemble
313 command line or from the config file. Only devices which have an md
314 superblock which contains the right identity will be considered for any device.
315
316 The config file is only used if explicitly named with
317 .B --config
318 or requested with
319 .B --scan.
320 In the later case,
321 .B /etc/mdctl.conf
322 is used.
323
324 If
325 .B --scan
326 is not given, then the config file will only be used to find the
327 identity of md arrays.
328
329 Normally the array will be started after it is assembled. However is
330 .B --scan
331 is not given and insufficient drives were lists to start a complete
332 (non-degraded) array, then the array is not started (to guard against
333 usage errors). To insist that the array be started in this case (as
334 may work for RAID1 or RAID5), give the
335 .B --run
336 flag.
337
338
339 .SH BUILD MODE
340
341 .HP 12
342 Usage:
343 .B mdctl --build
344 .I device
345 .BI --chunk= X
346 .BI --level= Y
347 .BI --raid-disks= Z
348 .I devices
349
350 .PP
351 This usage is similar to
352 .BR --create .
353 The difference is that it creates a legacy array without a superblock. With
354 these arrays there is no difference between initially creating the array and
355 subsequently assembling the array, except that hopefully there is useful
356 data there in the second case.
357
358 The level may only be 0, raid0, or linear. All devices must be listed
359 and the array will be started once complete.
360
361 .SH CREATE MODE
362
363 .HP 12
364 Usage:
365 .B mdctl --create
366 .I device
367 .BI --chunk= X
368 .BI --level= Y
369 .br
370 .BI --raid-disks= Z
371 .I devices
372
373 .PP
374 This usage will initialise a new md array, associate some devices with
375 it, and activate the array.
376
377 As devices are added, they are checked to see if they contain raid
378 superblocks or filesystems. They are also check to see if the variance in
379 device size exceeds 1%.
380
381 If any discrepancy is found, the array will not automatically be run, though
382 the presence of a
383 .B --run
384 can override this caution.
385
386 '''If the
387 '''.B --size
388 '''option is given, it is not necessary to list any subdevices in this command.
389 '''They can be added later, before a
390 '''.B --run.
391 '''If no
392 '''.B --size
393 '''is given, the apparent size of the smallest drive given is used.
394
395 The General Management options that are valid with --create are:
396 .TP
397 .B --run
398 insist of running the array even if some devices look like they might
399 be in use.
400
401 .TP
402 .B --readonly
403 start the array readonly - not supported yet.
404
405 .SH DETAIL MODE
406 .HP 12
407 Usage:
408 .B mdctl --detail
409 .RB [ --brief ]
410 .I device ...
411 .PP
412
413 This usage sill print out the details of the given array including a
414 list of component devices. To determine names for the devices,
415 .B mdctl
416 searches
417 .B /dev
418 for device files with the right major and minor numbers.
419
420 With
421 .B --brief
422 .B mdctl
423 prints a single line that identifies the level, number of disks, and
424 UUID of the array. This line is suitable for inclusion in
425 .BR /etc/mdctl.conf .
426
427 .SH EXAMINE MODE
428 .HP 12
429 Usage:
430 .B mdctl --examine
431 .RB [ --scan ]
432 .RB [ --brief ]
433 .I device ...
434 .PP
435 This usage will examine some block devices to see if that have a valid
436 RAID superblock on them. The information in each valid raid
437 superblock will be printed.
438
439 If
440 .B --scan
441 is used, the no devices should be listed, and the complete set of
442 devices identified in the configuration file are checked.
443 .B --scan
444 implies
445 .B --brief
446 but this implication can be countered by specifying
447 .BR --verbose .
448
449 With
450 .B --brief
451 .B mdctl
452 will output an config file entry of each distinct array that was
453 found. This entry will list the UUID, the raid level, and a list of
454 the individual devices on which a superblock for that array was found.
455 This output will by syntactically suitable for inclusion in the
456 configuration file, but should
457 .B NOT
458 be used blindly. Often the array description that you want in the
459 configuration file is much less specific than that given by
460 .BR "mdctl -Bs" .
461 For example, you normally do not want to list the devices,
462 particularly if they are SCSI devices.
463
464 '''.SH BUGS
465 '''no known bugs.
466
467 .SH FILES
468
469 .SS /proc/mdstat
14470
15471 If you're using the
16472 .B /proc
17473 filesystem,
18474 .B /proc/mdstat
19475 gives you informations about md devices status.
20
21 Currently, Linux supports linear md devices, RAID0 (striping), RAID1
22 (mirrroring), RAID4 and RAID5. For information on the various levels of
476 This file is not currently used by
477 .BR mdctl .
478
479 .SS /etc/mdctl.conf
480
481 The config file is line oriented with, as usual, blank lines and lines
482 beginning with a hash (or pound sign or sharp or number sign,
483 whichever you like to call it) ignored.
484 Lines that start with a blank are treated as continuations of the
485 previous line (I don't like trailing slashes).
486
487 Each line contains a sequence of space-separated words, the first of
488 which identified the type of line. Keywords are case-insensitive, and
489 the first work on a line can be abbreviated to 3 letters.
490
491 There are two types of lines. ARRAY and DEVICE.
492
493 The DEVICE lines usually come first. All remaining words on the line
494 are treated as names of devices, possibly containing wild cards (see
495 .IR glob (7)).
496 These list all the devices that
497 .B mdctl
498 is allowed to scan
499 when looking for devices with RAID superblocks.
500 Each line can contain multiple device names, and there can be multiple
501 DEVICE lines. For example:
502 .IP
503 DEVICE /dev/hda* /dev/hdc*
504 .br
505 DEV /dev/sd*
506 .br
507 DEVICE /dev/discs/disc*/disc
508 .PP
509 The ARRAY lines identify actual arrays. The second word on the line
510 should be the name of the device where the array is normally
511 assembled, such as /dev/md1.
512 Subsequent words identify the array. If multiple identities are given,
513 then the array much match ALL identities to be considered a match.
514 Each identity word has a tag, and equals sign, and some value.
515 The options are:
516
517 .TP
518 .B uuid=
519 The value should be a 128 bit uuid in hexadecimal, with punctuation
520 interspersed if desired. This must match the uuid stored in the
521 superblock.
522 .TP
523 .B super-minor=
524 The value is an integer which indicates the minor number that was
525 stored in the superblock when the array was created. When an array is
526 created as /dev/mdX, then the minor number X is stored.
527 .TP
528 .B devices=
529 The value is a comma separated list of device names. Precisely these
530 devices will be used to assemble the array. Note that the devices
531 listed there must also be listed on a DEVICE line.
532 .TP
533 .B level=
534 The value is a raid level. This is normally used to identify an
535 array, but is supported so that the output of
536 .B "mdctl --examine --scan"
537 can be use directly in the configuration file.
538 .TP
539 .B disks=
540 The value is the number of disks in a complete active array. As with
541 .B level=
542 this is mainly for compatibility with the output of
543 .BR "mdctl --examine --scan" .
544
545 .SH TODO
546
547 Finish and document Follow mode.
548
549 .SH SEE ALSO
550 For information on the various levels of
23551 RAID, check out:
24552
25 http://ostenfeld.dk/~jakob/Software-RAID.HOWTO/
26
553 .IP
554 .UR http://ostenfeld.dk/~jakob/Software-RAID.HOWTO/
555 http://ostenfeld.dk/~jakob/Software-RAID.HOWTO/
556 .UE
557 .PP
27558 for new releases of the RAID driver check out:
28559
29 ftp://ftp.kernel.org/pub/linux/kernel/people/mingo/raid-patches
30
31 .B mdctl
32 is a single program that can be used to control Linux md devices. It
33 is intended to provide all the functionality (and more) of the mdtools
34 and raidtools but with a very different interface.
35
36 mdctl can perform all functions without a configuration file. There is the
37 option of using a configuration file, but not in the same way that raidtools
38 uses one. raidtools uses a configuration file to describe how to create a
39 RAID array, and also uses this file partially to start a previously created
40 RAID array. Further, raidtools requires the configuration file for such
41 things as stopping a raid array which needs to know nothing about the array.
42
43 The configuration file that can be used by mdctl lists two different things:
44
45 .IP "\fB\-\fP"
46 a list of md devices and information about how to identify each. The
47 identity can consist of a UUID, and minor-number as recorded on the
48 superblock, or a list of devices.
49
50 .IP "\fB\-\fP"
51 a list of devices that should be scanned for md sub-devices.
52
53 .SH MODES
54 mdctl has 4 major modes of operation:
55 .IP "\fBCreate\fP"
56 This mode is used to create a new array with a superblock. It can progress
57 in several step create-add-add-run or it can all happen with one command.
58
59 .IP "\fBAssemble\fP"
60 This mode is used to assemble the parts of a previously created
61 array into an active array. Components can be explicitly given
62 or can be searched for.
63 .B mdctl
64 (optionally) checks that the components
65 do form a bonafide array, and can, on request, fiddle superblock
66 version numbers so as to assemble a faulty array.
67
68 .IP "\fBBuild\fP"
69 This is for building legacy arrays without superblocks.
70
71 .IP "\fBManage\fP"
72 This is for odd bits an pieces like hotadd, hotremove, setfaulty, stop,
73 readonly,readwrite If an array is only partially setup by the
74 Create/Assemble/Build command, subsequent Manage commands can finish the
75 job.
76
77 .SH OPTIONS
78
79 Available options are:
80
81 .IP "\fB\-C\fP, \fB\-\-create\fP"
82 Create a new array
83
84 .IP "\fB-A\fP, \fB\-\-assemble\fP"
85 Assemble an existing array
86
87 .IP "\fB\-B\fP, \fB\-\-build\fP"
88 Build a legacy array without superblock
89
90 .IP "\fB\-D\fP, \fB\-\-detail\fP"
91 Print detail of a given md array
92
93 .IP "\fB\-E\fP, \fB\-\-examine\fP"
94 Print content of md superblock on device
95
96 .IP "\fB\-h\fP, \fB\-\-help\fP"
97 This help message or, after above option, mode specific help message
98
99 .IP "\fB\-V\fP, \fB\-\-version\fP"
100 Print version information for mdctl
101
102 .IP "\fB\-v\fP, \fB\-\-verbose\fP"
103 Be more verbose about what is happening
104
105 .SH For create or build:
106
107 .IP "\fB\-c\fP, \fB\-\-chunk=\fP"
108 chunk size of kibibytes
109
110 .IP "\fB\-\-rounding=\fP"
111 rounding factor for linear array (==chunk size)
112
113 .IP "\fB\-l\fP, \fB\-\-level=\fP"
114 raid level: 0,1,4,5,linear. 0 or linear for build
115
116 .IP "\fB\-p\fP, \fB\-\-parity=\fP"
117 raid5 parity algorithm: {left,right}-{,a}symmetric
118
119 .IP "\fB\-\-layout=\fP"
120 same as --parity
121
122 .IP "\fB\-n\fP, \fB\-\-raid-disks=\fP"
123 number of active devices in array
124
125 .IP "\fB\-x\fP, \fB\-\-spare-disks=\fP"
126 number of spares (eXtras) to allow space for
127
128 .IP "\fB\-z\fP, \fB\-\-size=\fP"
129 Size (in K) of each drive in RAID1/4/5 - optional
130
131 .SH For assemble:
132
133 .IP "\fB\-u\fP, \fB\-\-uuid=\fP"
134 uuid of array to assemble. Devices which don't have this uuid are excluded
135
136 .IP "\fB\-c\fP, \fB\-\-config=\fP"
137 config file
138
139 .IP "\fB\-s\fP, \fB\-\-scan\fP"
140 scan config file for missing information
141
142 .IP "\fB\-f\fP, \fB\-\-force\fP"
143 Assemble the array even if some superblocks appear out-of-date
144
145 .SH General management
146
147 .IP "\fB\-a\fP, \fB\-\-add\fP"
148 add, or hotadd subsequent devices
149
150 .IP "\fB\-r\fP, \fB\-\-remove\fP"
151 remove subsequent devices
152
153 .IP "\fB\-f\fP, \fB\-\-fail\fP"
154 mark subsequent devices a faulty
155
156 .IP "\fB\-\-set-faulty\fP"
157 same as --fail
158
159 .IP "\fB\-R\fP, \fB\-\-run\fP"
160 start a partially built array
161
162 .IP "\fB\-S\fP, \fB\-\-stop\fP"
163 deactivate array, releasing all resources
164
165 .IP "\fB\-o\fP, \fB\-\-readonly\fP"
166 mark array as readonly
167
168 .IP "\fB\-w\fP, \fB\-\-readwrite\fP"
169 mark array as readwrite
170
171 .SH CREATE MODE
172
173 Usage:
174
175 .B mdctl
176 --create device --chunk=X --level=Y --raid-disks=Z devices
177
178 This usage will initialise a new md array and possibly associate some
179 devices with it. If enough devices are given to complete the array, the
180 array will be activated. Otherwise it will be left inactive to be completed
181 and activated by subsequent management commands.
182
183 As devices are added, they are checked to see if they contain raid
184 superblocks or filesystems. They are also check to see if the variance in
185 device size exceeds 1%.
186
187 If any discrepancy is found, the array will not automatically be run, though
188 the presence of a
189 .B --run
190 can override this caution.
191
192 If the
193 .B --size
194 option is given, it is not necessary to list any subdevices in this command.
195 They can be added later, before a
196 .B --run.
197 If no
198 .B --size
199 is given, the apparent size of the smallest drive given is used.
200
201 The General management options that are valid with --create are:
202 .IP "\fB\-\-run\fP"
203 insist of running the array even if not all devices are present or some look
204 odd.
205
206 .IP "\fB\-\-readonly\fP"
207 start the array readonly - not supported yet.
208
209 .SH ASSEMBLY MODE
210
211 Usage:
212
213 .B mdctl
214 --assemble device options...
215
216 .B mdctl
217 --assemble --scan options...
218
219 This usage assembles one or more raid arrays from pre-existing components.
220 For each array, mdctl needs to know the md device, the uuid, and a number of
221 sub devices. These can be found in a number of ways.
222
223 The md device is either given before
224 .B --scan
225 or is found from the config file. In the latter case, multiple md devices
226 can be started with a single mdctl command.
227
228 The uuid can be given with the
229 .B --uuid
230 option, or can be found in in the config file, or will be taken from the
231 super block on the first subdevice listed on the command line or in a
232 subsequent
233 .B --add
234 command.
235
236 Devices can be given on the
237 .B --assemble
238 command line, on subsequent
239 .B 'mdctl --add'
240 command lines, or from the config file. Only devices which have an md
241 superblock which contains the right uuid will be considered for any device.
242
243 The config file is only used if explicitly named with
244 .B --config
245 or requested with
246 .B --scan.
247 In the later case,
248 .B /etc/md.conf
249 is used.
250
251 If
252 .B --scan
253 is not given, then the config file will only be used to find uuids for md
254 arrays.
255
256 The format of the config file is:
257 not yet documented
258
259 .SH BUILD MDOE
260
261 Usage:
262
263 .B mdctl
264 --build device -chunk=X --level=Y --raid-disks=Z devices
265
266 This usage is similar to
267 .B --create.
268 The difference is that it creates a legacy array without a superblock. With
269 these arrays there is no different between initially creating the array and
270 subsequently assembling the array, except that hopefully there is useful
271 data there in the second case.
272
273 The level may only be 0 or linear. All devices must be listed and the array
274 will be started once complete.
275
276 .SH BUGS
277 no known bugs.
278
279 .SH TODO
280
281
282 .SH SEE ALSO
560 .IP
561 .UR ftp://ftp.kernel.org/pub/linux/kernel/people/mingo/raid-patches
562 ftp://ftp.kernel.org/pub/linux/kernel/people/mingo/raid-patches
563 .UE
564 .PP
565 or
566 .IP
567 .UR http://www.cse.unsw.edu.au/~neilb/patches/linux-stable/
568 http://www.cse.unsw.edu.au/~neilb/patches/linux-stable/
569 .URk
570 .PP
283571 .IR raidtab (5),
284572 .IR raid0run (8),
285573 .IR raidstop (8),
00 /*
11 * mdctl - manage Linux "md" devices aka RAID arrays.
22 *
3 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 *
55 *
66 * This program is free software; you can redistribute it and/or modify
6363 int sparedisks = 0;
6464 struct mddev_ident_s ident;
6565 char *configfile = NULL;
66 char *cp;
6667 int scan = 0;
6768 char devmode = 0;
6869 int runstop = 0;
6970 int readonly = 0;
70 char *devs[MD_SB_DISKS+1];
71 int devmodes[MD_SB_DISKS+1];
71 mddev_dev_t devlist = NULL;
72 mddev_dev_t *devlistend = & devlist;
73 mddev_dev_t dv;
7274 int devs_found = 0;
7375 int verbose = 0;
76 int brief = 0;
7477 int force = 0;
7578
7679 char *mailaddr = NULL;
8083 int mdfd = -1;
8184
8285 ident.uuid_set=0;
86 ident.level = -10;
87 ident.raid_disks = -1;
8388 ident.super_minor= -1;
8489 ident.devices=0;
8590
123128 case 'v': verbose = 1;
124129 continue;
125130
131 case 'b': brief = 1;
132 continue;
133
126134 case 1: /* an undecorated option - must be a device name.
127135 * Depending on mode, it could be that:
128 * All devices listed are "md" devices : --Detail, -As
129 * No devices are "md" devices : --Examine
130 * First device is "md", others are component: -A,-B,-C
136 * All devices listed are "md" devices : --Detail, -As
137 * No devices are "md" devices : --Examine
138 * First device is "md", others are component: -A,-B,-C
139 * Only accept on device before mode is determined.
140 * If mode is @, then require devmode for other devices.
131141 */
132 if (devs_found >= MD_SB_DISKS+1) {
133 fprintf(stderr, Name ": too many devices at %s - current limit -s %d\n",
134 optarg, MD_SB_DISKS+1);
135 exit(2);
136 }
137 devs[devs_found] = optarg;
138 devmodes[devs_found] = devmode;
142 if (devs_found > 0 && !mode ) {
143 fprintf(stderr, Name ": Must give mode flag before second device name at %s\n", optarg);
144 exit(2);
145 }
146 if (devs_found > 0 && mode == '@' && !devmode) {
147 fprintf(stderr, Name ": Must give on of -a/-r/-f for subsequent devices at %s\n", optarg);
148 exit(2);
149 }
150 dv = malloc(sizeof(*dv));
151 if (dv == NULL) {
152 fprintf(stderr, Name ": malloc failed\n");
153 exit(3);
154 }
155 dv->devname = optarg;
156 dv->disposition = devmode;
157 dv->next = NULL;
158 *devlistend = dv;
159 devlistend = &dv->next;
160
139161 devs_found++;
140162 continue;
141163
204226 optarg);
205227 exit(2);
206228 }
229 ident.level = level;
207230 continue;
208231
209232 case O('C','p'): /* raid5 layout */
245268 optarg);
246269 exit(2);
247270 }
271 ident.raid_disks = raiddisks;
248272 continue;
249273
250274 case O('C','x'): /* number of spare (eXtra) discs */
275299 continue;
276300 case O('A','u'): /* uuid of array */
277301 if (ident.uuid_set) {
278 fprintf(stderr, Name ": uuid cannot bet set twice. "
302 fprintf(stderr, Name ": uuid cannot be set twice. "
279303 "Second value %s.\n", optarg);
280304 exit(2);
281305 }
283307 ident.uuid_set = 1;
284308 else {
285309 fprintf(stderr,Name ": Bad uuid: %s\n", optarg);
310 exit(2);
311 }
312 continue;
313
314 case O('A','m'): /* super-minor for array */
315 if (ident.super_minor >= 0) {
316 fprintf(stderr, Name ": super-minor cannot be set twice. "
317 "Second value: %s.\n", optarg);
318 exit(2);
319 }
320 ident.super_minor = strtoul(optarg, &cp, 10);
321 if (!optarg[0] || *cp) {
322 fprintf(stderr, Name ": Bad super-minor number: %s.\n", optarg);
286323 exit(2);
287324 }
288325 continue;
298335 /* FIXME possibly check that config file exists. Even parse it */
299336 continue;
300337 case O('A','s'): /* scan */
338 case O('E','s'):
301339 scan = 1;
302340 continue;
303341
408446 fprintf(stderr, Name ": an md device must be given in this mode\n");
409447 exit(2);
410448 }
411 mdfd = open_mddev(devs[0]);
449 mdfd = open_mddev(devlist->devname);
412450 if (mdfd < 0)
413451 exit(1);
414452 }
419457 case '@':/* Management */
420458 /* readonly, add/remove, readwrite, runstop */
421459 if (readonly>0)
422 rv = Manage_ro(devs[0], mdfd, readonly);
460 rv = Manage_ro(devlist->devname, mdfd, readonly);
423461 if (!rv && devs_found>1)
424 rv = Manage_subdevs(devs[0], mdfd,
425 devs_found-1, devs+1, devmodes+1);
462 rv = Manage_subdevs(devlist->devname, mdfd,
463 devlist->next);
426464 if (!rv && readonly < 0)
427 rv = Manage_ro(devs[0], mdfd, readonly);
465 rv = Manage_ro(devlist->devname, mdfd, readonly);
428466 if (!rv && runstop)
429 rv = Manage_runstop(devs[0], mdfd, runstop);
467 rv = Manage_runstop(devlist->devname, mdfd, runstop);
430468 break;
431469 case 'A': /* Assemble */
432470 if (!scan)
433 rv = Assemble(devs[0], mdfd, &ident, configfile,
434 devs_found-1, devs+1,
471 rv = Assemble(devlist->devname, mdfd, &ident, configfile,
472 devlist->next,
435473 readonly, runstop, verbose, force);
436474 else if (devs_found>0)
437 for (i=0; i<devs_found; i++) {
438 mddev_ident_t array_ident = conf_get_ident(configfile, devs[i]);
439 mdfd = open_mddev(devs[i]);
475 for (dv = devlist ; dv ; dv=dv->next) {
476 mddev_ident_t array_ident = conf_get_ident(configfile, dv->devname);
477 mdfd = open_mddev(dv->devname);
440478 if (mdfd < 0) {
441479 rv |= 1;
442480 continue;
443481 }
444482 if (array_ident == NULL) {
445483 fprintf(stderr, Name ": %s not identified in config file.\n",
446 devs[i]);
484 dv->devname);
447485 rv |= 1;
448486 continue;
449487 }
450 rv |= Assemble(devs[i], mdfd, array_ident, configfile,
451 0, NULL,
488 rv |= Assemble(dv->devname, mdfd, array_ident, configfile,
489 NULL,
452490 readonly, runstop, verbose, force);
453491 }
454492 else {
458496 rv = 1;
459497 } else
460498 for (; array_list; array_list = array_list->next) {
499 mdu_array_info_t array;
461500 mdfd = open_mddev(array_list->devname);
462501 if (mdfd < 0) {
463502 rv |= 1;
464503 continue;
465504 }
505 if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0)
506 /* already assembled, skip */
507 continue;
466508 rv |= Assemble(array_list->devname, mdfd,
467509 array_list, configfile,
468 0, NULL,
510 NULL,
469511 readonly, runstop, verbose, force);
470512 }
471513 }
472514 break;
473515 case 'B': /* Build */
474 rv = Build(devs[0], mdfd, chunk, level, raiddisks, devs_found-1,devs+1);
516 rv = Build(devlist->devname, mdfd, chunk, level, raiddisks, devlist->next);
475517 break;
476518 case 'C': /* Create */
477 rv = Create(devs[0], mdfd, chunk, level, layout, size,
519 rv = Create(devlist->devname, mdfd, chunk, level, layout, size,
478520 raiddisks, sparedisks,
479 devs_found-1,devs+1, runstop, verbose, force);
521 devs_found-1, devlist->next, runstop, verbose, force);
480522 break;
481523 case 'D': /* Detail */
482 for (i=0; i<devs_found; i++)
483 rv |= Detail(devs[i]);
524 for (dv=devlist ; dv; dv=dv->next)
525 rv |= Detail(dv->devname, brief);
484526 break;
485527 case 'E': /* Examine */
486 for (i=0; i<devs_found; i++)
487 rv |= Examine(devs[i]);
528 if (devlist == NULL && scan==0) {
529 fprintf(stderr, Name ": No devices to examine\n");
530 exit(2);
531 }
532 rv = Examine(devlist, devlist?brief:!verbose, configfile);
488533 break;
489534 case 'F': /* Follow */
490 rv= Monitor(devs_found, devs, mailaddr, program,
535 rv= Monitor(devlist, mailaddr, program,
491536 delay?delay:60, configfile);
492537 }
493538 exit(rv);
00 /*
11 * mdctl - manage Linux "md" devices aka RAID arrays.
22 *
3 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 *
55 *
66 * This program is free software; you can redistribute it and/or modify
7575 char *devices; /* comma separated list of device
7676 * names with wild cards
7777 */
78
78 int level; /* -10 if not set */
79 int raid_disks; /* -1 if not set */
7980 char *spare_group;
8081 struct mddev_ident_s *next;
8182 } *mddev_ident_t;
8384 /* List of device names - wildcards expanded */
8485 typedef struct mddev_dev_s {
8586 char *devname;
87 char disposition; /* 'a' for add, 'r' for remove, 'f' for fail.
88 * Not set for names read from .config
89 */
8690 struct mddev_dev_s *next;
8791 } *mddev_dev_t;
8892
105109 extern int Manage_ro(char *devname, int fd, int readonly);
106110 extern int Manage_runstop(char *devname, int fd, int runstop);
107111 extern int Manage_subdevs(char *devname, int fd,
108 int devcnt, char *devnames[], int devmodes[]);
112 mddev_dev_t devlist);
109113
110114
111115 extern int Assemble(char *mddev, int mdfd,
112116 mddev_ident_t ident,
113117 char *conffile,
114 int subdevs, char *subdev[],
118 mddev_dev_t devlist,
115119 int readonly, int runstop,
116120 int verbose, int force);
117121
118122 extern int Build(char *mddev, int mdfd, int chunk, int level,
119123 int raiddisks,
120 int subdevs, char *subdev[]);
124 mddev_dev_t devlist);
121125
122126
123127 extern int Create(char *mddev, int mdfd,
124128 int chunk, int level, int layout, int size, int raiddisks, int sparedisks,
125 int subdevs, char *subdev[],
129 int subdevs, mddev_dev_t devlist,
126130 int runstop, int verbose, int force);
127131
128 extern int Detail(char *dev);
129 extern int Examine(char *dev);
130 extern int Monitor(int num_devs, char *devlist[],
132 extern int Detail(char *dev, int brief);
133 extern int Examine(mddev_dev_t devlist, int brief, char *conffile);
134 extern int Monitor(mddev_dev_t devlist,
131135 char *mailaddr, char *alert_cmd,
132136 int period,
133137 char *config);
141145
142146 extern mddev_ident_t conf_get_ident(char *, char*);
143147 extern mddev_dev_t conf_get_devs(char *);
148
149 extern char *human_size(long kbytes);
0 mdctl(8) mdctl(8)
1
2
3
4 NNAAMMEE
5 mdctl - manage MD devices _a_k_a Linux Software Raid.
6
7
8 SSYYNNOOPPSSIISS
9 mmddccttll _[_m_o_d_e_] _<_r_a_i_d_d_e_v_i_c_e_> _[_o_p_t_i_o_n_s_] _<_s_u_b_d_e_v_i_c_e_s_>
10
11
12 DDEESSCCRRIIPPTTIIOONN
13 RAID devices are virtual devices created from two or more
14 real block devices. This allows multiple devices (typi-
15 cally disk drives or partitions there-of) to be combined
16 into a single device to hold (for example) a single
17 filesystem. Some RAID levels included redundancy and so
18 can survive some degree of device failure.
19
20 Linux Software RAID devices are implemented through the md
21 (Multiple Devices) device driver.
22
23 Currently, Linux supports LLIINNEEAARR md devices, RRAAIIDD00 (strip-
24 ing), RRAAIIDD11 (mirroring), RRAAIIDD44 and RRAAIIDD55..
25
26 Recent kernels (2002) also support a mode known as MMUULLTTII--
27 PPAATTHH. mmddccttll does not support MULTIPATH as yet.
28
29 mmddccttll is a program that can be used to create and manage
30 MD devices. As such it provides a similar set of func-
31 tionality to the rraaiiddttoooollss packages. The key differences
32 between mmddccttll and rraaiiddttoooollss are:
33
34 +o mmddccttll is a single program and not a collection of pro-
35 grams.
36
37 +o mmddccttll can perform (almost) all of its functions with-
38 out having a configuration file. Also mdctl helps
39 with management of the configuration file.
40
41 +o mmddccttll can provide information about your arrays
42 (through Detail and Examine) that rraaiiddttoooollss cannot.
43
44 +o rraaiiddttoooollss can manage MULTIPATH devices which mmddccttll
45 cannot yet manage.
46
47
48 MMOODDEESS
49 mdctl has 7 major modes of operation:
50
51 AAsssseemmbbllee
52 Assemble the parts of a previously created array
53 into an active array. Components can be explicitly
54 given or can be searched for. mmddccttll checks that
55 the components do form a bona fide array, and can,
56 on request, fiddle superblock information so as to
57 assemble a faulty array.
58
59
60 BBuuiilldd Build a legacy array without per-device
61 superblocks.
62
63
64 CCrreeaattee Create a new array with per-device superblocks.
65
66
67 DDeettaaiill Display the details of a given md device. Details
68 include the RAID level, the number of devices,
69 which ones are faulty (if any), and the array UUID.
70
71
72 EExxaammiinnee
73 Examine a device to see if it is part of an md
74 array, and print out the details of that array.
75 This mode can also be used to examine a large num-
76 ber of devices and to print out a summary of the
77 arrays found in a format suitable for the
78 mmddccttll..ccoonnff configuration file.
79
80
81 FFoollllooww oorr MMoonniittoorr
82 Monitor one or more md devices and act on any state
83 changes.
84
85
86 MMaannaaggee This is for odd bits an pieces like hotadd,
87 hotremove, setfaulty, stop, readonly, readwrite.
88
89
90 OOPPTTIIOONNSS
91 Available options are:
92
93
94 --AA, ----aasssseemmbbllee
95 Assemble an existing array.
96
97
98 --BB, ----bbuuiilldd
99 Build a legacy array without superblocks.
100
101
102 --CC, ----ccrreeaattee
103 Create a new array.
104
105
106 --DD, ----ddeettaaiill
107 Print detail of one or more md devices.
108
109
110 --EE, ----eexxaammiinnee
111 Print content of md superblock on device(s).
112
113
114 --FF, ----ffoollllooww, ----mmoonniittoorr
115 Select MMoonniittoorr mode.
116
117
118 --hh, ----hheellpp
119 Display help message or, after above option, mode
120 specific help message.
121
122
123 --VV, ----vveerrssiioonn
124 Print version information for mdctl.
125
126
127 --vv, ----vveerrbboossee
128 Be more verbose about what is happening.
129
130
131 --bb, ----bbrriieeff
132 Be less verbose. This is used with ----ddeettaaiill and
133 ----eexxaammiinnee.
134
135
136 FFoorr ccrreeaattee oorr bbuuiilldd::
137 --cc, ----cchhuunnkk==
138 Specify chunk size of kibibytes. The default is
139 64.
140
141
142 ----rroouunnddiinngg==
143 Specify rounding factor for linear array (==chunk
144 size)
145
146
147 --ll, ----lleevveell==
148 Set raid level. Options are: linear, raid0, 0,
149 stripe, raid1, 1, mirror, raid5, 4, raid5, 5.
150 Obviously some of these are synonymous. Only the
151 first 4 are valid when Building.
152
153
154 --pp, ----ppaarriittyy==
155 Set raid5 parity algorithm. Options are:
156 {left,right}-{,a}symmetric, la, ra, ls, rs. The
157 default is left-symmetric.
158
159
160 ----llaayyoouutt==
161 same as --parity
162
163
164 --nn, ----rraaiidd--ddiisskkss==
165 number of active devices in array.
166
167
168 --xx, ----ssppaarree--ddiisskkss==
169 number of spare (eXtra) disks in initial array.
170 Spares can be added and removed later.
171
172
173 --zz, ----ssiizzee==
174 Amount (in Kibibytes) of space to use from each
175 drive in RAID1/4/5. This must be a multiple of the
176 chunk size, and must leave about 128Kb of space at
177 the end of the drive for the RAID superblock. If
178 this is not specified (as it normally is not) the
179 smallest drive (or partition) sets the size, though
180 if there is a variance among the drives of greater
181 than 1%, a warning is issued.
182
183
184 FFoorr aasssseemmbbllee::
185 --uu, ----uuuuiidd==
186 uuid of array to assemble. Devices which don't have
187 this uuid are excluded
188
189
190 --mm, ----ssuuppeerr--mmiinnoorr==
191 Minor number of device that array was created for.
192 Devices which don't have this minor number are
193 excluded. If you create an array as /dev/md1, then
194 all superblock will contain the minor number 1,
195 even if the array is later assembled as /dev/md2.
196
197
198 --cc, ----ccoonnffiigg==
199 config file. Default is //eettcc//mmddccttll..ccoonnff.
200
201
202 --ss, ----ssccaann
203 scan config file for missing information
204
205
206 --ff, ----ffoorrccee
207 Assemble the array even if some superblocks appear
208 out-of-date
209
210
211 --RR, ----rruunn
212 Attempt to start the array even if fewer drives
213 were given than are needed for a full array. Nor-
214 mally if not all drives are found and ----ssccaann is not
215 used, then the array will be assembled but not
216 started. With ----rruunn an attempt will be made to
217 start it anyway.
218
219
220 GGeenneerraall mmaannaaggeemmeenntt
221 --aa, ----aadddd
222 hotadd listed devices.
223
224
225 --rr, ----rreemmoovvee
226 remove listed devices. The must not be active.
227 i.e. they should be failed or spare devices.
228
229
230 --ff, ----ffaaiill
231 mark listed devices as faulty.
232
233
234 ----sseett--ffaauullttyy
235 same as --fail.
236
237
238 --RR, ----rruunn
239 start a partially built array.
240
241
242 --SS, ----ssttoopp
243 deactivate array, releasing all resources.
244
245
246 --oo, ----rreeaaddoonnllyy
247 mark array as readonly.
248
249
250 --ww, ----rreeaaddwwrriittee
251 mark array as readwrite.
252
253
254
255 AASSSSEEMMBBLLYY MMOODDEE
256 Usage: mmddccttll ----aasssseemmbbllee _d_e_v_i_c_e _o_p_t_i_o_n_s_._._.
257
258 Usage: mmddccttll ----aasssseemmbbllee ----ssccaann _o_p_t_i_o_n_s_._._.
259
260
261 This usage assembles one or more raid arrays from pre-
262 existing components. For each array, mdctl needs to know
263 the md device, the identity of the array, and a number of
264 sub devices. These can be found in a number of ways.
265
266 The md device is either given before ----ssccaann or is found
267 from the config file. In the latter case, multiple md
268 devices can be started with a single mdctl command.
269
270 The identity can be given with the ----uuuuiidd option, with the
271 ----ssuuppeerr--mmiinnoorr option, can be found in in the config file,
272 or will be taken from the super block on the first subde-
273 vice listed on the command line.
274
275 Devices can be given on the ----aasssseemmbbllee command line or
276 from the config file. Only devices which have an md
277 superblock which contains the right identity will be con-
278 sidered for any device.
279
280 The config file is only used if explicitly named with
281 ----ccoonnffiigg or requested with ----ssccaann.. In the later case,
282 //eettcc//mmddccttll..ccoonnff is used.
283
284 If ----ssccaann is not given, then the config file will only be
285 used to find the identity of md arrays.
286
287 Normally the array will be started after it is assembled.
288 However is ----ssccaann is not given and insufficient drives
289 were lists to start a complete (non-degraded) array, then
290 the array is not started (to guard against usage errors).
291 To insist that the array be started in this case (as may
292 work for RAID1 or RAID5), give the ----rruunn flag.
293
294
295
296 BBUUIILLDD MMOODDEE
297 Usage: mmddccttll ----bbuuiilldd _d_e_v_i_c_e ----cchhuunnkk==_X ----lleevveell==_Y ----rraaiidd--
298 ddiisskkss==_Z _d_e_v_i_c_e_s
299
300
301 This usage is similar to ----ccrreeaattee. The difference is that
302 it creates a legacy array without a superblock. With these
303 arrays there is no difference between initially creating
304 the array and subsequently assembling the array, except
305 that hopefully there is useful data there in the second
306 case.
307
308 The level may only be 0, raid0, or linear. All devices
309 must be listed and the array will be started once com-
310 plete.
311
312
313 CCRREEAATTEE MMOODDEE
314 Usage: mmddccttll ----ccrreeaattee _d_e_v_i_c_e ----cchhuunnkk==_X ----lleevveell==_Y
315 ----rraaiidd--ddiisskkss==_Z _d_e_v_i_c_e_s
316
317
318 This usage will initialise a new md array, associate some
319 devices with it, and activate the array.
320
321 As devices are added, they are checked to see if they con-
322 tain raid superblocks or filesystems. They are also check
323 to see if the variance in device size exceeds 1%.
324
325 If any discrepancy is found, the array will not automati-
326 cally be run, though the presence of a ----rruunn can override
327 this caution.
328
329
330 The General Management options that are valid with --cre-
331 ate are:
332
333 ----rruunn insist of running the array even if some devices
334 look like they might be in use.
335
336
337 ----rreeaaddoonnllyy
338 start the array readonly - not supported yet.
339
340
341 DDEETTAAIILL MMOODDEE
342 Usage: mmddccttll ----ddeettaaiill [----bbrriieeff] _d_e_v_i_c_e _._._.
343
344
345 This usage sill print out the details of the given array
346 including a list of component devices. To determine names
347 for the devices, mmddccttll searches //ddeevv for device files with
348 the right major and minor numbers.
349
350 With ----bbrriieeff mmddccttll prints a single line that identifies
351 the level, number of disks, and UUID of the array. This
352 line is suitable for inclusion in //eettcc//mmddccttll..ccoonnff.
353
354
355 EEXXAAMMIINNEE MMOODDEE
356 Usage: mmddccttll ----eexxaammiinnee [----ssccaann] [----bbrriieeff] _d_e_v_i_c_e _._._.
357
358 This usage will examine some block devices to see if that
359 have a valid RAID superblock on them. The information in
360 each valid raid superblock will be printed.
361
362 If ----ssccaann is used, the no devices should be listed, and
363 the complete set of devices identified in the configura-
364 tion file are checked. ----ssccaann implies ----bbrriieeff but this
365 implication can be countered by specifying ----vveerrbboossee.
366
367 With ----bbrriieeff mmddccttll will output an config file entry of
368 each distinct array that was found. This entry will list
369 the UUID, the raid level, and a list of the individual
370 devices on which a superblock for that array was found.
371 This output will by syntactically suitable for inclusion
372 in the configuration file, but should NNOOTT be used blindly.
373 Often the array description that you want in the configu-
374 ration file is much less specific than that given by mmddccttll
375 --BBss. For example, you normally do not want to list the
376 devices, particularly if they are SCSI devices.
377
378
379
380 FFIILLEESS
381 //pprroocc//mmddssttaatt
382 If you're using the //pprroocc filesystem, //pprroocc//mmddssttaatt gives
383 you informations about md devices status. This file is
384 not currently used by mmddccttll.
385
386
387 //eettcc//mmddccttll..ccoonnff
388 The config file is line oriented with, as usual, blank
389 lines and lines beginning with a hash (or pound sign or
390 sharp or number sign, whichever you like to call it)
391 ignored. Lines that start with a blank are treated as
392 continuations of the previous line (I don't like trailing
393 slashes).
394
395 Each line contains a sequence of space-separated words,
396 the first of which identified the type of line. Keywords
397 are case-insensitive, and the first work on a line can be
398 abbreviated to 3 letters.
399
400 There are two types of lines. ARRAY and DEVICE.
401
402 The DEVICE lines usually come first. All remaining words
403 on the line are treated as names of devices, possibly con-
404 taining wild cards (see _g_l_o_b(7)). These list all the
405 devices that mmddccttll is allowed to scan when looking for
406 devices with RAID superblocks. Each line can contain mul-
407 tiple device names, and there can be multiple DEVICE
408 lines. For example:
409
410 DEVICE /dev/hda* /dev/hdc*
411 DEV /dev/sd*
412 DEVICE /dev/discs/disc*/disc
413
414 The ARRAY lines identify actual arrays. The second word
415 on the line should be the name of the device where the
416 array is normally assembled, such as /dev/md1. Subsequent
417 words identify the array. If multiple identities are
418 given, then the array much match ALL identities to be con-
419 sidered a match. Each identity word has a tag, and equals
420 sign, and some value. The options are:
421
422
423 uuuuiidd== The value should be a 128 bit uuid in hexadecimal,
424 with punctuation interspersed if desired. This
425 must match the uuid stored in the superblock.
426
427 ssuuppeerr--mmiinnoorr==
428 The value is an integer which indicates the minor
429 number that was stored in the superblock when the
430 array was created. When an array is created as
431 /dev/mdX, then the minor number X is stored.
432
433 ddeevviicceess==
434 The value is a comma separated list of device
435 names. Precisely these devices will be used to
436 assemble the array. Note that the devices listed
437 there must also be listed on a DEVICE line.
438
439 lleevveell== The value is a raid level. This is normally used
440 to identify an array, but is supported so that the
441 output of mmddccttll ----eexxaammiinnee ----ssccaann can be use
442 directly in the configuration file.
443
444 ddiisskkss== The value is the number of disks in a complete
445 active array. As with lleevveell== this is mainly for
446 compatibility with the output of mmddccttll ----eexxaammiinnee
447 ----ssccaann.
448
449
450 TTOODDOO
451 Finish and document Follow mode.
452
453
454 SSEEEE AALLSSOO
455 For information on the various levels of RAID, check out:
456
457
458 http://ostenfeld.dk/~jakob/Software-RAID.HOWTO/
459
460 for new releases of the RAID driver check out:
461
462
463 ftp://ftp.kernel.org/pub/linux/kernel/peo-
464 ple/mingo/raid-patches
465
466 or
467
468 http://www.cse.unsw.edu.au/~neilb/patches/linux-
469 stable/
470
471 _r_a_i_d_t_a_b(5), _r_a_i_d_0_r_u_n(8), _r_a_i_d_s_t_o_p(8), _m_k_r_a_i_d(8)
472
473
474
475 mdctl(8)
00 /*
11 * mdctl - manage Linux "md" devices aka RAID arrays.
22 *
3 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
3 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
44 *
55 *
66 * This program is free software; you can redistribute it and/or modify
423423 super->sb_csum = oldcsum;
424424 return csum;
425425 }
426
427 char *human_size(long kbytes)
428 {
429 static char buf[30];
430
431 if (kbytes < 2000)
432 buf[0]=0;
433 else if (kbytes < 2*1024*1024)
434 sprintf(buf, " (%d MiB)", kbytes>>10);
435 else
436 sprintf(buf, " (%d GiB)", kbytes>>20);
437 return buf;
438 }