Hello. I was trying to fix issue with partitionable RAID1 devices. According to "lilo -t -v5" it seems to do right thing, but unfortunately I can't test it on real hardware now. Please review it.
A solution is straightforward. The patch scans for mdp major numbers and handles partitions by adding offset to underlying device. Special attention is paid to checking partition table. Since geo_get() substitutes raid drive geometry by underlying partition, geo_query_dev() is used instead.
diff --git a/geometry.c b/geometry.c index 74fbdcb..46d8df3 100644 --- a/geometry.c +++ b/geometry.c @@ -88,6 +88,9 @@ int dm_version_nr = 0; int dm_major_list[16]; int dm_major_nr; +int mdp_major_list[16]; +int mdp_major_nr; + #ifdef LCF_LVM struct lv_bmap { __u32 lv_block; @@ -144,6 +147,9 @@ DT_ENTRY *disktab = NULL; int old_disktab = 0; +static +unsigned char max_partno[512]; + void geo_init(char *name) { FILE *file = NULL; @@ -188,6 +194,7 @@ void geo_init(char *name) } dm_major_nr = 0; + mdp_major_nr = 0; file = fopen("/proc/devices", "r"); if (!file) return; @@ -201,12 +208,23 @@ void geo_init(char *name) 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 (verbose >= 3) { - printf("device-mapper major = %d\n", major); + if (strcmp(major_name, "mdp") == 0) { + if (mdp_major_nr > nelem(mdp_major_list) ) continue; + mdp_major_list[mdp_major_nr] = major; + if (verbose >= 3) { + printf("mdp major = %d\n", major); + } + max_partno[major] = 63; + ++mdp_major_nr; + } else + if (strcmp(major_name, "device-mapper") == 0) { + if (dm_major_nr > nelem(dm_major_list) ) continue; + dm_major_list[dm_major_nr] = major; + if (verbose >= 3) { + printf("device-mapper major = %d\n", major); + } + ++dm_major_nr; } - if (++dm_major_nr > nelem(dm_major_list) ) break; } (void) fclose(file); @@ -242,6 +260,16 @@ int is_dm_major(int major) return 0; } +int is_mdp_major(int major) +{ + int i; + + for(i=0; i<mdp_major_nr; i++) { + if (mdp_major_list[i] == major) return 1; + } + return 0; +} + void do_partition(void) @@ -1080,7 +1108,7 @@ void geo_get(GEOMETRY *geo,int device,int user_device,int all) #endif /* Find underlying device for MD RAID */ - if (MAJOR(device) == MD_MAJOR) { + if (MAJOR(device) == MD_MAJOR || is_mdp_major(MAJOR(device))) { char mdxxx[16]; int md_fd; /* int pass; */ @@ -1089,12 +1117,23 @@ void geo_get(GEOMETRY *geo,int device,int user_device,int all) md_disk_info_t md_disk_info; int raid_limit; - sprintf(mdxxx, DEV_DISK_DIR "/md%d", MINOR(device)); - if ((md_fd=open(mdxxx,O_NOACCESS)) < 0) - { - sprintf(mdxxx, DEV_DIR "/md/%d", MINOR(device)); + if (MAJOR(device) == MD_MAJOR) { + sprintf(mdxxx, DEV_DISK_DIR "/md%d", MINOR(device)); + if ((md_fd=open(mdxxx,O_NOACCESS)) < 0) + { + sprintf(mdxxx, DEV_DIR "/md/%d", MINOR(device)); + if ((md_fd=open(mdxxx,O_NOACCESS)) < 0) + die("Unable to open %s", mdxxx); + } + } else { + int devnum = MINOR(device) >> 6; /* FIXME */ + sprintf(mdxxx, DEV_DISK_DIR "/md_d%d", devnum); if ((md_fd=open(mdxxx,O_NOACCESS)) < 0) - die("Unable to open %s", mdxxx); + { + sprintf(mdxxx, DEV_DIR "/md/d%d", devnum); + if ((md_fd=open(mdxxx,O_NOACCESS)) < 0) + die("Unable to open %s", mdxxx); + } } if (ioctl(md_fd,RAID_VERSION,&md_version_info) < 0) die("Unable to get RAID version on %s", mdxxx); @@ -1114,11 +1153,27 @@ void geo_get(GEOMETRY *geo,int device,int user_device,int all) /* version 22.7 */ #if 1 - is_raid = (device==boot_dev_nr); - md_disk_info.number = raid_index; - if (ioctl(md_fd,GET_DISK_INFO,&md_disk_info) < 0) - die("GET_DISK_INFO: %s", mdxxx); - device = MKDEV(md_disk_info.major, md_disk_info.minor); + if (is_mdp_major(MAJOR(device)) && (MINOR(device) & 63)) { + int start; + geo_query_dev(geo, device, all); + start = geo->start; + geo_get(geo, MKDEV(MAJOR(device), MINOR(device) & ~63), user_device, all); + geo->start += start; + if (verbose >= 3) { + printf("Device 0x%04x: BIOS drive 0x%02x, %d heads, %d cylinders,\n", + device,geo->device,geo->heads,geo->cylinders == -1 ? BIOS_MAX_CYLS : + geo->cylinders); + printf("%15s%d sectors. Partition offset: %d sectors.\n","", + geo->sectors,geo->start); + } + return; + } else { + is_raid = (device==boot_dev_nr); + md_disk_info.number = raid_index; + if (ioctl(md_fd,GET_DISK_INFO,&md_disk_info) < 0) + die("GET_DISK_INFO: %s", mdxxx); + device = MKDEV(md_disk_info.major, md_disk_info.minor); + } #else /* prior to 22.7 */ { diff --git a/geometry.h b/geometry.h index 1bf387f..6c9f482 100644 --- a/geometry.h +++ b/geometry.h @@ -168,6 +168,11 @@ int is_dm_major(int major); device-mapper major devices */ +int is_mdp_major(int major); +/* tell whether the specified major device number is one of the + mdp major devices */ + + #if 0 int geo_devscan(int device); /* called to fill in a disktab with arbitrary BIOS codes */ diff --git a/partition.c b/partition.c index 87fa89a..e93c748 100644 --- a/partition.c +++ b/partition.c @@ -161,7 +161,11 @@ void part_verify(int dev_nr,int type) ) return; if (verbose >= 4) printf("part_verify: dev_nr=%04x, type=%d\n", dev_nr, type); - geo_get(&geo,dev_nr & ~mask,-1,1); + if (is_mdp_major(MAJOR(dev_nr))) { + geo_query_dev(&geo,dev_nr & ~mask,1); + } else { + geo_get(&geo,dev_nr & ~mask,-1,1); + } fd = dev_open(&dev,dev_nr & ~mask,cfg_get_flag(cf_options,"fix-table") && !test ? O_RDWR : O_RDONLY); part = (pe = dev_nr & mask)-1; diff --git a/raid.c b/raid.c index b96f1be..435c743 100644 --- a/raid.c +++ b/raid.c @@ -118,7 +118,7 @@ int raid_setup(void) fflush(stdout); #endif - if ( MAJOR(st.st_rdev) != MAJOR_MD ) { /* not raid */ + if ( MAJOR(st.st_rdev) != MAJOR_MD && !is_mdp_major(MAJOR(st.st_rdev))) { /* not raid */ if (cfg_get_strg(cf_options, RAID_EXTRA_BOOT)) die("Not a RAID install, '" RAID_EXTRA_BOOT "=' not allowed"); return 0;