From: Waldemar Kozaczuk <jwkozac...@gmail.com>
Committer: Waldemar Kozaczuk <jwkozac...@gmail.com>
Branch: master

zfs: new zfs_builder to create ZFS images

This patch makes some incremental improvements to the process
of building ZFS images. However, the main driving force here is
to support building and running ZFS images with the kernel built
with most symbols hidden.

The key missing part to support the above is adding libstdc++.so
to the image so that it can be loaded as needed by cpiod.so and mkfs.so.
However, this would make the loader.elf even larger than the non-hidden
version of it. So instead this patch adds new artifact - zfs_builder.elf
- which is intended to be used by upload_manifest.py only to build ZFS-images.

In essence this patch modifies the main makefile to build new zfs_builder.elf
with bootfs populated with all artifacts necessary to build and load ZFS 
filesystem
(cpiod.so, mkfs.so, etc). At the same time we drop support of building
kernel.elf which became obsolete in favor of standard loader.elf which
now is even leaner - it does not carry the bootfs footprint with ZFS
building tools. On top of that we optimise the build time of ZFS image
by making it run zfs_builder.elf in QEMU kernel direct mode and VGA
console off that cuts boot time to around 20ms.

At the end of the day we come close to satisfying #1068 - "Building a
full OSv image without running it" - we use new OSv-based build tool 
zfs_builder.elf
to build final ZFS image - usr.img.

Another benefit of this approach is that we can use some "old"
pre-existing version of zfs_builder.elf (possibly retrieved from github)
to build ZFS image that includes new version of kernel (loader.elf).

Refs #1068
Refs #1186

Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com>

---
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -144,10 +144,13 @@ endif
 quiet = $(if $V, $1, @echo " $2"; $1)
 very-quiet = $(if $V, $1, @$1)
 
-all: $(out)/loader.img links $(out)/kernel.elf
+all: $(out)/loader.img links $(out)/zfs_builder-stripped.elf
 ifeq ($(arch),x64)
 all: $(out)/vmlinuz.bin
 endif
+ifeq ($(arch),aarch64)
+all: $(out)/zfs_builder.img
+endif
 .PHONY: all
 
 links:
@@ -532,6 +535,12 @@ $(out)/loader.img: $(out)/preboot.bin 
$(out)/loader-stripped.elf
        $(call quiet, scripts/imgedit.py setsize_aarch64 "-f raw $@" 
$(image_size), IMGEDIT $@)
        $(call quiet, scripts/imgedit.py setargs "-f raw $@" $(cmdline), 
IMGEDIT $@)
 
+$(out)/zfs_builder.img: $(out)/preboot.bin $(out)/zfs_builder-stripped.elf
+       $(call quiet, dd if=$(out)/preboot.bin of=$@ > /dev/null 2>&1, DD $@ 
preboot.bin)
+       $(call quiet, dd if=$(out)/zfs_builder-stripped.elf of=$@ conv=notrunc 
obs=4096 seek=16 > /dev/null 2>&1, DD $@ zfs_builder-stripped.elf)
+       $(call quiet, scripts/imgedit.py setsize_aarch64 "-f raw $@" 
$(image_size), IMGEDIT $@)
+       $(call quiet, scripts/imgedit.py setargs "-f raw $@" $(cmdline), 
IMGEDIT $@)
+
 endif # aarch64
 
 $(out)/bsd/sys/crypto/rijndael/rijndael-api-fst.o: COMMON+=-fno-strict-aliasing
@@ -2068,7 +2077,7 @@ $(loader_options_dep): stage1
 ifeq ($(conf_hide_symbols),1)
 version_script_file:=$(out)/version_script
 #Detect which version script to be used and copy to $(out)/version_script
-#so that loader.elf/kernel.elf is rebuilt accordingly if version script has 
changed
+#so that loader.elf/zfs_builder.elf is rebuilt accordingly if version script 
has changed
 ifdef conf_version_script
 ifeq (,$(wildcard $(conf_version_script)))
     $(error Missing version script: $(conf_version_script))
@@ -2121,13 +2130,14 @@ $(out)/loader.elf: $(stage1_targets) 
arch/$(arch)/loader.ld $(out)/bootfs.o $(lo
        @scripts/libosv.py $(out)/osv.syms $(out)/libosv.ld 
`scripts/osv-version.sh` | $(CC) -c -o $(out)/osv.o -x assembler -
        $(call quiet, $(CC) $(out)/osv.o -nostdlib -shared -o $(out)/libosv.so 
-T $(out)/libosv.ld, LIBOSV.SO)
 
-$(out)/kernel.elf: $(stage1_targets) arch/$(arch)/loader.ld 
$(out)/empty_bootfs.o $(loader_options_dep) $(version_script_file)
+$(out)/zfs_builder.elf: $(stage1_targets) arch/$(arch)/loader.ld 
$(out)/zfs_builder_bootfs.o $(loader_options_dep) $(version_script_file)
        $(call quiet, $(LD) -o $@ $(def_symbols) \
                -Bdynamic --export-dynamic --eh-frame-hdr --enable-new-dtags 
-L$(out)/arch/$(arch) \
             $(patsubst 
%version_script,--version-script=%version_script,$(patsubst %.ld,-T %.ld,$^)) \
            $(linker_archives_options) $(conf_linker_extra_options), \
-               LINK kernel.elf)
-       $(call quiet, $(STRIP) $(out)/kernel.elf -o $(out)/kernel-stripped.elf, 
STRIP kernel.elf -> kernel-stripped.elf )
+               LINK zfs_builder.elf)
+$(out)/zfs_builder-stripped.elf:  $(out)/zfs_builder.elf
+       $(call quiet, $(STRIP) $(out)/zfs_builder.elf -o 
$(out)/zfs_builder-stripped.elf, STRIP zfs_builder.elf -> 
zfs_builder-stripped.elf )
 
 $(out)/bsd/%.o: COMMON += -DSMP -D'__FBSDID(__str__)=extern int __bogus__'
 
@@ -2163,9 +2173,8 @@ libgcc_s_dir := ../../$(aarch64_gccbase)/lib64
 endif
 
 $(out)/bootfs.bin: scripts/mkbootfs.py $(bootfs_manifest) 
$(bootfs_manifest_dep) $(tools:%=$(out)/%) \
-               $(out)/zpool.so $(out)/zfs.so $(out)/libenviron.so 
$(out)/libvdso.so
-       $(call quiet, olddir=`pwd`; cd $(out); "$$olddir"/scripts/mkbootfs.py 
-o bootfs.bin -d bootfs.bin.d -m "$$olddir"/$(bootfs_manifest) \
-               -D libgcc_s_dir=$(libgcc_s_dir), MKBOOTFS $@)
+               $(out)/libenviron.so $(out)/libvdso.so $(out)/libsolaris.so
+       $(call quiet, olddir=`pwd`; cd $(out); "$$olddir"/scripts/mkbootfs.py 
-o bootfs.bin -d bootfs.bin.d -m "$$olddir"/$(bootfs_manifest), MKBOOTFS $@)
 
 $(out)/bootfs.o: $(out)/bootfs.bin
 $(out)/bootfs.o: ASFLAGS += -I$(out)
@@ -2184,7 +2193,17 @@ else
 endif
 endif
 
-$(out)/empty_bootfs.o: ASFLAGS += -I$(out)
+$(shell mkdir -p $(out) && cp zfs_builder_bootfs.manifest.skel 
$(out)/zfs_builder_bootfs.manifest)
+ifeq ($(conf_hide_symbols),1)
+$(shell echo "/usr/lib/libstdc++.so.6: $$(readlink -f 
$(libstd_dir))/libstdc++.so" >> $(out)/zfs_builder_bootfs.manifest)
+endif
+$(out)/zfs_builder_bootfs.bin: scripts/mkbootfs.py 
$(zfs_builder_bootfs_manifest) $(tools:%=$(out)/%) \
+               $(out)/zpool.so $(out)/zfs.so $(out)/libenviron.so 
$(out)/libvdso.so $(out)/libsolaris.so
+       $(call quiet, olddir=`pwd`; cd $(out); "$$olddir"/scripts/mkbootfs.py 
-o zfs_builder_bootfs.bin -d zfs_builder_bootfs.bin.d -m 
zfs_builder_bootfs.manifest \
+               -D libgcc_s_dir=$(libgcc_s_dir), MKBOOTFS $@)
+
+$(out)/zfs_builder_bootfs.o: $(out)/zfs_builder_bootfs.bin
+$(out)/zfs_builder_bootfs.o: ASFLAGS += -I$(out)
 
 $(out)/tools/mkfs/mkfs.so: $(out)/tools/mkfs/mkfs.o $(out)/libzfs.so
        $(makedir)
diff --git a/bootfs.manifest.skel b/bootfs.manifest.skel
--- a/bootfs.manifest.skel
+++ b/bootfs.manifest.skel
@@ -1,10 +1,2 @@
 [manifest]
-/libvdso.so: libvdso.so
-/libuutil.so: libuutil.so
-/zpool.so: zpool.so
-/libzfs.so: libzfs.so
 /libsolaris.so: libsolaris.so
-/zfs.so: zfs.so
-/tools/mkfs.so: tools/mkfs/mkfs.so
-/tools/cpiod.so: tools/cpiod/cpiod.so
-/usr/lib/libgcc_s.so.1: %(libgcc_s_dir)s/libgcc_s.so.1
diff --git a/modules/zfs-tools/usr.manifest b/modules/zfs-tools/usr.manifest
--- a/modules/zfs-tools/usr.manifest
+++ b/modules/zfs-tools/usr.manifest
@@ -0,0 +1,5 @@
+[manifest]
+/zpool.so: zpool.so
+/libzfs.so: libzfs.so
+/libuutil.so: libuutil.so
+/libsolaris.so: libsolaris.so
diff --git a/scripts/build b/scripts/build
--- a/scripts/build
+++ b/scripts/build
@@ -301,9 +301,6 @@ if [[ ${vars[create_disk]} == "true" ]]; then
        bare="$SRC"/scripts/disk.bin
        raw_disk=disk
        qcow2_disk=disk
-       if [[ "$arch" == 'x64' ]]; then
-               upload_kernel_mode="-k"
-       fi
 else
        partition_offset=$kernel_end
        bare=loader.img
@@ -316,7 +313,7 @@ create_zfs_disk() {
        "$SRC"/scripts/imgedit.py setpartition "-f raw ${raw_disk}.raw" 2 
$partition_offset $partition_size
        qemu-img convert -f raw -O qcow2 $raw_disk.raw $qcow2_disk.img
        qemu-img resize $qcow2_disk.img ${image_size}b >/dev/null 2>&1
-       "$SRC"/scripts/upload_manifest.py --arch=$arch -o $qcow2_disk.img -m 
usr.manifest -D libgcc_s_dir="$libgcc_s_dir" $upload_kernel_mode
+       "$SRC"/scripts/upload_manifest.py --arch=$arch -o $qcow2_disk.img -m 
usr.manifest -D libgcc_s_dir="$libgcc_s_dir"
 }
 
 create_rofs_disk() {
diff --git a/scripts/firecracker.py b/scripts/firecracker.py
--- a/scripts/firecracker.py
+++ b/scripts/firecracker.py
@@ -370,7 +370,7 @@ def main(options):
     parser.add_argument("-i", "--image", action="store", default=None, 
metavar="CMD",
                         help="path to disk image file. defaults to 
../build/last/usr.img")
     parser.add_argument("-k", "--kernel", action="store", default=None, 
metavar="CMD",
-                        help="path to kernel loader file. defaults to 
../build/last/kernel.elf")
+                        help="path to kernel loader file. defaults to 
../build/last/loader-stripped.elf")
     parser.add_argument("-n", "--networking", action="store_true",
                         help="needs root to setup tap networking first time")
     parser.add_argument("-b", "--bridge", action="store", default=None,
@@ -390,7 +390,7 @@ def main(options):
         default_kernel_file_name = "loader.img"
         default_image_file_name = "disk.img"
     else:
-        default_kernel_file_name = "kernel.elf"
+        default_kernel_file_name = "loader-stripped.elf"
         default_image_file_name = "usr.img"
     cmdargs.kernel_path = os.path.abspath(cmdargs.kernel or 
os.path.join(osv_base, "build/%s/%s" % (cmdargs.opt_path, 
default_kernel_file_name)))
     cmdargs.image_path = os.path.abspath(cmdargs.image or 
os.path.join(osv_base, "build/%s/%s" % (cmdargs.opt_path, 
default_image_file_name)))
diff --git a/scripts/run.py b/scripts/run.py
--- a/scripts/run.py
+++ b/scripts/run.py
@@ -594,7 +594,7 @@ def main(options):
     parser.add_argument("-k", "--kernel", action="store_true",
                         help="Run OSv in QEMU kernel mode as PVH.")
     parser.add_argument("--kernel-path", action="store",
-                        help="path to kernel.elf. defaults to 
build/$mode/kernel.elf")
+                        help="path to loader-stripped.elf. defaults to 
build/$mode/loader-stripped.elf")
     parser.add_argument("--virtio", action="store", 
choices=["legacy","transitional","modern"], default="transitional",
                         help="specify virtio version: legacy, transitional or 
modern")
     parser.add_argument("--arch", action="store", 
choices=["x86_64","aarch64"], default=host_arch,
@@ -618,7 +618,7 @@ def main(options):
         default_kernel_file_name = "loader.img"
         default_image_file_name = "disk.img"
     else:
-        default_kernel_file_name = "kernel.elf"
+        default_kernel_file_name = "loader-stripped.elf"
         default_image_file_name = "usr.img"
     cmdargs.kernel_file = os.path.abspath(cmdargs.kernel_path or 
os.path.join(osv_base, "build/%s/%s" % (cmdargs.opt_path, 
default_kernel_file_name)))
     cmdargs.image_file = os.path.abspath(cmdargs.image or 
os.path.join(osv_base, "build/%s/%s" % (cmdargs.opt_path, 
default_image_file_name)))
diff --git a/scripts/upload_manifest.py b/scripts/upload_manifest.py
--- a/scripts/upload_manifest.py
+++ b/scripts/upload_manifest.py
@@ -136,10 +136,6 @@ def main():
                         metavar='VAR=DATA',
                         action='callback',
                         callback=add_var),
-            make_option('-k',
-                        dest='kernel',
-                        action='store_true',
-                        help='run OSv in direct kernel mode'),
             make_option('--arch',
                         dest='arch',
                         default=host_arch,
@@ -157,14 +153,18 @@ def main():
 
     image_path = os.path.abspath(options.output)
     upload_port = find_free_port()
-    if options.kernel:
-        kernel_mode_flag = '-k --kernel-path build/release/loader-stripped.elf'
-    else:
-        kernel_mode_flag = ''
     arch = options.arch
     if arch == 'x64':
         arch = 'x86_64'
-    osv = subprocess.Popen('cd ../..; scripts/run.py %s --arch=%s --vnc none 
-m 512 -c1 -i "%s" --block-device-cache unsafe -s -e "--norandom --nomount 
--noinit /tools/mkfs.so; /tools/cpiod.so --prefix /zfs/zfs/; /zfs.so set 
compression=off osv" --forward tcp:127.0.0.1:%s-:10000' % 
(kernel_mode_flag,arch,image_path,upload_port), shell=True, 
stdout=subprocess.PIPE)
+
+    if arch == 'aarch64':
+        console = ''
+        zfs_builder_name = 'zfs_builder.img'
+    else:
+        console = '--console=serial'
+        zfs_builder_name = 'zfs_builder-stripped.elf'
+
+    osv = subprocess.Popen('cd ../..; scripts/run.py -k --kernel-path 
build/release/%s --arch=%s --vnc none -m 512 -c1 -i "%s" --block-device-cache 
unsafe -s -e "%s --norandom --nomount --noinit /tools/mkfs.so; /tools/cpiod.so 
--prefix /zfs/zfs/; /zfs.so set compression=off osv" --forward 
tcp:127.0.0.1:%s-:10000' % 
(zfs_builder_name,arch,image_path,console,upload_port), shell=True, 
stdout=subprocess.PIPE)
 
     upload(osv, manifest, depends, upload_port)
 
diff --git a/usr.manifest.skel b/usr.manifest.skel
--- a/usr.manifest.skel
+++ b/usr.manifest.skel
@@ -1,13 +1,6 @@
 [manifest]
 /libenviron.so: libenviron.so
 /libvdso.so: libvdso.so
-/zpool.so: zpool.so
-/libzfs.so: libzfs.so
-/libuutil.so: libuutil.so
-/zfs.so: zfs.so
-/libsolaris.so: libsolaris.so
-/tools/mkfs.so: tools/mkfs/mkfs.so
-/tools/cpiod.so: tools/cpiod/cpiod.so
 /tools/mount-fs.so: tools/mount/mount-fs.so
 /tools/umount.so: tools/mount/umount.so
 /usr/lib/libgcc_s.so.1: %(libgcc_s_dir)s/libgcc_s.so.1
diff --git a/zfs_builder_bootfs.S b/zfs_builder_bootfs.S
--- a/zfs_builder_bootfs.S
+++ b/zfs_builder_bootfs.S
@@ -2,4 +2,5 @@
 .global bootfs_start
 .hidden bootfs_start
 bootfs_start:
+.incbin "zfs_builder_bootfs.bin"
 .popsection
diff --git a/zfs_builder_bootfs.manifest.skel b/zfs_builder_bootfs.manifest.skel
--- a/zfs_builder_bootfs.manifest.skel
+++ b/zfs_builder_bootfs.manifest.skel
@@ -0,0 +1,10 @@
+[manifest]
+/libvdso.so: libvdso.so
+/libuutil.so: libuutil.so
+/zpool.so: zpool.so
+/libzfs.so: libzfs.so
+/libsolaris.so: libsolaris.so
+/zfs.so: zfs.so
+/tools/mkfs.so: tools/mkfs/mkfs.so
+/tools/cpiod.so: tools/cpiod/cpiod.so
+/usr/lib/libgcc_s.so.1: %(libgcc_s_dir)s/libgcc_s.so.1

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/000000000000794da505e3407dbb%40google.com.

Reply via email to