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;

Reply via email to