m/node: add /dev/tty0 and /dev/ttyS0 to erofs
... alongside a few other 'critical' /dev chardevs.
This is in preparation for making minit log into /dev/tty0 and
/dev/ttyS0, as currently it does not log at all (broken by
review.monogon.dev/517).
While we're at it, we chip away at the move-everything-to-fsspec
refactor, and unify initramfs/erofs /dev structure into a dedicated
fsspec file, plus move directories from extra_dirs into its own fsspec
file as well. Fsspec targets can now take files in the fsspecs
attribute, which we point at the newly created files.
Alternatively we could've made a 'fsspec_bundle' rule that would
generate an fsspec provider from a definition (either as native starlark
types or a prototext). We'll have to do something like this later so
that we can get rid of the files attribute in erofs_image, but let's not
make this change too large.
Since we've cleaned up some starlark attribute usage, we then pull on
that thread to remove some now unused code, like the builtin_fsspec
functionality for fsspec-based rules, and the extra_dirs attribute.
Change-Id: I0df6c60df20e38abfc9632d0a701d547292f3697
Reviewed-on: https://review.monogon.dev/c/monogon/+/650
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/metropolis/node/build/BUILD b/metropolis/node/build/BUILD
index e69de29..8eafa9d 100644
--- a/metropolis/node/build/BUILD
+++ b/metropolis/node/build/BUILD
@@ -0,0 +1 @@
+exports_files(["earlydev.fsspec"])
diff --git a/metropolis/node/build/def.bzl b/metropolis/node/build/def.bzl
index c456a94..722a828 100644
--- a/metropolis/node/build/def.bzl
+++ b/metropolis/node/build/def.bzl
@@ -58,12 +58,12 @@
},
)
-def _fsspec_core_impl(ctx, tool, output_file, builtin_fsspec):
+def _fsspec_core_impl(ctx, tool, output_file):
"""
_fsspec_core_impl implements the core of an fsspec-based rule. It takes
- input from the `files`,`files_cc`, `extra_dirs`, `symlinks` and `fsspecs`
- attributes and calls `tool` with the `-out` parameter pointing to
- `output_file` and paths to all fsspecs as positional arguments.
+ input from the `files`,`files_cc`, `symlinks` and `fsspecs` attributes
+ and calls `tool` with the `-out` parameter pointing to `output_file`
+ and paths to all fsspecs as positional arguments.
"""
fs_spec_name = ctx.label.name + ".prototxt"
fs_spec = ctx.actions.declare_file(fs_spec_name)
@@ -97,32 +97,28 @@
mode = 0o555 if is_executable else 0o444
fs_files.append(struct(path = p, source_path = src.path, mode = mode, uid = 0, gid = 0))
- fs_dirs = []
- for p in ctx.attr.extra_dirs:
- if not p.startswith("/"):
- fail("directory {} invalid: must begin with /".format(p))
-
- fs_dirs.append(struct(path = p, mode = 0o555, uid = 0, gid = 0))
-
fs_symlinks = []
for target, p in ctx.attr.symlinks.items():
fs_symlinks.append(struct(path = p, target_path = target))
- fs_spec_content = struct(file = fs_files, directory = fs_dirs, symbolic_link = fs_symlinks)
+ fs_spec_content = struct(file = fs_files, directory = [], symbolic_link = fs_symlinks)
ctx.actions.write(fs_spec, proto.encode_text(fs_spec_content))
extra_specs = []
- if builtin_fsspec != None:
- builtin_fsspec_file = ctx.actions.declare_file(ctx.label.name + "-builtin.prototxt")
- ctx.actions.write(builtin_fsspec_file, proto.encode_text(builtin_fsspec))
- extra_specs.append(builtin_fsspec_file)
for fsspec in ctx.attr.fsspecs:
+ # Skip files-as-fsspecs.
+ if FSSpecInfo not in fsspec:
+ continue
fsspecInfo = fsspec[FSSpecInfo]
extra_specs.append(fsspecInfo.spec)
for f in fsspecInfo.referenced:
inputs.append(f)
+ for file in ctx.files.fsspecs:
+ # Raw .fsspec prototext. No referenced data allowed.
+ extra_specs.append(file)
+
ctx.actions.run(
outputs = [output_file],
inputs = [fs_spec] + inputs + extra_specs,
@@ -133,21 +129,10 @@
return
def _node_initramfs_impl(ctx):
- # At least /dev/console and /dev/null are required to exist for Linux
- # to properly boot an init inside the initramfs. Here we additionally
- # include important device nodes like /dev/kmsg and /dev/ptmx which
- # might need to be available before a proper device manager is launched.
- builtin_fsspec = struct(special_file = [
- struct(path = "/dev/console", mode = 0o600, major = 5, minor = 1),
- struct(path = "/dev/ptmx", mode = 0o644, major = 5, minor = 2),
- struct(path = "/dev/null", mode = 0o644, major = 1, minor = 3),
- struct(path = "/dev/kmsg", mode = 0o644, major = 1, minor = 11),
- ])
-
initramfs_name = ctx.label.name + ".cpio.lz4"
initramfs = ctx.actions.declare_file(initramfs_name)
- _fsspec_core_impl(ctx, ctx.executable._mkcpio, initramfs, builtin_fsspec)
+ _fsspec_core_impl(ctx, ctx.executable._mkcpio, initramfs)
# TODO(q3k): Document why this is needed
return [DefaultInfo(runfiles = ctx.runfiles(files = [initramfs]), files = depset([initramfs]))]
@@ -179,13 +164,6 @@
# Attach static transition to all files_cc inputs to ensure they are built with musl and static.
cfg = build_static_transition,
),
- "extra_dirs": attr.string_list(
- default = [],
- doc = """
- Extra directories to create. These will be created in addition to all the directories required to
- contain the files specified in the `files` attribute.
- """,
- ),
"symlinks": attr.string_dict(
default = {},
doc = """
@@ -201,6 +179,7 @@
These will be merged with all other given attributes.
""",
providers = [FSSpecInfo],
+ allow_files = True,
),
# Tool
@@ -221,7 +200,7 @@
fs_name = ctx.label.name + ".img"
fs_out = ctx.actions.declare_file(fs_name)
- _fsspec_core_impl(ctx, ctx.executable._mkerofs, fs_out, None)
+ _fsspec_core_impl(ctx, ctx.executable._mkerofs, fs_out)
return [DefaultInfo(files = depset([fs_out]))]
@@ -252,13 +231,6 @@
# Attach static transition to all files_cc inputs to ensure they are built with musl and static.
cfg = build_static_transition,
),
- "extra_dirs": attr.string_list(
- default = [],
- doc = """
- Extra directories to create. These will be created in addition to all the directories required to
- contain the files specified in the `files` attribute.
- """,
- ),
"symlinks": attr.string_dict(
default = {},
doc = """
@@ -274,6 +246,7 @@
These will be merged with all other given attributes.
""",
providers = [FSSpecInfo],
+ allow_files = True,
),
# Tools, implicit dependencies.
diff --git a/metropolis/node/build/earlydev.fsspec b/metropolis/node/build/earlydev.fsspec
new file mode 100644
index 0000000..0e88e43
--- /dev/null
+++ b/metropolis/node/build/earlydev.fsspec
@@ -0,0 +1,48 @@
+# Critical /dev files which should be present as early as possible, ie. be baked
+# into filesystem images.
+
+# At least /dev/console and /dev/null are required to exist for Linux
+# to properly boot an init. Here we additionally include important device nodes
+# like /dev/kmsg and /dev/ptmx which might need to be available before a proper
+# device manager (ie. devtmpfs) is launched.
+special_file <
+ path: "/dev/console"
+ type: CHARACTER_DEV
+ major: 1 minor: 1
+ mode: 0600 uid: 0 gid: 0
+>
+special_file <
+ path: "/dev/ptmx"
+ type: CHARACTER_DEV
+ major: 5 minor: 2
+ mode: 0644 uid: 0 gid: 0
+>
+special_file <
+ path: "/dev/null"
+ type: CHARACTER_DEV
+ major: 1 minor: 3
+ mode: 0644 uid: 0 gid: 0
+>
+special_file <
+ path: "/dev/kmsg"
+ type: CHARACTER_DEV
+ major: 1 minor: 11
+ mode: 0644 uid: 0 gid: 0
+>
+
+
+# Metropolis core logs to /dev/ttyS0 and /dev/tty0 by default, we want
+# these to also be present before devtmpfs is mounted so that minit can
+# log there, too.
+special_file <
+ path: "/dev/tty0"
+ type: CHARACTER_DEV
+ major: 4 minor: 0
+ mode: 0600 uid: 0 gid: 0
+>
+special_file <
+ path: "/dev/ttyS0"
+ type: CHARACTER_DEV
+ major: 4 minor: 64
+ mode: 0660 uid: 0 gid: 0
+>
diff --git a/metropolis/node/build/mkerofs/main.go b/metropolis/node/build/mkerofs/main.go
index 0d35eff..9cacc59 100644
--- a/metropolis/node/build/mkerofs/main.go
+++ b/metropolis/node/build/mkerofs/main.go
@@ -21,6 +21,7 @@
import (
"flag"
+ "fmt"
"io"
"log"
"os"
@@ -88,6 +89,34 @@
if err != nil {
log.Fatalf("failed to create symbolic link: %s", err)
}
+ case *fsspec.Inode_SpecialFile:
+ err := fmt.Errorf("unimplemented special file type %s", inode.SpecialFile.Type)
+ base := erofs.Base{
+ Permissions: uint16(inode.SpecialFile.Mode),
+ UID: uint16(inode.SpecialFile.Uid),
+ GID: uint16(inode.SpecialFile.Gid),
+ }
+ switch inode.SpecialFile.Type {
+ case fsspec.SpecialFile_FIFO:
+ err = w.Create(pathname, &erofs.FIFO{
+ Base: base,
+ })
+ case fsspec.SpecialFile_CHARACTER_DEV:
+ err = w.Create(pathname, &erofs.CharacterDevice{
+ Base: base,
+ Major: inode.SpecialFile.Major,
+ Minor: inode.SpecialFile.Minor,
+ })
+ case fsspec.SpecialFile_BLOCK_DEV:
+ err = w.Create(pathname, &erofs.BlockDevice{
+ Base: base,
+ Major: inode.SpecialFile.Major,
+ Minor: inode.SpecialFile.Minor,
+ })
+ }
+ if err != nil {
+ log.Fatalf("failed to make special file: %v", err)
+ }
}
}
@@ -154,8 +183,9 @@
entryRef.data.Type = &fsspec.Inode_SymbolicLink{SymbolicLink: symlink}
}
- if len(spec.SpecialFile) > 0 {
- log.Fatalf("special files are currently unimplemented in mkerofs")
+ for _, specialFile := range spec.SpecialFile {
+ entryRef := fsRoot.pathRef(specialFile.Path)
+ entryRef.data.Type = &fsspec.Inode_SpecialFile{SpecialFile: specialFile}
}
fs, err := os.Create(*outPath)