]>
git.ipfire.org Git - thirdparty/mdadm.git/blob - Assemble.c
2 * mdctl - manage Linux "md" devices aka RAID arrays.
4 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Email: <neilb@cse.unsw.edu.au>
24 * School of Computer Science and Engineering
25 * The University of New South Wales
34 int Assemble(char *mddev
, int mdfd
,
35 int uuid
[4], int uuidset
,
36 char *conffile
, int scan
,
37 int subdevs
, char **subdev
,
38 int readonly
, int runstop
,
39 int verbose
, int force
)
42 * The task of Assemble is to submit a
43 * SET_ARRAY_INFO ioctl with no arg - to prepare
44 * the array - and then submit a number of
45 * ADD_NEW_DISK ioctls to add disks into
46 * the array. Finally RUN_ARRAY might
47 * be submitted to start the array.
49 * Much of the work of Assemble is in finding and/or
50 * checking the disks to make sure they look right.
52 * If mddev is not set, then scan must be and we
53 * read through the config file for dev+uuid mapping
54 * We recurse, setting mddev, for each device that
56 * - has a valid uuid (or any uuid if !uuidset
58 * If mddev is set, we try to determine state of md.
59 * check version - must be at least 0.90.0
60 * check kernel version. must be at least 2.4.
61 * If not, we can possibly fall back on START_ARRAY
62 * Try to GET_ARRAY_INFO.
63 * If possible, give up
64 * If not, try to STOP_ARRAY just to make sure
66 * If !uuidset and scan, look in conf-file for uuid
67 * If not found, give up
68 * If !subdevs and scan and uuidset, get list of devs from conf-file
71 * Check superblock - discard if bad
72 * Check uuid (set if we don't have one) - discard if no match
73 * Check superblock similarity if we have a superbloc - discard if different
74 * Record events, devicenum, utime
75 * This should give us a list of devices for the array
76 * We should collect the most recent event and utime numbers
78 * Count disks with recent enough event count
79 * While force && !enough disks
80 * Choose newest rejected disks, update event count
81 * mark clean and rewrite superblock
84 * foreach device with recent events : ADD_NEW_DISK
85 * if runstop == 1 || "enough" disks and runstop==0 -> RUN_ARRAY
87 * Check the device numbers in superblock are right
88 * update superblock if any changes
94 mdu_array_info_t array
;
95 mddev_dev_t devlist
= NULL
;
96 mdp_super_t first_super
, super
;
103 } devices
[MD_SB_DISKS
];
104 int best
[MD_SB_DISKS
]; /* indexed by raid_disk */
105 int devcnt
= 0, okcnt
;
109 if (!mddev
&& !scan
) {
110 fputs(Name
": internal error - Assemble called with no devie or scan\n", stderr
);
114 mddev_uuid_t device_list
;
116 device_list
= conf_get_uuids(conffile
);
118 fprintf(stderr
, Name
": No devices found in config file\n");
121 while (device_list
) {
122 if (!uuidset
|| same_uuid(device_list
->uuid
,uuid
)) {
123 mdfd
= open(device_list
->devname
, O_RDONLY
, 0);
126 Name
": error opening %s: %s\n",
127 device_list
->devname
,
131 if (Assemble(device_list
->devname
, mdfd
,
132 device_list
->uuid
, 1,
135 readonly
, runstop
, verbose
, force
)==0)
139 device_list
= device_list
->next
;
143 fprintf(stderr
,Name
": Did not successful Assemble any devices\n");
148 * Ok, we have an mddev, check it out
150 vers
= md_get_version(mdfd
);
152 fprintf(stderr
, Name
": %s appears not to be an md device.\n");
156 fprintf(stderr
, Name
": Assemble requires driver version 0.90.0 or later.\n"
157 " Upgrade your kernel or try --Build\n");
160 if (get_linux_version() < 2004000)
163 if (ioctl(mdfd
, GET_ARRAY_INFO
, &array
)>=0) {
164 fprintf(stderr
, Name
": device %s already active - cannot assemble it\n",
168 ioctl(mdfd
, STOP_ARRAY
, NULL
); /* just incase it was started but has no content */
171 * We have a valid mddev, check out uuid
173 if (!uuidset
&& scan
) {
174 /* device must be listed with uuid in conf file */
175 mddev_uuid_t device_list
;
176 device_list
= conf_get_uuids(conffile
);
177 while (device_list
&&
178 strcmp(device_list
->devname
, mddev
) != 0)
179 device_list
= device_list
->next
;
182 fprintf(stderr
, Name
": --scan set and no uuid found for %s in config file.\n",
186 /* the uuid is safe until next call to conf_get_uuids */
187 uuid
= device_list
->uuid
;
191 /* Now to start looking at devices.
192 * If no devices were given, but a uuid is available and
193 * --scan was set, then we should scan all devices listed in the
197 if (subdevs
==0 && scan
&& uuidset
)
198 devlist
= conf_get_devs(conffile
);
200 if (subdevs
== 0 && devlist
== NULL
) {
201 fprintf(stderr
, Name
": no devices given for %s\n", mddev
);
204 /* now for each device */
205 first_super
.md_magic
= 0;
206 for (i
=0; i
<MD_SB_DISKS
; i
++)
209 while (subdevs
|| devlist
) {
220 devname
= devlist
->devname
;
221 devlist
= devlist
->next
;
225 dfd
= open(devname
, O_RDONLY
, 0);
227 if (inargv
|| verbose
)
228 fprintf(stderr
, Name
": cannot open device %s: %s\n",
229 devname
, strerror(errno
));
232 if (fstat(dfd
, &stb
)< 0) {
234 fprintf(stderr
, Name
": fstat failed for %s: %s\n",
235 devname
, strerror(errno
));
239 if ((stb
.st_mode
& S_IFMT
) != S_IFBLK
) {
240 fprintf(stderr
, Name
": %d is not a block device.\n",
245 if (load_super(dfd
, &super
)) {
246 if (inargv
|| verbose
)
247 fprintf( stderr
, Name
": no RAID superblock on %s\n",
253 if (compare_super(&first_super
, &super
)) {
254 if (inargv
|| verbose
)
255 fprintf(stderr
, Name
": superblock on %s doesn't match\n",
260 uuid_from_super(this_uuid
, &first_super
);
261 if (!same_uuid(this_uuid
, uuid
)) {
262 if (inargv
|| verbose
)
263 fprintf(stderr
, Name
": %s has wrong uuid.\n",
268 uuid_from_super(uuid
, &first_super
);
272 /* Ok, this one is at least worth considering */
273 if (devcnt
>= MD_SB_DISKS
) {
274 fprintf(stderr
, Name
": ouch - too many devices appear to be in this array. Ignoring %s\n",
278 devices
[devcnt
].devname
= devname
;
279 devices
[devcnt
].major
= MAJOR(stb
.st_rdev
);
280 devices
[devcnt
].minor
= MINOR(stb
.st_rdev
);
281 devices
[devcnt
].events
= md_event(&super
);
282 devices
[devcnt
].utime
= super
.utime
;
283 devices
[devcnt
].uptodate
= 0;
284 if (most_recent
< devcnt
) {
285 if (devices
[devcnt
].events
286 > devices
[most_recent
].events
)
287 most_recent
= devcnt
;
289 i
= super
.this_disk
.raid_disk
;
291 || devices
[best
[i
]].events
< devices
[devcnt
].events
) {
298 fprintf(stderr
, Name
": no devices found for %s\n",
302 /* now we have some devices that might be suitable.
306 for (i
=0; i
< first_super
.raid_disks
;i
++) {
309 if (devices
[j
].events
+1 >=
310 devices
[most_recent
].events
) {
311 devices
[j
].uptodate
= 1;
315 while (force
&& !enough(first_super
.level
, first_super
.raid_disks
, okcnt
)) {
316 /* Choose the newest best drive which is
317 * not up-to-date, update the superblock
320 fprintf(stderr
,"NotImplementedYet\n");
324 /* Almost ready to actually *do* something */
326 if (ioctl(mdfd
, SET_ARRAY_INFO
, NULL
) != 0) {
327 fprintf(stderr
, Name
": SET_ARRAY_INFO failed for %s: %s\n",
328 mddev
, strerror(errno
));
331 /* First, add the raid disks */
332 for (i
=0; i
<first_super
.raid_disks
; i
++) {
334 if (devices
[j
].uptodate
) {
335 mdu_disk_info_t disk
;
336 memset(&disk
, 0, sizeof(disk
));
337 disk
.major
= devices
[j
].major
;
338 disk
.minor
= devices
[j
].minor
;
339 if (ioctl(mdfd
, ADD_NEW_DISK
, &disk
)!=0) {
340 fprintf(stderr
, Name
": failed to add %s to %s: %s\n",
347 fprintf(stderr
, Name
": no uptodate device for slot %d of %s\n",
352 enough(first_super
.level
, first_super
.raid_disks
, okcnt
))) {
353 if (ioctl(mdfd
, RUN_ARRAY
, NULL
)==0)
355 fprintf(stderr
, Name
": failed to RUN_ARRAY %s: %s\n",
356 mddev
, strerror(errno
));