]>
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 device 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 for (; device_list
; device_list
=device_list
->next
) {
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)
142 fprintf(stderr
,Name
": Did not successfully Assemble any devices\n");
147 * Ok, we have an mddev, check it out
149 vers
= md_get_version(mdfd
);
151 fprintf(stderr
, Name
": %s appears not to be an md device.\n");
155 fprintf(stderr
, Name
": Assemble requires driver version 0.90.0 or later.\n"
156 " Upgrade your kernel or try --Build\n");
159 if (get_linux_version() < 2004000)
162 if (ioctl(mdfd
, GET_ARRAY_INFO
, &array
)>=0) {
163 fprintf(stderr
, Name
": device %s already active - cannot assemble it\n",
167 ioctl(mdfd
, STOP_ARRAY
, NULL
); /* just incase it was started but has no content */
170 * We have a valid mddev, check out uuid
172 if (!uuidset
&& scan
) {
173 /* device must be listed with uuid in conf file */
174 mddev_uuid_t device_list
;
175 device_list
= conf_get_uuids(conffile
);
176 while (device_list
&&
177 strcmp(device_list
->devname
, mddev
) != 0)
178 device_list
= device_list
->next
;
181 fprintf(stderr
, Name
": --scan set and no uuid found for %s in config file.\n",
185 /* the uuid is safe until next call to conf_get_uuids */
186 uuid
= device_list
->uuid
;
190 /* Now to start looking at devices.
191 * If no devices were given, but a uuid is available and
192 * --scan was set, then we should scan all devices listed in the
196 if (subdevs
==0 && scan
&& uuidset
)
197 devlist
= conf_get_devs(conffile
);
199 if (subdevs
== 0 && devlist
== NULL
) {
200 fprintf(stderr
, Name
": no devices given for %s\n", mddev
);
203 /* now for each device */
204 first_super
.md_magic
= 0;
205 for (i
=0; i
<MD_SB_DISKS
; i
++)
209 fprintf(stderr
, Name
": looking for devices for %s\n",
212 while (subdevs
|| devlist
) {
223 devname
= devlist
->devname
;
224 devlist
= devlist
->next
;
228 dfd
= open(devname
, O_RDONLY
, 0);
230 if (inargv
|| verbose
)
231 fprintf(stderr
, Name
": cannot open device %s: %s\n",
232 devname
, strerror(errno
));
235 if (fstat(dfd
, &stb
)< 0) {
237 fprintf(stderr
, Name
": fstat failed for %s: %s\n",
238 devname
, strerror(errno
));
242 if ((stb
.st_mode
& S_IFMT
) != S_IFBLK
) {
243 fprintf(stderr
, Name
": %d is not a block device.\n",
248 if (load_super(dfd
, &super
)) {
249 if (inargv
|| verbose
)
250 fprintf( stderr
, Name
": no RAID superblock on %s\n",
256 uuid_from_super(this_uuid
, &super
);
257 if (uuidset
&& !same_uuid(this_uuid
, uuid
)) {
258 if (inargv
|| verbose
)
259 fprintf(stderr
, Name
": %s has wrong uuid.\n",
263 if (compare_super(&first_super
, &super
)) {
264 if (inargv
|| verbose
)
265 fprintf(stderr
, Name
": superblock on %s doesn't match\n",
270 uuid_from_super(this_uuid
, &first_super
);
271 if (!same_uuid(this_uuid
, uuid
)) {
272 if (inargv
|| verbose
)
273 fprintf(stderr
, Name
": %s has wrong uuid.\n",
278 uuid_from_super(uuid
, &first_super
);
282 /* Ok, this one is at least worth considering */
283 if (devcnt
>= MD_SB_DISKS
) {
284 fprintf(stderr
, Name
": ouch - too many devices appear to be in this array. Ignoring %s\n",
288 devices
[devcnt
].devname
= devname
;
289 devices
[devcnt
].major
= MAJOR(stb
.st_rdev
);
290 devices
[devcnt
].minor
= MINOR(stb
.st_rdev
);
291 devices
[devcnt
].events
= md_event(&super
);
292 devices
[devcnt
].utime
= super
.utime
;
293 devices
[devcnt
].uptodate
= 0;
294 if (most_recent
< devcnt
) {
295 if (devices
[devcnt
].events
296 > devices
[most_recent
].events
)
297 most_recent
= devcnt
;
299 i
= super
.this_disk
.raid_disk
;
301 || devices
[best
[i
]].events
< devices
[devcnt
].events
) {
308 fprintf(stderr
, Name
": no devices found for %s\n",
312 /* now we have some devices that might be suitable.
316 for (i
=0; i
< first_super
.raid_disks
;i
++) {
319 if (devices
[j
].events
+1 >=
320 devices
[most_recent
].events
) {
321 devices
[j
].uptodate
= 1;
325 while (force
&& !enough(first_super
.level
, first_super
.raid_disks
, okcnt
)) {
326 /* Choose the newest best drive which is
327 * not up-to-date, update the superblock
330 fprintf(stderr
,"NotImplementedYet\n");
334 /* Almost ready to actually *do* something */
336 if (ioctl(mdfd
, SET_ARRAY_INFO
, NULL
) != 0) {
337 fprintf(stderr
, Name
": SET_ARRAY_INFO failed for %s: %s\n",
338 mddev
, strerror(errno
));
341 /* First, add the raid disks */
342 for (i
=0; i
<first_super
.raid_disks
; i
++) {
344 if (devices
[j
].uptodate
) {
345 mdu_disk_info_t disk
;
346 memset(&disk
, 0, sizeof(disk
));
347 disk
.major
= devices
[j
].major
;
348 disk
.minor
= devices
[j
].minor
;
349 if (ioctl(mdfd
, ADD_NEW_DISK
, &disk
)!=0) {
350 fprintf(stderr
, Name
": failed to add %s to %s: %s\n",
357 fprintf(stderr
, Name
": no uptodate device for slot %d of %s\n",
362 enough(first_super
.level
, first_super
.raid_disks
, okcnt
))) {
363 if (ioctl(mdfd
, RUN_ARRAY
, NULL
)==0) {
364 fprintf(stderr
, Name
": %s has been started with %d drives\n",
368 fprintf(stderr
, Name
": failed to RUN_ARRAY %s: %s\n",
369 mddev
, strerror(errno
));
373 fprintf(stderr
, Name
": %s assembled from %d drives, but not started.\n",
377 fprintf(stderr
, Name
": %s assembled from %d drives - not enough to start it.\n",
381 /* It maybe just a case of calling START_ARRAY, but it may not..
382 * We need to pick a working device, read it's super block, and make
383 * sure all the device numbers and the minor number are right.
384 * Then we might need to re-write the super block.
385 * THEN we call START_ARRAY
386 * If the md_minor is wrong, wejust give up for now. The alternate is to
387 * re-write ALL super blocks.
389 int chosen_drive
= -1;
392 for (i
=0; i
<first_super
.nr_disks
; i
++) {
393 if (!devices
[i
].uptodate
)
395 if (chosen_drive
== -1) {
398 if (open(devices
[i
].devname
, O_RDONLY
)>= 0) {
399 fprintf(stderr
, Name
": Cannot open %s: %s\n",
400 devices
[i
].devname
, strerror(errno
));
403 if (load_super(fd
, &super
)) {
405 fprintf(stderr
, Name
": RAID superblock has disappeared from %s\n",
411 if (devices
[i
].major
!= super
.disks
[i
].major
||
412 devices
[i
].minor
!= super
.disks
[i
].minor
) {
414 super
.disks
[i
].major
= devices
[i
].major
;
415 super
.disks
[i
].minor
= devices
[i
].minor
;
420 super
.sb_csum
= calc_sb_csum(super
);
421 fd
= open(devices
[chosen_drive
].devname
, O_RDWR
);
423 fprintf(stderr
, Name
": Could open %s for write - cannot Assemble array.\n",
424 devices
[chosen_drive
].devname
);
427 if (store_super(fd
, &super
)) {
429 fprintf(stderr
, Name
": Could not re-write superblock on %s\n",
430 devices
[chosen_drive
].devname
);
435 dev
= MKDEV(devices
[chosen_drive
].major
,
436 devices
[chosen_drive
].minor
);
437 if (ioctl(mdfd
, START_ARRAY
, dev
)) {
438 fprintf(stderr
, Name
": Cannot start array: %s\n",