I've written a patch for Lilo to support installation on BIOS raids created with the Device-Mapper kernel interface. This patch should be very usefull in combination with the dmraid tool, but it breaks the code Cristophe Saout wrote: actually his patch disables dmraid users to install Lilo as they can use very detailed settings in /etc/lilo.conf as a fall-back. This code helps guessing the correct values to install the bootloader succesfully onto the Fake-RAID. This can also be done with some shellscripts parsing the output from dmsetup and fdisk to generate a correct /etc/lilo.conf but it might be more interesting if one piece of code can make all DM users happy. Maybe I'll integrate Saout's idea's later. Cheers, Gerte
diff -Nur lilo-22.6/Makefile lilo-22.6-goed/Makefile --- lilo-22.6/Makefile 2004-09-02 20:06:27.000000000 +0200 +++ lilo-22.6/Makefile 2004-10-25 22:51:47.000000000 +0200 @@ -53,7 +53,7 @@ # XL_SECS=n Support for extra large (non-standard) floppies. CONFIG=-DBDATA -DDSECS=3 -DEVMS -DIGNORECASE -DLVM -DONE_SHOT -DPASS160 \ - -DREISERFS -DREWRITE_TABLE -DSOLO_CHAIN -DVERSION -DVIRTUAL + -DREISERFS -DREWRITE_TABLE -DSOLO_CHAIN -DVERSION -DVIRTUAL -DDEVMAPPER # set the compiler optimization level @@ -95,6 +95,8 @@ LDFLAGS=#-Xlinker -qmagic LIBS= +DEVMAPPER=-ldevmapper + OBJS=lilo.o raid.o map.o geometry.o boot.o device.o common.o bsect.o cfg.o \ partition.o identify.o probe.o shs2.o edit.o temp.o @@ -270,7 +272,11 @@ cp -p dparam.S dparam.s lilo: $(OBJS) +ifneq (,$(findstring DEVMAPPER,$(CONFIG))) + $(CC) -o lilo $(LDFLAGS) $(OBJS) $(LIBS) $(DEVMAPPER) +else $(CC) -o lilo $(LDFLAGS) $(OBJS) $(LIBS) +endif lilo-static: $(OBJS) $(CC) -o lilo-static -static $(LDFLAGS) $(OBJS) $(LIBS) diff -Nur lilo-22.6/geometry.c lilo-22.6-goed/geometry.c --- lilo-22.6/geometry.c 2004-08-25 20:21:08.000000000 +0200 +++ lilo-22.6-goed/geometry.c 2004-10-26 00:31:05.297591680 +0200 @@ -27,6 +27,10 @@ #include <string.h> +#ifdef LCF_DEVMAPPER +#include <libdevmapper.h> +#endif + #include "config.h" #include "lilo.h" #include "common.h" @@ -61,6 +65,17 @@ #endif #endif +#ifdef LCF_DEVMAPPER +typedef struct _dm_target { + struct _dm_target *next; + uint64_t start,length,offset; + int device; +} DM_TARGET; + +int dm_major_list[16]; +int dm_major_nr = 0; +#endif + #ifdef LCF_LVM struct lv_bmap { __u32 lv_block; @@ -115,6 +130,10 @@ { FILE *file; char line[MAX_LINE+1]; +#ifdef LCF_DEVMAPPER + char major_name[32]; + int major; +#endif char *here; DT_ENTRY *entry; int disk_section,items; @@ -123,29 +142,53 @@ if ((file = fopen(name,"r")) == NULL) die("open %s: %s",name,strerror(errno)); } - else if ((file = fopen(DFL_DISKTAB,"r")) == NULL) return; - disk_section = !!disktab; - while (fgets(line,MAX_LINE,file)) { - here = strchr(line,'\n'); - if (here) *here = 0; - here = strchr(line,'#'); - if (here) *here = 0; - if (strspn(line," \t") != strlen(line)) { - entry = alloc_t(DT_ENTRY); - items = sscanf(line,"0x%x 0x%x %d %d %d %d",&entry->device, - &entry->bios,&entry->sectors,&entry->heads,&entry->cylinders, - &entry->start); - if (items == 5) entry->start = -1; - if (items < 5) - die("Invalid line in %s:\n\"%s\"",name ? name : DFL_DISKTAB, - line); - entry->next = disktab; - disktab = entry; - if (disk_section) die("DISKTAB and DISK are mutually exclusive"); - old_disktab = 1; + if (name || (file = fopen(DFL_DISKTAB,"r")) != NULL) { + disk_section = !!disktab; + while (fgets(line,MAX_LINE,file)) { + here = strchr(line,'\n'); + if (here) *here = 0; + here = strchr(line,'#'); + if (here) *here = 0; + if (strspn(line," \t") != strlen(line)) { + entry = alloc_t(DT_ENTRY); + items = sscanf(line,"0x%x 0x%x %d %d %d %d",&entry->device, + &entry->bios,&entry->sectors,&entry->heads,&entry->cylinders, + &entry->start); + if (items == 5) entry->start = -1; + if (items < 5) + die("Invalid line in %s:\n\"%s\"",name ? name : DFL_DISKTAB, + line); + entry->next = disktab; + disktab = entry; + if (disk_section) die("DISKTAB and DISK are mutually exclusive"); + old_disktab = 1; + } + } + (void) fclose(file); + } + +#ifdef LCF_DEVMAPPER + dm_major_nr = 0; + file = fopen("/proc/devices", "r"); + if (!file) return; + + do { + if (!fgets(line, (sizeof line)-1, file)) { + (void) fclose(file); + return; } + line[(sizeof line)-1] = 0; + } while(strncmp(line, "Block", 5) != 0); + + while(fgets(line, (sizeof line)-1, file)) { + if (sscanf(line, "%d %31s\n", &major, major_name) != 2) continue; + if (strcmp(major_name, "device-mapper") != 0) continue; + dm_major_list[dm_major_nr] = major; + if (++dm_major_nr > (sizeof dm_major_list)/(sizeof dm_major_list[0])) break; } + (void) fclose(file); +#endif } @@ -776,7 +819,14 @@ { DT_ENTRY *walk; int inherited,keep_cyls,is_raid=0; - + + int i; + int major_disk,minor_disk; + struct dm_task *dms,*dml; + struct dm_names *names,*begin; + unsigned next=0,found=0; + uint64_t start,number_of_sectors; + if (verbose>=5) printf("geo_get: device %04X, all=%d\n", device, all); #ifdef LCF_LVM /* @@ -878,6 +928,122 @@ close(md_fd); } + + for(i = 0; i < dm_major_nr; i++) + if (MAJOR(device) == dm_major_list[i]) { + if (!(dml = dm_task_create(DM_DEVICE_LIST))) + die("device-mapper: dm_task_create(DM_DEVICE_LIST) failed"); + + if (!dm_task_run(dml)) { + dm_task_destroy(dml); + die("device-mapper: dm_task_run(DM_DEVICE_TABLE) failed"); + } + + if (!(names = dm_task_get_names(dml))) { + dm_task_destroy(dml); + die("device-mapper: dm_task_set_names failed"); + } + + if (!names->dev) { + dm_task_destroy(dml); + die("not any info about mappings in the Device Mapper table => Can't handle device (dev 0x%04x).",device); + } + + /* We have a list with devices, lets look which one is actually the device we want to query */ + begin=names; + do { + char *params; + uint64_t length; + char *target_type = NULL; + + names = (void *) names + next; + if (MAJOR(names->dev) == MAJOR(device) && + MINOR(names->dev) == MINOR(device)) { + found = 1; /* Yes, this is the one */ + if (!(dms = dm_task_create(DM_DEVICE_TABLE))) + die("device-mapper: dm_task_create(DM_DEVICE_TABLE) failed"); + + if (!dm_task_set_name(dms, names->name)) { + dm_task_destroy(dms); + die("device-mapper: dm_task_set_name(\"%s\") failed",names->name); + } + + if (!dm_task_run(dms)) { + dm_task_destroy(dms); + die("device-mapper: dm_task_run(DM_DEVICE_TABLE) failed"); + } + + /* fetch the partition offset in sectors */ + dm_get_next_target(dms, NULL, &start, &length, &target_type, ¶ms); + + /* and look for the RAID mapping to which this partition belongs */ + if(strcmp(target_type, "linear")!=0) { + /* a partition shouldn't be striped or mirrored, this must be the RAID Mapping */ + major_disk=MAJOR(names->dev); + minor_disk=MINOR(names->dev); + } + + else if (!sscanf(params, "%d:%d %"PRIu64, &major_disk, &minor_disk, &start)) { + dm_task_destroy(dms); + die("device-mapper: parse error in linear params (\"%s\")", params); + } + /* we now know this is a partition at $start sectors on the RAID mapping with $major_disk and $minor_disk */ + dm_task_destroy(dms); + } + + if (!(next = names->next) && !found) { + dm_task_destroy(dml); + die("no info about device in Device Mapper table => Can't handle device (dev 0x%04x).", device); + } + } while (!found); + + /* Lets get the number_of_sectors of the RAID mapping */ + names = begin; + next = 0; + found = 0; + do { + char *params; + char *target_type = NULL; + uint64_t dontgive; + + names = (void *) names + next; + if ((MAJOR(names->dev) == major_disk) && + MINOR(names->dev) == minor_disk) { + found = 1; /* Yes, this is the disk */ + if (!(dms = dm_task_create(DM_DEVICE_TABLE))) { + die("device-mapper: dm_task_create(DM_DEVICE_TABLE) failed"); + } + + if (!dm_task_set_name(dms, names->name)) { + dm_task_destroy(dms); + die("device-mapper: dm_task_set_name(\"%s\") failed",names->name); + } + + if (!dm_task_run(dms)) { + dm_task_destroy(dms); + die("device-mapper: dm_task_run(DM_DEVICE_TABLE) failed"); + } + + /* and this way we have found the number_of_sectors */ + dm_get_next_target(dms, NULL, &dontgive, &number_of_sectors, &target_type, ¶ms); + dm_task_destroy(dms); + } + + if(!(next=names->next) && !found) { + dm_task_destroy(dml); + die("Failed to lookup RAID mapping info. Device suddenly disappeared from device table?"); + } + } while (!found); + + dm_task_destroy(dml); + + geo->device = 0x80; /* Maybe you want to override this by a bios= section in the configuration. */ + geo->heads = 255; /* Let's hope we are using lineair or lba32 OR let's hope we guess correctly */ + geo->sectors = 63; /* Let's hope we are using lineair or lba32 OR let's hope we guess correctly */ + geo->cylinders = number_of_sectors/(geo->heads * geo->sectors); + geo->start = start; + } + #if BETA_TEST if (verbose>=5) printf("geo_get(2): device=%04X, all=%d\n", device, all); #endif @@ -896,7 +1062,7 @@ #endif if (inherited) for (walk = disktab; walk; walk = walk->next) - if (walk->device == (device & D_MASK(device))) break; + if ( (walk->device == (device & D_MASK(device))) || (found && MAJOR(walk->device)==MAJOR(device) ) ) break; #if BETA_TEST if (verbose>=5) printf("walk=%08lx\n", (long)walk); #endif @@ -917,7 +1083,7 @@ #if 1 /* add 'all' to conditional below -- JRC 2002-08-20 */ - if (keep_cyls && (all || MAJOR(device)==MAJOR_FD) ) { + if (keep_cyls && (all || MAJOR(device)==MAJOR_FD) && !found ) { #else /* Werner's original conditional */ if (keep_cyls) {