NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

bin/58212: cgdconfig(8): Add zfs verification method



>Number:         58212
>Category:       bin
>Synopsis:       cgdconfig(8): Add zfs verification method
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Apr 28 20:15:00 +0000 2024
>Originator:     Malte Dehling
>Release:        NetBSD 10.0, -current
>Organization:
>Environment:
    NetBSD 10.0 (GENERIC) #4: Wed Apr 24 12:21:26 PDT 2024
    mdehling@nb-base-dev:/scratch/obj/sys/arch/amd64/compile/GENERIC amd64

>Description:
I would like to propose the attached patch to add a zfs verification
method to the cgdconfig(8) program.  With such a method, it will be
possible to use cgd devices as vdevs in a zpool without an intermediate
gpt.

The verification method used here is the same as in fstyp(8): read the
first vdev label (256k at offset 0) and see if vdev_label->vl_vdev_phys
(112k-40b at offset 16k) describes a valid nvlist structure with existing
zpool name property.

>How-To-Repeat:

>Fix:
Make it possible to use cgd devices as vdevs in a zpool without an
intermediate gpt.
---
 .../amd64/ramdisks/ramdisk-cgdroot/Makefile   |  3 ++
 .../amd64/ramdisks/ramdisk-cgdroot/list.zfs   |  3 ++
 rescue/Makefile                               |  4 ++
 rescue/list.zfs                               |  3 ++
 sbin/cgdconfig/Makefile                       | 18 +++++++
 sbin/cgdconfig/cgdconfig.8                    |  2 +
 sbin/cgdconfig/cgdconfig.c                    | 53 +++++++++++++++++++
 sbin/cgdconfig/params.c                       |  9 ++++
 sbin/cgdconfig/params.h                       |  1 +
 9 files changed, 96 insertions(+)
 create mode 100644 distrib/amd64/ramdisks/ramdisk-cgdroot/list.zfs
 create mode 100644 rescue/list.zfs

diff --git a/distrib/amd64/ramdisks/ramdisk-cgdroot/Makefile
b/distrib/amd64/ramdisks/ramdisk-cgdroot/Makefile
index 7be7a009f28..75b07c6ebf0 100644
--- a/distrib/amd64/ramdisks/ramdisk-cgdroot/Makefile
+++ b/distrib/amd64/ramdisks/ramdisk-cgdroot/Makefile
@@ -9,6 +9,9 @@ SMALLPROG_INET6=1
 .include "${.CURDIR}/../common/Makefile.ramdisk"

 LISTS+=		${DISTRIBDIR}/common/list.cgdroot
+.if ${MKZFS} != "no"
+LISTS+=		${.CURDIR}/list.zfs
+.endif
 MTREECONF+=	${DISTRIBDIR}/common/mtree.cgdroot

 .if ${USE_INET6} != "no"
diff --git a/distrib/amd64/ramdisks/ramdisk-cgdroot/list.zfs
b/distrib/amd64/ramdisks/ramdisk-cgdroot/list.zfs
new file mode 100644
index 00000000000..8247065d020
--- /dev/null
+++ b/distrib/amd64/ramdisks/ramdisk-cgdroot/list.zfs
@@ -0,0 +1,3 @@
+#	$NetBSD$
+
+LIBS    -lnvpair
diff --git a/rescue/Makefile b/rescue/Makefile
index 459e8a7135a..6ed6c178f3f 100644
--- a/rescue/Makefile
+++ b/rescue/Makefile
@@ -42,6 +42,10 @@ LISTS+=		${.CURDIR}/list.${f}
 LISTS+=		${.CURDIR}/list.inet6
 .endif

+.if ${MKZFS} != "no"
+LISTS+=		${.CURDIR}/list.zfs
+.endif
+
 LISTS+=		${.CURDIR}/list.crypto
 CRUNCHENV+=	MKKERBEROS=no		# for ssh

diff --git a/rescue/list.zfs b/rescue/list.zfs
new file mode 100644
index 00000000000..02bf8bc362c
--- /dev/null
+++ b/rescue/list.zfs
@@ -0,0 +1,3 @@
+#	$NetBSD$
+
+LIBS	-lnvpair
diff --git a/sbin/cgdconfig/Makefile b/sbin/cgdconfig/Makefile
index fec75b4e375..bf1be8109e3 100644
--- a/sbin/cgdconfig/Makefile
+++ b/sbin/cgdconfig/Makefile
@@ -29,4 +29,22 @@ ARGON2_NO_THREADS=1
 .include "${NETBSDSRCDIR}/external/apache2/argon2/lib/libargon2/Makefile.inc"
 .endif

+.if ${MKZFS} != "no"
+DPADD+=	${LIBNVPAIR}
+LDADD+=	-lnvpair
+CPPFLAGS+=	-DHAVE_ZFS
+
+OSNET=${NETBSDSRCDIR}/external/cddl/osnet
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/include
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/sys
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/dist/head
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/dist/lib/libzpool/common
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/dist/uts/common
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/dist/uts/common/fs/zfs
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/dist/lib/libnvpair
+
+COPTS.cgdconfig.c+=	-Wno-unknown-pragmas
+COPTS.cgdconfig.c+=	-Wno-strict-prototypes
+.endif
+
 .include <bsd.prog.mk>
diff --git a/sbin/cgdconfig/cgdconfig.8 b/sbin/cgdconfig/cgdconfig.8
index 2b0da2cb732..e48ccde02c5 100644
--- a/sbin/cgdconfig/cgdconfig.8
+++ b/sbin/cgdconfig/cgdconfig.8
@@ -270,6 +270,8 @@ scan for a valid Master Boot Record.
 scan for a valid GUID partition table.
 .It ffs
 scan for a valid FFS file system.
+.It zfs
+scan for a valid ZFS vdev label (if compiled with MKZFS).
 .It re-enter
 prompt for passphrase twice, and ensure entered passphrases are
 identical.
diff --git a/sbin/cgdconfig/cgdconfig.c b/sbin/cgdconfig/cgdconfig.c
index 9a634ef37e2..4baccb1d68f 100644
--- a/sbin/cgdconfig/cgdconfig.c
+++ b/sbin/cgdconfig/cgdconfig.c
@@ -73,6 +73,11 @@ __RCSID("$NetBSD: cgdconfig.c,v 1.61 2022/11/17
06:40:38 chs Exp $");

 #include <ufs/ffs/fs.h>

+#ifdef HAVE_ZFS
+#include <libnvpair.h>
+#include <sys/vdev_impl.h>
+#endif
+
 #include "params.h"
 #include "pkcs5_pbkdf2.h"
 #include "utils.h"
@@ -170,6 +175,9 @@ static int	 verify_ffs(int);
 static int	 verify_reenter(struct params *);
 static int	 verify_mbr(int);
 static int	 verify_gpt(int);
+#ifdef HAVE_ZFS
+static int	 verify_zfs(int);
+#endif

 __dead static void	 usage(void);

@@ -1024,6 +1032,10 @@ verify(struct params *p, int fd)
 		return verify_mbr(fd);
 	case VERIFY_GPT:
 		return verify_gpt(fd);
+#ifdef HAVE_ZFS
+	case VERIFY_ZFS:
+		return verify_zfs(fd);
+#endif
 	default:
 		warnx("unimplemented verification method");
 		return -1;
@@ -1182,6 +1194,47 @@ verify_gpt(int fd)
 	return ret;
 }

+#ifdef HAVE_ZFS
+static int
+verify_zfs(int fd)
+{
+	vdev_label_t *vdev_label;
+	vdev_phys_t *vdev_phys;
+	nvlist_t *config = NULL;
+	ssize_t ret;
+
+	/*
+	 * Read the first ZFS vdev label located at offset 0.
+	 */
+	vdev_label = emalloc(sizeof *vdev_label);
+	ret = prog_pread(fd, vdev_label, sizeof(*vdev_label), 0);
+	if (ret < 0) {
+		warn("pread");
+		ret = 1;
+		goto bail;
+	} else if ((size_t)ret < sizeof(*vdev_label)) {
+		warnx("pread: incomplete block");
+		ret = 1;
+		goto bail;
+	};
+
+	ret = 0;
+
+	vdev_phys = &(vdev_label->vl_vdev_phys);
+	if ((nvlist_unpack(vdev_phys->vp_nvlist,
+		sizeof(vdev_phys->vp_nvlist), &config, 0)) != 0 ||
+		!nvlist_exists(config, "name"))
+	{
+		ret = 1;
+	};
+
+	nvlist_free(config);
+ bail:
+	free(vdev_label);
+	return ret;
+}
+#endif
+
 static off_t sblock_try[] = SBLOCKSEARCH;

 static int
diff --git a/sbin/cgdconfig/params.c b/sbin/cgdconfig/params.c
index 91af02c21cc..5da25ec0595 100644
--- a/sbin/cgdconfig/params.c
+++ b/sbin/cgdconfig/params.c
@@ -287,6 +287,10 @@ params_verify_method(string_t *in)
 		p->verify_method = VERIFY_MBR;
 	if (!strcmp("gpt", vm))
 		p->verify_method = VERIFY_GPT;
+#ifdef HAVE_ZFS
+	if (!strcmp("zfs", vm))
+		p->verify_method = VERIFY_ZFS;
+#endif

 	string_free(in);

@@ -1065,6 +1069,11 @@ params_fput(struct params *p, FILE *f)
 	case VERIFY_GPT:
 		print_kvpair_cstr(f, ts, "verify_method", "gpt");
 		break;
+#ifdef HAVE_ZFS
+	case VERIFY_ZFS:
+		print_kvpair_cstr(f, ts, "verify_method", "zfs");
+		break;
+#endif
 	default:
 		warnx("unsupported verify_method (%d)", p->verify_method);
 		return -1;
diff --git a/sbin/cgdconfig/params.h b/sbin/cgdconfig/params.h
index fb79a0deb80..ef49dde6aba 100644
--- a/sbin/cgdconfig/params.h
+++ b/sbin/cgdconfig/params.h
@@ -81,6 +81,7 @@ struct params {
 #define VERIFY_REENTER		0x4
 #define VERIFY_MBR      	0x5
 #define VERIFY_GPT      	0x6
+#define VERIFY_ZFS      	0x7

 /* shared key derivation methods */

-- 
Malte Dehling



Home | Main Index | Thread Index | Old Index