Module Name:    src
Committed By:   martin
Date:           Wed Oct 18 11:44:22 UTC 2023

Modified Files:
        src/sys/arch/i386/stand/lib [netbsd-10]: biosdisk.c
        src/sys/dev/raidframe [netbsd-10]: rf_netbsdkintf.c
        src/sys/rump/librump/rumpkern [netbsd-10]: emul.c

Log Message:
Pull up following revision(s) (requested by manu in ticket #418):

        sys/arch/i386/stand/lib/biosdisk.c: revision 1.59
        sys/rump/librump/rumpkern/emul.c: revision 1.200
        sys/arch/i386/stand/lib/biosdisk.c: revision 1.60
        sys/dev/raidframe/rf_netbsdkintf.c: revision 1.416

Align the behavior of different boot methods in RAIDframe

We enforce the documented and paritally implemented behavior when
looking for the kernel in RAID 1 sets without a partition name given.

We search for:
- A GPT partition with bootme attribute set
- A FFS or LFS patititon
- The first partition

Fix root search in RAID 1 sets

We use the wedge information given by bootstrap, where the kernel was
found. This requires src/sys/arch/i386/stand/i386/lib/biosdisk.c 1.59
to work in all cases.

Fix build with -DNO_GPT


To generate a diff of this commit:
cvs rdiff -u -r1.58 -r1.58.4.1 src/sys/arch/i386/stand/lib/biosdisk.c
cvs rdiff -u -r1.410.4.2 -r1.410.4.3 src/sys/dev/raidframe/rf_netbsdkintf.c
cvs rdiff -u -r1.196 -r1.196.20.1 src/sys/rump/librump/rumpkern/emul.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/i386/stand/lib/biosdisk.c
diff -u src/sys/arch/i386/stand/lib/biosdisk.c:1.58 src/sys/arch/i386/stand/lib/biosdisk.c:1.58.4.1
--- src/sys/arch/i386/stand/lib/biosdisk.c:1.58	Tue May  3 10:09:40 2022
+++ src/sys/arch/i386/stand/lib/biosdisk.c	Wed Oct 18 11:44:22 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: biosdisk.c,v 1.58 2022/05/03 10:09:40 jmcneill Exp $	*/
+/*	$NetBSD: biosdisk.c,v 1.58.4.1 2023/10/18 11:44:22 martin Exp $	*/
 
 /*
  * Copyright (c) 1996, 1998
@@ -105,6 +105,7 @@
 struct biosdisk {
 	struct biosdisk_ll ll;
 	daddr_t         boff;
+	daddr_t         size;
 	char            buf[BIOSDISK_BUFSIZE];
 #if !defined(NO_DISKLABEL) || !defined(NO_GPT)
 	struct biosdisk_partition part[BIOSDISKNPART];
@@ -327,7 +328,6 @@ guid_is_equal(const struct uuid *a, cons
 	return (memcmp(a, b, sizeof(*a)) == 0 ? true : false);
 }
 
-#ifndef NO_GPT
 static void
 part_name_utf8(const uint16_t *utf16_src, size_t utf16_srclen,
 	       char *utf8_dst, size_t utf8_dstlen)
@@ -350,7 +350,6 @@ part_name_utf8(const uint16_t *utf16_src
 
 	return;
 }
-#endif
 
 static int
 check_gpt(struct biosdisk *d, daddr_t rf_offset, daddr_t sector)
@@ -666,6 +665,7 @@ read_label(struct biosdisk *d, daddr_t o
 	dflt_lbl.d_npartitions = 8;
 
 	d->boff = 0;
+	d->size = 0;
 
 	if (d->ll.type != BIOSDISK_TYPE_HD)
 		/* No label on floppy and CD */
@@ -1208,7 +1208,7 @@ add_biosdisk_bootinfo(void)
 #endif
 
 #ifndef NO_GPT
-static daddr_t
+static void
 raidframe_part_offset(struct biosdisk *d, int part)
 {
 	struct biosdisk raidframe;
@@ -1221,8 +1221,10 @@ raidframe_part_offset(struct biosdisk *d
 
 	rf_offset = d->part[part].offset + RF_PROTECTED_SECTORS;
 	rf_size = d->part[part].size;
-	if (read_gpt(&raidframe, rf_offset, rf_size) != 0)
-		return RF_PROTECTED_SECTORS;
+	if (read_gpt(&raidframe, rf_offset, rf_size) != 0) {
+		d->boff += RF_PROTECTED_SECTORS;
+		return;
+	}
 
 	candidate = 0;
 	for (i = 0; i < BIOSDISKNPART; i++) {
@@ -1231,12 +1233,20 @@ raidframe_part_offset(struct biosdisk *d
 		if (raidframe.part[i].fstype == FS_UNUSED)
 			continue;
 #ifndef NO_GPT
-		if (raidframe.part[i].attr & GPT_ENT_ATTR_BOOTME)
+		if (raidframe.part[i].attr & GPT_ENT_ATTR_BOOTME) {
 			candidate = i;
+			break;
+		}
 #endif
+		if (raidframe.part[i].fstype == FS_BSDFFS ||
+		    raidframe.part[i].fstype == FS_BSDLFS) {
+			if (candidate == 0)
+				candidate = i;
+		}
 	}
 
-	return RF_PROTECTED_SECTORS + raidframe.part[candidate].offset;
+	d->boff += RF_PROTECTED_SECTORS + raidframe.part[candidate].offset;
+	d->size = raidframe.part[candidate].size;
 }
 #endif
 
@@ -1285,17 +1295,18 @@ biosdisk_open(struct open_file *f, ...)
 	}
 
 	d->boff = d->part[partition].offset;
+	d->size = d->part[partition].size;
 
 	if (d->part[partition].fstype == FS_RAID)
 #ifndef NO_GPT
-		d->boff += raidframe_part_offset(d, partition);
+		raidframe_part_offset(d, partition);
 #else
 		d->boff += RF_PROTECTED_SECTORS;
 #endif
 
 #ifdef _STANDALONE
-	bi_wedge.startblk = d->part[partition].offset;
-	bi_wedge.nblks = d->part[partition].size;
+	bi_wedge.startblk = d->boff;
+	bi_wedge.nblks = d->size;
 #endif
 
 nolabel:
@@ -1389,6 +1400,8 @@ next_disk:
 
 #ifndef NO_RAIDFRAME
 	for (i = 0; i < raidframe_count; i++) {
+		int first_bootme = -1;
+		int first_ffs = -1;
 		int candidate = -1;
 
 		if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) {
@@ -1402,12 +1415,20 @@ next_disk:
 			goto next_raidframe;
 
 		for (part = 0; part < BIOSDISKNPART; part++) {
-			bool bootme = d->part[part].attr & GPT_ENT_ATTR_BOOTME;
 			if (d->part[part].size == 0)
 				continue;
 			if (d->part[part].fstype == FS_UNUSED)
 				continue;
 
+			if (first_bootme == -1 && 
+			    d->part[part].attr & GPT_ENT_ATTR_BOOTME)
+				first_bootme = part;
+
+			if (first_ffs == -1 && 
+			    (d->part[part].fstype == FS_BSDFFS ||
+			     d->part[part].fstype == FS_BSDLFS))
+				first_ffs = part;
+
 			if (d->part[part].part_name != NULL &&
 			    strcmp(d->part[part].part_name, name) == 0) {
 				*biosdev = raidframe[i].biosdev;
@@ -1418,11 +1439,13 @@ next_disk:
 				ret = 0;
 				goto out;
 			}
-			if (strcmp(raidframe[i].parent_name, name) == 0) {
-				if (candidate == -1 || bootme)
-					candidate = part;
-				continue;
-			}
+		}
+
+		if (strcmp(raidframe[i].parent_name, name) == 0) {
+			if (first_bootme != -1)
+				candidate = first_bootme;
+			else if (first_ffs != -1)
+				candidate = first_ffs;
 		}
 
 		if (candidate != -1) {
@@ -1514,6 +1537,10 @@ next_disk:
 	}
 
 	for (i = 0; i < raidframe_count; i++) {
+		int first_bootme = -1;
+		int first_ffs = -1;
+		int candidate = -1;
+
 		if (raidframe[i].last_unit != target_unit)
 			continue;
 
@@ -1532,6 +1559,18 @@ next_disk:
 				continue;
 			if (d->part[part].fstype == FS_UNUSED)
 				continue;
+
+#ifndef NO_GPT
+			if (first_bootme == -1 &&
+			    d->part[part].attr & GPT_ENT_ATTR_BOOTME)
+				first_bootme = part;
+#endif
+
+			if (first_ffs == -1 &&
+			    (d->part[part].fstype == FS_BSDFFS ||
+			     d->part[part].fstype == FS_BSDLFS))
+				first_ffs = part;
+
 			if (part == target_part) {
 				*biosdev = raidframe[i].biosdev;
 				*offset = raidframe[i].offset
@@ -1542,6 +1581,22 @@ next_disk:
 				goto out;
 			}
 		}
+
+		if (first_bootme != -1)
+			candidate = first_bootme;
+		else if (first_ffs != -1)
+			candidate = first_ffs;
+
+		if (candidate != -1) {
+			*biosdev = raidframe[i].biosdev;
+			*offset = raidframe[i].offset
+				+ RF_PROTECTED_SECTORS
+				+ d->part[candidate].offset;
+			*size = d->part[candidate].size;
+			ret = 0;
+			goto out;
+		}
+
 next_raidframe:
 		dealloc_biosdisk(d);
 		d = NULL;
@@ -1567,11 +1622,11 @@ biosdisk_open_name(struct open_file *f, 
 	int error = -1;
 
 #ifndef NO_GPT
-	if (strstr(name, "NAME=") == name)
+	if (error && strstr(name, "NAME=") == name)
 		error = biosdisk_find_name(name, &biosdev, &offset, &size);
 #endif
 #ifndef NO_RAIDFRAME
-	if (strstr(name, "raid") == name)
+	if (error && strstr(name, "raid") == name)
 		error = biosdisk_find_raid(name, &biosdev, &offset, &size);
 #endif
 

Index: src/sys/dev/raidframe/rf_netbsdkintf.c
diff -u src/sys/dev/raidframe/rf_netbsdkintf.c:1.410.4.2 src/sys/dev/raidframe/rf_netbsdkintf.c:1.410.4.3
--- src/sys/dev/raidframe/rf_netbsdkintf.c:1.410.4.2	Mon Sep 18 18:57:33 2023
+++ src/sys/dev/raidframe/rf_netbsdkintf.c	Wed Oct 18 11:44:22 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: rf_netbsdkintf.c,v 1.410.4.2 2023/09/18 18:57:33 martin Exp $	*/
+/*	$NetBSD: rf_netbsdkintf.c,v 1.410.4.3 2023/10/18 11:44:22 martin Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2008-2011 The NetBSD Foundation, Inc.
@@ -101,7 +101,7 @@
  ***********************************************************/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.410.4.2 2023/09/18 18:57:33 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.410.4.3 2023/10/18 11:44:22 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_raid_autoconfig.h"
@@ -158,6 +158,8 @@ int     rf_kdebug_level = 0;
 #define db1_printf(a) { }
 #endif				/* DEBUG */
 
+#define DEVICE_XNAME(dev) dev ? device_xname(dev) : "null"
+
 #if (RF_INCLUDE_PARITY_DECLUSTERING_DS > 0)
 static rf_declare_mutex2(rf_sparet_wait_mutex);
 static rf_declare_cond2(rf_sparet_wait_cv);
@@ -524,6 +526,134 @@ rf_rescan(void)
 	return 0;
 }
 
+/*
+ * Example setup:
+ * dk1 at wd0: "raid@wd0", 171965 blocks at 32802, type: raidframe
+ * dk3 at wd1: "raid@wd1", 171965 blocks at 32802, type: raidframz
+ * raid1: Components: /dev/dk1 /dev/dk3
+ * dk4 at raid1: "empty@raid1", 8192 blocks at 34, type: msdos
+ * dk5 at raid1: "root@raid1", 163517 blocks at 8226, type: ffs
+ * 
+ * If booted from wd0, booted_device will be 
+ * disk wd0, startblk = 41092, nblks = 163517
+ *
+ * That is, dk5 with startblk computed from the beginning of wd0
+ * instead of beginning of raid1:
+ * 32802 + 64 (RF_PROTECTED_SECTORS) + 8226 = 41092
+ * 
+ * In order to find the boot wedge, we must iterate on each component, 
+ * find its offset from disk beginning, abd look for the boot wedge with 
+ * startblck adjusted.
+ */
+static device_t
+rf_find_bootwedge(struct raid_softc *rsc)
+{
+	RF_Raid_t *r = &rsc->sc_r;
+	const char *bootname;
+	size_t len;
+	device_t rdev = NULL;
+
+	if (booted_device == NULL)
+		goto out;
+		
+	bootname = device_xname(booted_device);
+	len = strlen(bootname);
+
+	aprint_debug("%s: booted_device %s, startblk = %"PRId64", "
+		     "nblks = %"PRId64"\n", __func__,
+		     bootname, booted_startblk, booted_nblks);
+
+	for (int col = 0; col < r->numCol; col++) {
+		const char *devname = r->Disks[col].devname;
+		const char *parent;
+		struct disk *dk;
+		u_int nwedges;
+		struct dkwedge_info *dkwi;
+		struct dkwedge_list dkwl;
+		size_t dkwi_len;
+		int i;
+
+		devname += sizeof("/dev/") - 1;
+		if (strncmp(devname, "dk", 2) != 0) 
+			continue;
+
+		parent = dkwedge_get_parent_name(r->Disks[col].dev);
+		if (parent == NULL) {
+			aprint_debug("%s: cannot find parent for "
+				     "component /dev/%s", __func__, devname); 
+			continue;
+		}
+
+		if (strncmp(parent, bootname, len) != 0)
+			continue;
+
+		aprint_debug("%s: looking up wedge %s in device %s\n",
+			     __func__, devname, parent);
+
+		dk = disk_find(parent);
+		nwedges = dk->dk_nwedges;
+		dkwi_len = sizeof(*dkwi) * nwedges;
+		dkwi = RF_Malloc(dkwi_len);
+
+		dkwl.dkwl_buf = dkwi;
+		dkwl.dkwl_bufsize = dkwi_len;
+		dkwl.dkwl_nwedges = 0;
+		dkwl.dkwl_ncopied = 0;
+
+		if (dkwedge_list(dk, &dkwl, curlwp) == 0) {
+			daddr_t startblk;
+
+			for (i = 0; i < dkwl.dkwl_ncopied; i++) {
+				if (strcmp(dkwi[i].dkw_devname, devname) == 0)
+					break;
+			}
+
+			KASSERT(i < dkwl.dkwl_ncopied);
+
+			aprint_debug("%s: wedge %s, "
+				     "startblk = %"PRId64", "
+				     "nblks = %"PRId64"\n",
+				     __func__,
+				     dkwi[i].dkw_devname,
+				     dkwi[i].dkw_offset,
+				     dkwi[i].dkw_size);
+
+			startblk = booted_startblk
+				 - dkwi[i].dkw_offset
+				 - RF_PROTECTED_SECTORS;
+			
+			aprint_debug("%s: looking for wedge in %s, "
+				     "startblk = %"PRId64", "
+				     "nblks = %"PRId64"\n",
+				     __func__,
+				     DEVICE_XNAME(rsc->sc_dksc.sc_dev),
+				     startblk, booted_nblks);
+
+			rdev = dkwedge_find_partition(rsc->sc_dksc.sc_dev,
+						      startblk,
+						      booted_nblks);
+			if (rdev) {
+				aprint_debug("%s: root candidate wedge %s "
+					     "shifted from %s\n", __func__,
+					     device_xname(rdev), 
+					     dkwi[i].dkw_devname);
+				goto done;
+			} else {
+				aprint_debug("%s: not found\n", __func__);
+			}
+		}
+
+		aprint_debug("%s: nothing found for col %d\n", __func__, col);
+done:
+		RF_Free(dkwi, dkwi_len);
+	}
+
+out:
+	if (!rdev)
+		aprint_debug("%s: nothing found\n", __func__);
+
+	return rdev;
+}
 
 static void
 rf_buildroothack(RF_ConfigSet_t *config_sets)
@@ -587,49 +717,33 @@ rf_buildroothack(RF_ConfigSet_t *config_
 	}
 
 	/* we found something bootable... */
-
-	/*
-	 * XXX: The following code assumes that the root raid
-	 * is the first ('a') partition. This is about the best
-	 * we can do with a BSD disklabel, but we might be able
-	 * to do better with a GPT label, by setting a specified
-	 * attribute to indicate the root partition. We can then
-	 * stash the partition number in the r->root_partition
-	 * high bits (the bottom 2 bits are already used). For
-	 * now we just set booted_partition to 0 when we override
-	 * root.
-	 */
 	if (num_root == 1) {
-		device_t candidate_root;
+		device_t candidate_root = NULL;
 		dksc = &rsc->sc_dksc;
+
 		if (dksc->sc_dkdev.dk_nwedges != 0) {
-			char cname[sizeof(cset->ac->devname)];
-			/* XXX: assume partition 'a' first */
-			snprintf(cname, sizeof(cname), "%s%c",
-			    device_xname(dksc->sc_dev), 'a');
-			candidate_root = dkwedge_find_by_wname(cname);
-			aprint_debug("%s: candidate wedge root=%s\n", __func__,
-			    cname);
+
+			/* Find the wedge we booted from */
+			candidate_root = rf_find_bootwedge(rsc);
+
+			/* Try first partition */
 			if (candidate_root == NULL) {
-				/*
-				 * If that is not found, because we don't use
-				 * disklabel, return the first dk child
-				 * XXX: we can skip the 'a' check above
-				 * and always do this...
-				 */
 				size_t i = 0;
 				candidate_root = dkwedge_find_by_parent(
 				    device_xname(dksc->sc_dev), &i);
 			}
-			aprint_debug("%s: candidate wedge root=%p\n", __func__,
-			    candidate_root);
-		} else
+			aprint_debug("%s: candidate wedge root %s\n",
+			    __func__, DEVICE_XNAME(candidate_root));
+		} else {
 			candidate_root = dksc->sc_dev;
-		aprint_debug("%s: candidate root=%p booted_device=%p "
-			     "root_partition=%d contains_boot=%d\n",
-		    __func__, candidate_root, booted_device,
-		    rsc->sc_r.root_partition,
+		}
+
+		aprint_debug("%s: candidate root = %s, booted_device = %s, "
+			     "root_partition = %d, contains_boot=%d\n",
+		    __func__, DEVICE_XNAME(candidate_root),
+		    DEVICE_XNAME(booted_device), rsc->sc_r.root_partition,
 		    rf_containsboot(&rsc->sc_r, booted_device));
+
 		/* XXX the check for booted_device == NULL can probably be
 		 * dropped, now that rf_containsboot handles that case.
 		 */
@@ -639,12 +753,12 @@ rf_buildroothack(RF_ConfigSet_t *config_
 			booted_device = candidate_root;
 			booted_method = "raidframe/single";
 			booted_partition = 0;	/* XXX assume 'a' */
-			aprint_debug("%s: set booted_device=%s(%p)\n", __func__,
-			    device_xname(booted_device), booted_device);
+			aprint_debug("%s: set booted_device = %s\n", __func__,
+			    DEVICE_XNAME(booted_device));
 		}
 	} else if (num_root > 1) {
-		aprint_debug("%s: many roots=%d, %p\n", __func__, num_root,
-		    booted_device);
+		aprint_debug("%s: many roots=%d, %s\n", __func__, num_root,
+		    DEVICE_XNAME(booted_device));
 
 		/*
 		 * Maybe the MD code can help. If it cannot, then

Index: src/sys/rump/librump/rumpkern/emul.c
diff -u src/sys/rump/librump/rumpkern/emul.c:1.196 src/sys/rump/librump/rumpkern/emul.c:1.196.20.1
--- src/sys/rump/librump/rumpkern/emul.c:1.196	Thu Apr 30 03:28:19 2020
+++ src/sys/rump/librump/rumpkern/emul.c	Wed Oct 18 11:44:22 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: emul.c,v 1.196 2020/04/30 03:28:19 riastradh Exp $	*/
+/*	$NetBSD: emul.c,v 1.196.20.1 2023/10/18 11:44:22 martin Exp $	*/
 
 /*
  * Copyright (c) 2007-2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: emul.c,v 1.196 2020/04/30 03:28:19 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: emul.c,v 1.196.20.1 2023/10/18 11:44:22 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/cprng.h>
@@ -83,6 +83,8 @@ int mem_no = 2;
 
 device_t booted_device;
 device_t booted_wedge;
+daddr_t booted_startblk;
+uint64_t booted_nblks;
 int booted_partition;
 const char *booted_method;
 

Reply via email to