Re: [PATCH] Adding-storeio-to-the-bootstrap-chain.
Mikhail Karpov <[email protected]>
| Newsgroups | gmane.os.hurd.bugs |
|---|---|
| Message-ID | <[email protected]> |
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
0001-Adding-storeio-to-the-bootstrap-chain.patch
(text/x-patch, 12.2 KB)
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