1 /* raid.c - The RAID-1 hooks for LILO
3 * Copyright 2001-2005 John Coffman
4 * Copyright 2009-2011 Joachim Wiedorn
7 * Licensed under the terms contained in the file 'COPYING'
8 * in the source directory.
21 /*#include <asm/page.h>*/
32 #include "partition.h"
36 static DT_ENTRY *md_disk;
37 static DT_ENTRY *disk;
38 static unsigned int raid_base, raid_offset[MAX_RAID];
39 static char *raid_mbr[MAX_RAID];
40 static int raid_device[MAX_RAID+1];
41 static int raid_bios[MAX_RAID+1];
43 enum {MD_NULL=0, MD_PARALLEL, MD_MIXED, MD_SKEWED};
44 int do_md_install, ndisk, md_bios;
45 static char *raid_list[MAX_RAID];
46 static int list_index[MAX_RAID];
47 static int nlist, faulty;
51 #define IS_COVERED 0x1000
52 #define TO_BE_COVERED 0x2000
53 #define COVERED (IS_COVERED|TO_BE_COVERED)
55 static int is_primary(int device)
59 mask = has_partitions(device);
60 if (!mask) die("is_primary: Not a valid device 0x%04X", device);
61 mask = device & ~mask;
62 return (mask && mask<=PART_MAX);
67 static int master(int device)
71 if (MAJOR(device) == MAJOR_FD) return device;
73 mask = has_partitions(device);
74 if (!mask) die("master: Not a valid device 0x%04X", device);
79 static int is_accessible(int device)
83 mask = has_partitions(device);
84 if (!mask) die("is_accessible: Not a valid device 0x%04X", device);
85 mask = device & ~mask;
86 return (mask<=PART_MAX);
95 struct md_version md_version_info;
96 md_disk_info_t md_disk_info;
97 md_array_info_t md_array_info;
101 int raid_offset_set, all_pri_eq, pri_index;
105 if (!(boot=cfg_get_strg(cf_options,"boot"))) {
108 warn("RAID1 install implied by omitted 'boot='");
111 if (stat(boot,&st)<0) die("raid_setup: stat(\"%s\")", boot);
114 printf("raid_setup: dev=%04X rdev=%04X\n",
115 (int)st.st_dev, (int)st.st_rdev);
121 if ( MAJOR(st.st_rdev) != MAJOR_MD ) { /* not raid */
122 if (cfg_get_strg(cf_options, RAID_EXTRA_BOOT))
123 die("Not a RAID install, '" RAID_EXTRA_BOOT "=' not allowed");
126 else { /* It is a RAID installation */
128 if (!nowarn && boot[0]=='/' && !boot[1])
129 warn("RAID1 install implied by 'boot=/'\n");
131 /* scan the devices in /proc/partitions */
135 if ((md_fd=dev_open(&dev, st.st_rdev, O_NOACCESS) ) < 0)
136 die("Unable to open %s",boot);
137 boot = stralloc(dev.name);
138 if (fstat(md_fd,&st) < 0)
139 die("Unable to stat %s",boot);
140 if (!S_ISBLK(st.st_mode))
141 die("%s is not a block device",boot);
143 boot_dev_nr = st.st_rdev; /* set this very early */
145 if (ioctl(md_fd,RAID_VERSION,&md_version_info) < 0)
146 die("Unable to get RAID version on %s", boot);
147 if (verbose >= 4) printf("RAID_VERSION = %d.%d\n",
148 (int)md_version_info.major,
149 (int)md_version_info.minor);
150 if (md_version_info.major > 0)
151 die("Raid major versions > 0 are not supported");
152 if (md_version_info.minor < 90)
153 die("Raid versions < 0.90 are not supported");
155 if (ioctl(md_fd,GET_ARRAY_INFO,&md_array_info) < 0)
156 die("Unable to get RAID info on %s",boot);
157 if (verbose >= 4) printf("GET_ARRAY_INFO version = %d.%d\n",
158 (int)md_array_info.major_version,
159 (int)md_array_info.minor_version);
160 if (md_version_info.major != 0 || md_version_info.minor != 90 ||
161 ((md_array_info.major_version != 0 ||
162 md_array_info.minor_version != 90) &&
163 (md_array_info.major_version != 1 ||
164 md_array_info.minor_version != 0))
166 die("Incompatible Raid version information on %s (RV=%d.%d GAI=%d.%d)",
168 (int)md_version_info.major,
169 (int)md_version_info.minor,
170 (int)md_array_info.major_version,
171 (int)md_array_info.minor_version);
173 if (md_array_info.level != 1)
174 die("Only RAID1 devices are supported as boot devices");
175 if (!linear && !lba32) {
178 warn("RAID install requires LBA32 or LINEAR;"
179 " LBA32 assumed.\n");
181 extrap = cfg_get_strg(cf_options, RAID_EXTRA_BOOT);
182 extra = !extrap ? X_AUTO :
183 !strcasecmp(extrap,"none") ? X_NONE :
184 !strcasecmp(extrap,"auto") ? X_AUTO :
185 !strcasecmp(extrap,"mbr-only") ? X_MBR_ONLY :
186 !strcasecmp(extrap,"mbr") ? X_MBR :
189 do_md_install = MD_PARALLEL;
192 raid_offset_set = pri_index = pri_offset = 0;
193 raid_flags = FLAG_RAID;
194 md_bios = 0xFF; /* we want to find the minimum */
195 ndisk = 0; /* count the number of disks on-line */
199 device = MKDEV(MD_MAJOR, md_array_info.md_minor);
201 /* search the disk table for a definition */
203 while (md_disk && md_disk->device != device)
204 md_disk = md_disk->next;
207 md_disk = alloc_t(DT_ENTRY);
208 md_disk->device = MKDEV(MD_MAJOR, md_array_info.md_minor);
209 md_disk->bios = -1; /* use the default */
210 md_disk->next = disktab;
215 printf("RAID info: nr=%d, raid=%d, active=%d, working=%d, failed=%d, spare=%d\n",
216 md_array_info.nr_disks,
217 md_array_info.raid_disks,
218 md_array_info.active_disks,
219 md_array_info.working_disks,
220 md_array_info.failed_disks,
221 md_array_info.spare_disks );
224 /* scan through all the RAID devices */
225 raid_limit = md_array_info.raid_disks;
226 if (md_array_info.active_disks < md_array_info.raid_disks) {
227 if (!force_raid) die("Not all RAID-1 disks are active; use '-H' to install to active disks only");
229 warn("Partial RAID-1 install on active disks only; booting is not failsafe\n");
230 raid_limit = md_array_info.raid_disks;
234 for (pass=0; pass < raid_limit; pass++) {
237 char new_name[MAX_TOKEN+1];
240 md_disk_info.number = pass;
241 if (ioctl(md_fd,GET_DISK_INFO,&md_disk_info) < 0)
243 die("raid: GET_DISK_INFO: %s, pass=%d", strerror(errno), pass);
246 printf("raid: GET_DISK_INFO: %s, pass=%d\n", strerror(errno), pass);
250 device = MKDEV(md_disk_info.major, md_disk_info.minor);
251 if(verbose>=3) printf("md: RAIDset device %d = 0x%04X\n", pass, device);
252 if (device == 0) { /* empty slot left over from recovery process */
254 warn("Faulty disk in RAID-1 array; boot with caution!!");
257 disk_fd = dev_open(&dev,device,O_NOACCESS);
258 if (md_disk_info.state & (1 << MD_DISK_FAULTY)) {
259 printf("disk %s marked as faulty, skipping\n",dev.name);
263 geo_get(&geo, device, -1, 1);
264 disk = alloc_t(DT_ENTRY);
266 printf("RAID scan: geo_get: returns geo->device = 0x%02X"
267 " for device %04X\n", geo.device, device);
269 disk->bios = geo.device; /* will be overwritten */
270 disk->device = device;
271 /* used to mask above with 0xFFF0; forces MBR; sloppy, mask may be: 0xFFF8 */
272 disk->sectors = geo.sectors;
273 disk->heads = geo.heads;
274 disk->cylinders = geo.cylinders;
275 disk->start = geo.start;
277 raid_base = geo.start;
280 raid_offset[ndisk] = geo.start - raid_base;
281 raid_device[ndisk] = device;
283 if (raid_offset[ndisk]) {
284 do_md_install = MD_SKEWED; /* flag non-zero raid_offset */
287 if (all_pri_eq && is_primary(device)) {
288 if (raid_offset_set) {
289 all_pri_eq &= (pri_offset == raid_offset[ndisk]);
291 pri_offset = raid_offset[ndisk];
298 if (geo.device < md_bios) { /* OLD: use smallest device code */
300 if (ndisk==0) { /* NEW: use the device code of the first device */
302 md_bios = geo.device; /* find smallest device code, period */
303 lowest = ndisk; /* record where */
305 raid_bios[ndisk] = geo.device; /* record device code */
307 disk->next = disktab;
310 if (verbose >= 3 && do_md_install) {
311 printf("disk->start = %d\t\traid_offset = %d (%08X)\n",
312 disk->start, (int)raid_offset[ndisk], (int)raid_offset[ndisk]);
315 /* derive the MBR name, which may be needed later */
316 strncpy(new_name,dev.name,MAX_TOKEN);
317 new_name[MAX_TOKEN] = '\0';
318 np = boot_mbr(dev.name, 0);
319 if (!np) np = stralloc(new_name);
320 raid_mbr[ndisk] = np;
322 if (ndisk==0) { /* use the first disk geometry */
323 md_disk->sectors = geo.sectors;
324 md_disk->heads = geo.heads;
325 md_disk->cylinders = geo.cylinders;
326 md_disk->start = geo.start;
329 ndisk++; /* count the disk */
330 } /* for (pass=... */
333 raid_bios[ndisk] = 0; /* mark the end */
334 raid_device[ndisk] = 0;
336 all_pri_eq &= raid_offset_set;
337 if (all_pri_eq && do_md_install == MD_SKEWED) {
338 do_md_install = MD_MIXED;
340 else pri_index = lowest;
343 /* check that all devices have an accessible block for writeback info */
344 for (pass=0; pass < ndisk; pass++) {
345 if (extra == X_MBR_ONLY || extra == X_MBR)
346 raid_bios[pass] |= TO_BE_COVERED;
348 if (extra == X_AUTO /*&& raid_bios[pass] != 0x80*/) {
349 if (do_md_install == MD_SKEWED) {
350 raid_bios[pass] |= TO_BE_COVERED;
353 if (do_md_install == MD_MIXED) {
354 if (is_primary(raid_device[pass])) raid_bios[pass] |= IS_COVERED;
356 raid_bios[pass] |= TO_BE_COVERED;
362 if ((do_md_install == MD_PARALLEL && is_accessible(raid_device[pass]))
363 || (do_md_install == MD_MIXED && pri_offset == raid_offset[pass]
364 && is_primary(raid_device[pass]))
366 raid_bios[pass] |= IS_COVERED;
373 scan = next = extrap;
374 while (next && *next) {
376 while (isspace(*scan)) scan++; /* deblank the line */
377 next = strchr(scan, ','); /* find the separator */
378 if (next) *next++ = 0; /* NUL terminate scan */
380 if ((md_fd=open(scan,O_NOACCESS)) < 0)
381 die("Unable to open %s", scan);
382 if (fstat(md_fd,&st) < 0)
383 die("Unable to stat %s",scan);
384 if (!S_ISBLK(st.st_mode))
385 die("%s (%04X) not a block device", scan, (int)st.st_rdev);
386 if (verbose>=4) printf("RAID list: %s is device 0x%04X\n",
387 scan, (int)st.st_rdev);
390 list_index[nlist] = ndisk; /* raid_bios==0 here */
391 for (pass=0; pass < ndisk; pass++) {
392 if (master(st.st_rdev) == master(raid_device[pass])) {
393 list_index[nlist] = pass;
394 if (st.st_rdev == raid_device[pass])
395 die("Cannot write to a partition within a RAID set: %s", scan);
396 else if (is_accessible(st.st_rdev))
397 raid_bios[pass] |= IS_COVERED;
401 if (list_index[nlist] == ndisk) {
402 #ifdef FLAG_RAID_NOWRITE
403 raid_flags |= FLAG_RAID_NOWRITE; /* disk is outside RAID set */
405 if (!nowarn) printf("Warning: device outside of RAID set %s 0x%04X\n",
406 scan, (int)st.st_rdev);
408 raid_list[nlist++] = stralloc(scan);
414 /* if the install is to MBRs, then change the boot= name */
415 if (extra == X_MBR_ONLY) {
417 if (cfg_get_strg(cf_options,"boot")) cfg_unset(cf_options,"boot");
418 cfg_set(cf_options, "boot", (boot=raid_mbr[0]), NULL);
421 else { /* if skewed install, disable mdX boot records as
422 source of writeback info */
423 if (do_md_install == MD_SKEWED) raid_flags |= FLAG_RAID_DEFEAT
424 #ifdef FLAG_RAID_NOWRITE
425 | (extra == X_NONE ? FLAG_RAID_NOWRITE : 0)
431 for (pass=0; pass < ndisk; pass++) {
432 mask &= !!(raid_bios[pass] & COVERED);
434 #ifdef FLAG_RAID_NOWRITE
436 raid_flags |= FLAG_RAID_NOWRITE;
439 if (raid_flags & FLAG_RAID_NOWRITE) {
440 warn("FLAG_RAID_NOWRITE has been set.");
444 /* if the disk= bios= did not specify the bios, then this is the default */
445 if (md_disk->bios < 0) {
446 md_disk->bios = md_bios;
448 md_bios = md_disk->bios;
449 if (md_disk->bios < 0x80 || md_disk->bios > DEV_MASK)
450 die("Unusual RAID bios device code: 0x%02X", md_disk->bios);
452 /* Assigning all disks the same bios code is OBSOLETE in 22.5.6 */
454 for (pass=0; pass < ndisk; pass++) {
455 disk->bios = md_disk->bios; /* all disks in the array are */
456 disk = disk->next; /* assigned the same bios code */
461 "Using BIOS device code 0x%02X for RAID boot blocks\n",
466 if ( mask && ( extra == X_NONE ||
467 (extra == X_AUTO && autocount == 0) ) ) {
468 if (bios_passes_dl > DL_BAD) bios_passes_dl = DL_GOOD;
472 if (bios_passes_dl==DL_GOOD && !(extra == X_MBR_ONLY || extra == X_MBR))
473 warn("Boot sector on %s will depend upon the BIOS device code\n"
474 " passed in the DL register being accurate. Install Master Boot Records\n"
475 " with the 'lilo -M' command, and activate the RAID1 partitions with the\n"
476 " 'lilo -A' command.",
479 return raid_offset[pri_index];
480 } /* IF (test for a raid installation */
481 } /* int raid_setup(void) */
485 void raid_final(void)
489 int mask = FLAG_SAVE;
492 if (bios_passes_dl < DL_GOOD) mask &= ~FLAG_MAP_ON_BOOT;
494 if (test) /* do nothing */;
495 else if ((cp=cfg_get_strg(cf_options,"force-backup"))) force=1;
496 else cp=cfg_get_strg(cf_options,"backup");
499 printf("do_md_install: %s\n", do_md_install == MD_PARALLEL ? "MD_PARALLEL" :
500 do_md_install == MD_MIXED ? "MD_MIXED" :
501 do_md_install == MD_SKEWED ? "MD_SKEWED" : "unknown");
502 for (pass=0; pass<ndisk; pass++)
503 printf(" offset %08X %s\n", raid_offset[pass], raid_mbr[pass]);
506 if (extra == X_MBR_ONLY) {
508 while (pass < ndisk) {
510 # error "Bios Translation algorithms require '-DUNIFY' in Makefile"
512 if (pass==0 && test) {
514 if (passw) printf("The password crc file has *NOT* been updated.\n");
515 printf("The map file has *NOT* been altered.\n");
519 bsect_raid_update(raid_mbr[pass], raid_offset[pass],
520 cp, force, pass ? pass : -1, mask );
523 printf("The Master boot "
524 "record of %s has%s been updated.\n",
526 test ? " *NOT*" : "" );
530 else { /* extra != X_MBR_ONLY */
532 #ifdef FLAG_RAID_DEFEAT
533 raid_flags &= ~FLAG_RAID_DEFEAT; /* change won't affect /dev/mdX */
538 if (passw) printf("The password crc file has *NOT* been updated.\n");
539 printf("The map file has *NOT* been updated.\n");
542 /* write out the /dev/mdX boot records */
543 bsect_raid_update(boot, 0L, cp, force, 0, FLAG_SAVE);
545 printf("The boot record of %s has%s been updated.\n",
547 test ? " *NOT*" : "");
550 if (extra == X_NONE ||
551 (extra == X_AUTO && autocount == 0) ) return;
554 for (pass = 0; pass < nlist; pass++) {
557 if (raid_bios[list_index[pass]] & 0xFF) {
558 index = list_index[pass]; /* within RAID set */
560 else { /* not in the RAID set */
561 #ifdef FLAG_RAID_DEFEAT
562 raid_flags |= FLAG_RAID_DEFEAT; /* make outsider invisible */
567 if (verbose>=3) printf("Specified partition: %s raid offset = %08X\n",
568 raid_list[pass], raid_offset[index]);
571 bsect_raid_update(raid_list[pass], raid_offset[index], cp, force, 1, mask);
573 printf("The boot record of %s has%s been updated.\n",
574 raid_list[pass], (test ? " *NOT*" : ""));
576 #ifdef FLAG_RAID_DEFEAT
577 raid_flags &= ~FLAG_RAID_DEFEAT; /* restore DEFEAT flag to 0 */
580 else { /* extra = X_AUTO or X_MBR*/
581 for (pass = 0; pass < ndisk; pass++) {
582 if (!(raid_bios[pass] & IS_COVERED)) {
583 if ((raid_bios[pass] & 0xFF) != 0x80 || extra == X_MBR) {
585 bsect_raid_update(raid_mbr[pass], raid_offset[pass],
587 printf("The Master boot record of %s has%s been updated.\n",
588 raid_mbr[pass], (test ? " *NOT*" : ""));
590 warn("%splicit AUTO does not allow updating the Master Boot Record\n"
591 " of '%s' on BIOS device code 0x80, the System Master Boot Record.\n"
592 " You must explicitly specify updating of this boot sector with\n"
593 " '-x %s' or 'raid-extra-boot = %s' in the\n"
594 " configuration file.",
595 cfg_get_strg(cf_options, RAID_EXTRA_BOOT) ? "Ex" : "Im",
607 #ifdef FLAG_RAID_NOWRITE
608 if (raid_flags & FLAG_RAID_NOWRITE) {
609 warn("FLAG_RAID_NOWRITE has been set.%s", verbose>=1 ?
610 "\n The boot loader will be unable to update the stored command line;\n"
611 " 'lock' and 'fallback' are not operable; the 'lilo -R' boot command\n"
612 " line will be locked." : "" );
618 /* form the mask of the raid bios codes and the list of offsets */
619 /* this information goes into the MENUTABLE passed to the loader */
620 int raid_mask(int *offsets)
624 int offset[MAX_BIOS_DEVICES];
626 if (ndisk > MAX_RAID_DEVICES)
627 die("More than %d active RAID1 disks", MAX_RAID_DEVICES);
629 memset(offset, 0, sizeof(offset));
630 for (i=0; i<ndisk; i++) {
631 offset[j = raid_bios[i] & (DEV_MASK & 0x7F) ] = raid_offset[i];
634 for (i=0; i<nelem(offset); i++) {
635 if ( (mask>>i) & 1 ) *offsets++ = offset[i];
636 if (do_md_install && verbose>=3) printf("RAID offset entry %d 0x%08X\n", offset[i], offset[i]);
639 if (verbose>=2) printf("RAID device mask 0x%04X\n", mask);