Hello,
On Tue, 28 Apr 2026 23:01:42 Samuel Thibault wrote:
Well, I managed to stop using libmachdev, but I still couldn't get the
store from storeio.
> Opening the store can be done provided that you have the bootstrap
> port. And you have it from the special port, you can just pick it
> up with task_get_bootstrap_port and use it. You just need to make
> sure that storeio resumes the next task after being ready to serve
> file_get_storage_info.
Passing the storeio_port obtained from task_get_bootstrap_port to
store_create
doesn't produce an invalid port error, but it turns out that in this case,
cred = NULL is passed to trivfs_S_file_get_storage_info. I discovered
that the
problem was that trivfs_begin_using_protid_payload couldn't find a suitable
class from trivfs_dynamic_protid_port_classes. I'm also confused about where
and with what parameters fsys_getroot should be called. I tried calling
it in
storeio_bootstrap_startup after task_resume (next_task) with the
storeio_fsys->underlying parameter (I understand correctly that this is the
storeio process control port, right?), but this doesn't produce any results.
> Not sure what you mean. You don't need to interact with exec etc. before
> interacting with storeio and rumpdisk.
As far as I understand, the mechanism for calling exec from ext2fs is
roughly
analogous to what storeio requires for ext2fs. However, it expects
fsys_startup
to be called from exec, so I don't think it's very applicable...
Thanks,
--
Mikhail Karpov
From a525e64e2d75d38512eae8e442769f437c43ca52 Mon Sep 17 00:00:00 2001
From: Mikhail Karpov <[email protected]>
Date: Wed, 6 May 2026 09:59:34 +0700
Subject: [PATCH] Adding storeio to the bootstrap chain
---
libdiskfs/init-main.c | 26 ++++-
storeio/storeio.c | 265 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 280 insertions(+), 11 deletions(-)
diff --git a/libdiskfs/init-main.c b/libdiskfs/init-main.c
index 69c30fd1..c257c840 100644
--- a/libdiskfs/init-main.c
+++ b/libdiskfs/init-main.c
@@ -31,6 +31,7 @@ diskfs_init_main (struct argp *startup_argp,
{
error_t err;
struct store_argp_params store_params = { 0 };
+ store_params.store_optional = 1;
struct store *store;
/* We must use ARGP_IN_ORDER for the parsing of --boot-command to work. */
@@ -40,9 +41,14 @@ diskfs_init_main (struct argp *startup_argp,
assert_perror_backtrace (err);
*store_parsed = store_params.result;
- err = store_parsed_name (*store_parsed, &diskfs_disk_name);
- if (err)
- error (2, err, "store_parsed_name");
+ //if (diskfs_boot_filesystem ())
+ // diskfs_disk_name = "storeio";
+ //else
+ // {
+ err = store_parsed_name (*store_parsed, &diskfs_disk_name);
+ if (err)
+ error (2, err, "store_parsed_name");
+ // }
/* This must come after the args have been parsed, as this is where the
host priv ports are set for booting. */
@@ -63,8 +69,18 @@ diskfs_init_main (struct argp *startup_argp,
if (err)
error (4, err, "diskfs_init_diskfs");
- err = store_parsed_open (*store_parsed, diskfs_readonly ? STORE_READONLY : 0,
- &store);
+ //if (diskfs_boot_filesystem ())
+ // {
+ // mach_port_t storeio_port;
+ // task_get_bootstrap_port (mach_task_self (), &storeio_port);
+ // err = store_create (storeio_port, diskfs_readonly ? STORE_READONLY : 0,
+ // 0, &store);
+ // mach_port_deallocate (mach_task_self (), storeio_port);
+ // }
+ //else
+ err = store_parsed_open (*store_parsed,
+ diskfs_readonly ? STORE_READONLY : 0, &store);
+
if (err)
error (3, err, "%s", diskfs_disk_name);
diff --git a/storeio/storeio.c b/storeio/storeio.c
index 4e8a9628..2740e073 100644
--- a/storeio/storeio.c
+++ b/storeio/storeio.c
@@ -23,12 +23,16 @@
#include <fcntl.h>
#include <argp.h>
#include <argz.h>
+#include <sys/mman.h>
#include <sys/sysmacros.h>
#include <stdbool.h>
#include <hurd.h>
#include <hurd/ports.h>
#include <hurd/trivfs.h>
+#include <hurd/fsys.h>
+#include <hurd/startup.h>
+#include <hurd/paths.h>
#include <version.h>
#include "open.h"
@@ -48,6 +52,11 @@ static struct argp_option options[] =
{"rdev", 'n', "ID", 0,
"The stat rdev number for this node; may be either a"
" single integer, or of the form MAJOR,MINOR"},
+ {0, 0, 0, 0, "Boot options:"},
+ {"next-task", 'N', "TASK", 0, "Next bootstrap task"},
+ {"host-priv-port", 'H', "PORT", 0, "Port for bootstrapping host"},
+ {"device-master-port", 'P', "PORT", 0, "Port for bootstrapping device"
+ " master"},
{0}
};
static const char doc[] = "Translator for devices and other stores";
@@ -57,6 +66,23 @@ const char *argp_program_version = STANDARD_HURD_VERSION (storeio);
static bool debug=false;
static char *debug_fname=NULL;
+/* The FS control port */
+static mach_port_t control_port;
+
+/* Startup and shutdown notifications management */
+struct port_class *shutdown_notify_class;
+
+static char **hurd_init_argv;
+
+struct port_bucket *port_bucket;
+
+/* Our parent's task, if applicable */
+static task_t parent_task;
+
+static task_t next_task;
+
+struct trivfs_control *storeio_fsys;
+
/* Desired store parameters specified by the user. */
struct storeio_argp_params
{
@@ -64,6 +90,66 @@ struct storeio_argp_params
struct dev *dev; /* We fill in its flag members. */
};
+static error_t
+storeio_bootstrap_startup (mach_port_t bootstrap)
+{
+ port_bucket = ports_create_bucket ();
+ struct port_class *trivfs_cntl_class;
+ trivfs_cntl_class = ports_create_class (trivfs_clean_cntl, 0);
+ struct port_class *trivfs_protid_class;
+ trivfs_protid_class = ports_create_class (trivfs_clean_protid, 0);
+
+ error_t err = trivfs_startup (bootstrap, 0, trivfs_cntl_class, port_bucket,
+ trivfs_protid_class, 0, &storeio_fsys);
+ if (err)
+ return err;
+
+ err = fsys_getpriv (bootstrap, &_hurd_host_priv,
+ &_hurd_device_master, &parent_task);
+ if (err)
+ return err;
+
+ mach_port_t right = ports_get_send_right (&storeio_fsys->pi);
+ err = task_set_special_port (next_task, TASK_BOOTSTRAP_PORT, right);
+ if (err)
+ return err;
+
+ err = mach_port_deallocate (mach_task_self (), right);
+ if (err)
+ return err;
+
+ err = task_resume (next_task);
+ if (err)
+ return err;
+
+ /* Make sure we have a console. */
+ mach_port_t dev;
+ err = get_privileged_ports (NULL, &dev);
+ if (err)
+ return err;
+
+ mach_port_t cons;
+ err = device_open (dev, D_READ | D_WRITE, "console", &cons);
+ if (err)
+ return err;
+
+ err = mach_port_deallocate (mach_task_self (), dev);
+ if (err)
+ return err;
+
+ stdin = mach_open_devstream (cons, "r");
+ stdout = stderr = mach_open_devstream (cons, "w");
+ err = mach_port_deallocate (mach_task_self (), cons);
+ if (err)
+ return err;
+
+ setlinebuf (stderr);
+ printf ("storeio ");
+ fflush (stdout);
+
+ return 0;
+}
+
/* Parse a single option. */
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
@@ -80,6 +166,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
case 'e': params->dev->enforced = 1; break;
case 'F': params->dev->no_fileio = 1; break;
+ case 'N': next_task = atoi (arg); break;
+ case 'H': _hurd_host_priv = atoi (arg); break;
+ case 'P': _hurd_device_master = atoi (arg); break;
+
case 'n':
{
char *start = arg, *end;
@@ -134,8 +224,6 @@ parse_opt (int key, char *arg, struct argp_state *state)
static const struct argp_child argp_kids[] = { { &store_argp }, {0} };
static const struct argp argp = { options, parse_opt, 0, doc, argp_kids };
-
-struct trivfs_control *storeio_fsys;
int
main (int argc, char *argv[])
@@ -144,6 +232,7 @@ main (int argc, char *argv[])
mach_port_t bootstrap;
struct dev device;
struct storeio_argp_params params;
+ hurd_init_argv = argv;
memset (&device, 0, sizeof device);
pthread_mutex_init (&device.lock, NULL);
@@ -165,10 +254,19 @@ main (int argc, char *argv[])
if (bootstrap == MACH_PORT_NULL)
error (2, 0, "Must be started as a translator");
- /* Reply to our parent */
- err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &storeio_fsys);
- if (err)
- error (3, err, "trivfs_startup");
+ if (next_task != MACH_PORT_NULL)
+ {
+ err = storeio_bootstrap_startup (bootstrap);
+ if (err)
+ error (1, err, "storeio_bootstrap_startup");
+ }
+ else
+ {
+ /* Reply to our parent */
+ err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &storeio_fsys);
+ if (err)
+ error (3, err, "trivfs_startup");
+ }
}
storeio_fsys->hook = &device;
@@ -452,3 +550,158 @@ trivfs_S_fsys_syncfs (struct trivfs_control *cntl,
else
return 0;
}
+
+/* Override the privileged ports for booting the system */
+kern_return_t
+trivfs_S_fsys_getpriv (struct trivfs_control *cntl,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ mach_port_t *host, mach_msg_type_name_t *host_privPoly,
+ mach_port_t *dev, mach_msg_type_name_t *devPoly,
+ mach_port_t *fstask, mach_msg_type_name_t *fstPoly)
+{
+ error_t err = get_privileged_ports (host, dev);
+ if (!err)
+ {
+ *fstask = mach_task_self ();
+ *host_privPoly = *devPoly = MACH_MSG_TYPE_MOVE_SEND;
+ *fstPoly = MACH_MSG_TYPE_COPY_SEND;
+ }
+
+ return err;
+}
+
+kern_return_t
+trivfs_S_fsys_startup (mach_port_t bootport,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ int flags,
+ mach_port_t cntl,
+ mach_port_t *realnode,
+ mach_msg_type_name_t *realnodetype)
+{
+ control_port = cntl;
+ *realnode = MACH_PORT_NULL;
+ *realnodetype = MACH_MSG_TYPE_COPY_SEND;
+
+ mach_port_t mybootport;
+ task_get_bootstrap_port (mach_task_self (), &mybootport);
+ if (mybootport)
+ fsys_startup (mybootport, flags, control_port, MACH_MSG_TYPE_COPY_SEND,
+ realnode);
+ return 0;
+}
+
+static void
+arrange_shutdown_notification (void)
+{
+ shutdown_notify_class = ports_create_class (0, 0);
+
+ /* Arrange to get notified when the system goes down */
+ struct port_info *pi;
+ error_t err = ports_create_port (shutdown_notify_class, port_bucket,
+ sizeof (struct port_info), &pi);
+ if (err)
+ return;
+
+ mach_port_t initport = file_name_lookup (_SERVERS_STARTUP, 0, 0);
+ if (initport == MACH_PORT_NULL)
+ {
+ mach_print ("WARNING: machdev not registered for shutdown\n");
+ return;
+ }
+
+ mach_port_t notify = ports_get_send_right (pi);
+ ports_port_deref (pi);
+ startup_request_notification (initport, notify, MACH_MSG_TYPE_MAKE_SEND,
+ program_invocation_short_name);
+ mach_port_deallocate (mach_task_self (), notify);
+ mach_port_deallocate (mach_task_self (), initport);
+}
+
+static void
+essential_task (void)
+{
+ mach_port_t host;
+ error_t err = get_privileged_ports (&host, 0);
+ if (err)
+ {
+ mach_print ("WARNING: Cannot register as essential task\n");
+ return;
+ }
+
+ mach_port_t startup = file_name_lookup (_SERVERS_STARTUP, 0, 0);
+ if (startup == MACH_PORT_NULL)
+ {
+ mach_print ("WARNING: Cannot register as essential task\n");
+ mach_port_deallocate (mach_task_self (), host);
+ return;
+ }
+
+ startup_essential_task (startup, mach_task_self (), MACH_PORT_NULL,
+ program_invocation_short_name, host);
+ mach_port_deallocate (mach_task_self (), startup);
+ mach_port_deallocate (mach_task_self (), host);
+}
+
+kern_return_t
+trivfs_S_fsys_init (struct trivfs_control *fsys,
+ mach_port_t reply, mach_msg_type_name_t replytype,
+ mach_port_t procserver,
+ mach_port_t authhandle)
+{
+ /* Traverse to the bootstrapping server first */
+ error_t err;
+ mach_port_t bootstrap;
+ task_get_bootstrap_port (mach_task_self (), &bootstrap);
+ if (bootstrap)
+ {
+ process_t parent_proc;
+
+ err = proc_task2proc (procserver, parent_task, &parent_proc);
+ assert_perror_backtrace (err);
+
+ /* We don't need this anymore. */
+ mach_port_deallocate (mach_task_self (), parent_task);
+ parent_task = MACH_PORT_NULL;
+
+ proc_mark_exec(parent_proc);
+
+ err = fsys_init (bootstrap, parent_proc, MACH_MSG_TYPE_COPY_SEND, authhandle);
+ assert_perror_backtrace (err);
+
+ mach_port_deallocate (mach_task_self (), parent_proc);
+ }
+
+ mach_port_t root;
+ uid_t idlist[] = {0, 0, 0};
+ retry_type retry;
+ string_t retry_name;
+ err = fsys_getroot (control_port, MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND,
+ idlist, 3, idlist, 3, 0,
+ &retry, retry_name, &root);
+ assert_perror_backtrace (err);
+ assert_backtrace (retry == FS_RETRY_NORMAL);
+ assert_backtrace (retry_name[0] == '\0');
+ assert_backtrace (root != MACH_PORT_NULL);
+
+ mach_port_t *portarray = mmap (0, INIT_PORT_MAX * sizeof (*portarray),
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ for (unsigned int i = 0; i < INIT_PORT_MAX; ++i)
+ portarray[i] = MACH_PORT_NULL;
+ portarray[INIT_PORT_PROC] = procserver;
+ portarray[INIT_PORT_AUTH] = authhandle;
+ portarray[INIT_PORT_CRDIR] = root;
+ portarray[INIT_PORT_CWDIR] = root;
+ _hurd_init (0, hurd_init_argv, portarray, INIT_PORT_MAX, NULL, 0);
+#ifdef HAVE__HURD_LIBC_PROC_INIT
+ _hurd_libc_proc_init (hurd_init_argv);
+#endif
+
+ /* Mark us as essential if bootstrapping. */
+ essential_task ();
+
+ arrange_shutdown_notification ();
+
+ return 0;
+}
--
2.43.0