Hi, there is AFAIK no solution for safe booting from RAID1 devices such as in the typical case of two harddrives in a PC (Primary Master+Primary Slave or Primary Master+Secondary Master).
Created a BIOS wrapper to automatically detect disk failure and swap 0x80<->0x81 reading so it applies to stage1/stage2/kernel/initrd/whatever loading. It was tested using QEMU patches simulating various disk failures. http://cvs.jankratochvil.net/viewcvs/biosautoraid/biosautoraid.tar.gz?tarball=1 http://cvs.jankratochvil.net/viewcvs/biosautoraid/README?rev=HEAD WHY: The loading of stage2 can be fixed only for 0x80 or 0x81 but there is never a foolproof choice. Sometimes the primary drive 0x80 dies while becoming unreadable, in some other cases it dies while disappearing from POST so 0x81 becomes 0x80. If you set 0x80 or 0x81 there are always some disk crash cases where the booting will fail. Fallback to the second drive during failure of the kernel load is AFAIK not possible with LILO and it is even a bit complicated to configure with GRUB. REQUIREMENTS: This solution is fully independent of the used loader. Either LILO or GRUB can be used, both have been tested. Just the sectors required for booting need to be exactly at the same sectors of both disks. This is satisfied with standard Linux-RAID devices /dev/md* if both disks are partitioned the same way. DISADVANTAGE: Currently it does not support LBA32 handling so you must install the boot stuff under the first 8GB. I have some draft LBA32 support done but it never got debugged/finished as there are no business needs for it. The whole swapping wrapper no longer fits into 1 sector so it needs its own stage2 loader (also with automatic drives swapping) etc. TESTING/DEBUGGING: Used the attached "block-limit.diff" QEMU patch, it is user unfriendly to use. SPONSORSHIP: Development paid by the courtesy of JK Labs s.r.o. Some integration into GRUB/LILO would be wised? Do you find it useful? Regards, Lace
Index: block-qcow.c =================================================================== RCS file: /sources/qemu/qemu/block-qcow.c,v retrieving revision 1.6 diff -u -p -r1.6 block-qcow.c --- block-qcow.c 18 Dec 2005 18:28:15 -0000 1.6 +++ block-qcow.c 27 Feb 2006 21:07:09 -0000 @@ -458,6 +458,15 @@ static int qcow_read(BlockDriverState *b int ret, index_in_cluster, n; uint64_t cluster_offset; + static BlockDriverState *bs_first=NULL; + if (!bs_first) + bs_first=bs; + if (bs==bs_first && sector_num) { +fprintf(stderr,"%p:%lld+%d: %s\n",bs,(long long)sector_num,nb_sectors,bs->filename); +puts("fail"); + return -1; + } + while (nb_sectors > 0) { cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0); index_in_cluster = sector_num & (s->cluster_sectors - 1); Index: block.c =================================================================== RCS file: /sources/qemu/qemu/block.c,v retrieving revision 1.25 diff -u -p -r1.25 block.c --- block.c 18 Dec 2005 18:28:15 -0000 1.25 +++ block.c 27 Feb 2006 21:07:10 -0000 @@ -709,6 +709,25 @@ static int raw_read(BlockDriverState *bs BDRVRawState *s = bs->opaque; int ret; + static BlockDriverState *bs_first=NULL; + if (!bs_first) + bs_first=bs; + if (!strcmp(bs->filename,"/tmp/sda-head.bin") && bs==bs_first && sector_num) { +fprintf(stderr,"%p:%lld+%d: %s\n",bs,(long long)sector_num,nb_sectors,bs->filename); +puts("fail"); + return -1; + } +#if 0 + fprintf(stderr,"%p:%lld+%d: %s\n",bs,(long long)sector_num,nb_sectors,bs->filename); + if (!strcmp(bs->filename,"/tmp/sda-head.bin") && bs==bs_first && ((sector_num/63)&1)) { +puts("fail"); + return -1; + } + if (!strcmp(bs->filename,"/tmp/sda-head.bin") && bs!=bs_first && !((sector_num/63)&1)) { +puts("fail"); + return -1; + } +#endif lseek(s->fd, sector_num * 512, SEEK_SET); ret = read(s->fd, buf, nb_sectors * 512); if (ret != nb_sectors * 512)
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel