NB: Reboot still hangs on diskfs_S_startup_dosync() even though that times out and then rumpdisk shuts down cleanly.
--- libmachdev/Makefile | 6 +-- libmachdev/ds_routines.c | 10 ++++ libmachdev/machdev-device_emul.h | 1 + libmachdev/machdev.h | 1 + libmachdev/startup.c | 86 ++++++++++++++++++++++++++++++++ libmachdev/startup.h | 28 +++++++++++ libmachdev/trivfs_server.c | 49 +++++++++++++++++- libmachdev/trivfs_server.h | 30 +++++++++++ rumpdisk/block-rump.c | 16 +++++- 9 files changed, 221 insertions(+), 6 deletions(-) create mode 100644 libmachdev/startup.c create mode 100644 libmachdev/startup.h create mode 100644 libmachdev/trivfs_server.h diff --git a/libmachdev/Makefile b/libmachdev/Makefile index 15b98cf1..bb4fcd8a 100644 --- a/libmachdev/Makefile +++ b/libmachdev/Makefile @@ -19,10 +19,10 @@ dir := libmachdev makemode := library libname = libmachdev -SRCS = ds_routines.c trivfs_server.c \ - deviceServer.c notifyServer.c mach_i386Server.c +SRCS = ds_routines.c trivfs_server.c startup_notifyServer.c \ + deviceServer.c notifyServer.c mach_i386Server.c startup.c -LCLHDRS = machdev.h machdev-device_emul.h machdev-dev_hdr.h mach_device.h +LCLHDRS = machdev.h machdev-device_emul.h machdev-dev_hdr.h mach_device.h startup.h installhdrs = machdev.h machdev-device_emul.h machdev-dev_hdr.h HURDLIBS = ports trivfs LDLIBS += -lpthread -lmachuser diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index 53e0c080..64080176 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -317,6 +317,16 @@ void machdev_device_init() } } +void machdev_device_shutdown() +{ + int i; + for (i = 0; i < num_emul; i++) + { + if (emulation_list[i]->shutdown) + emulation_list[i]->shutdown(); + } +} + static int demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) { diff --git a/libmachdev/machdev-device_emul.h b/libmachdev/machdev-device_emul.h index ab1bd92b..edf79b96 100644 --- a/libmachdev/machdev-device_emul.h +++ b/libmachdev/machdev-device_emul.h @@ -64,6 +64,7 @@ struct machdev_device_emulation_ops recnum_t, vm_offset_t, vm_size_t); io_return_t (*writev_trap) (void *, dev_mode_t, recnum_t, io_buf_vec_t *, vm_size_t); + void (*shutdown) (void); }; #endif /* _MACHDEV_DEVICE_EMUL_H_ */ diff --git a/libmachdev/machdev.h b/libmachdev/machdev.h index 55a56e0d..5f07d35f 100644 --- a/libmachdev/machdev.h +++ b/libmachdev/machdev.h @@ -30,6 +30,7 @@ void machdev_register (struct machdev_device_emulation_ops *ops); void machdev_device_init(void); +void machdev_device_shutdown(void); void * machdev_server(void *); error_t machdev_create_device_port (size_t size, void *result); int machdev_trivfs_init(mach_port_t bootstrap_resume_task, const char *name, mach_port_t *bootstrap); diff --git a/libmachdev/startup.c b/libmachdev/startup.c new file mode 100644 index 00000000..49eec502 --- /dev/null +++ b/libmachdev/startup.c @@ -0,0 +1,86 @@ +/* + Copyright (C) 2020 Free Software Foundation, Inc. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* Startup and shutdown notifications management */ + +#include "startup.h" +#include "trivfs_server.h" +#include <startup_notify_S.h> +#include <unistd.h> +#include <hurd/paths.h> +#include <hurd/startup.h> +#include <hurd/trivfs.h> +#include "libmachdev/machdev.h" + +struct port_class *machdev_shutdown_notify_class; + +void +arrange_shutdown_notification () +{ + error_t err; + mach_port_t initport, notify; + process_t proc; + struct port_info *pi; + + proc = getproc (); + assert_backtrace (proc); + + machdev_shutdown_notify_class = ports_create_class (0, 0); + + /* Arrange to get notified when the system goes down */ + err = ports_create_port (machdev_shutdown_notify_class, port_bucket, + sizeof (struct port_info), &pi); + if (err) + return; + + /* Mark us as important. */ + err = proc_mark_important (proc); + mach_port_deallocate (mach_task_self (), proc); + + initport = file_name_lookup (_SERVERS_STARTUP, 0, 0); + if (initport == MACH_PORT_NULL) + { + mach_print ("WARNING: machdev not registered for shutdown\n"); + return; + } + + 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); +} + +/* The system is going down. Sync data, then call trivfs_goaway() */ +error_t +S_startup_dosync (mach_port_t handle) +{ + struct port_info *inpi = ports_lookup_port (port_bucket, handle, + machdev_shutdown_notify_class); + + if (!inpi) + return EOPNOTSUPP; + + ports_port_deref (inpi); + + /* Sync and close device(s) */ + machdev_device_shutdown (); + + return trivfs_goaway (NULL, FSYS_GOAWAY_FORCE); +} diff --git a/libmachdev/startup.h b/libmachdev/startup.h new file mode 100644 index 00000000..2bc6b1d7 --- /dev/null +++ b/libmachdev/startup.h @@ -0,0 +1,28 @@ +/* + Copyright (C) 2020 Free Software Foundation, Inc. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef STARTUP_H +#define STARTUP_H + +/* Startup and shutdown notifications management */ + +/* Port class for startup requests */ +extern struct port_class *machdev_shutdown_notify_class; + +void arrange_shutdown_notification (void); + +#endif /* STARTUP_H */ diff --git a/libmachdev/trivfs_server.c b/libmachdev/trivfs_server.c index eec8585e..6757b217 100644 --- a/libmachdev/trivfs_server.c +++ b/libmachdev/trivfs_server.c @@ -24,18 +24,22 @@ #include <stdio.h> #include <fcntl.h> #include <error.h> +#include <sys/mman.h> #include <hurd/ports.h> #include <hurd/trivfs.h> +#include <hurd/fsys.h> #include <hurd.h> #include <device/device.h> /* mach console */ #include "libdiskfs/diskfs.h" +#include "startup.h" +#include "startup_notify_S.h" #include "device_S.h" #include "notify_S.h" #include "fsys_S.h" #include "mach_i386_S.h" -static struct port_bucket *port_bucket; +struct port_bucket *port_bucket; /* Trivfs hooks. */ int trivfs_fstype = FSTYPE_MISC; @@ -49,6 +53,9 @@ int trivfs_allow_open = O_READ | O_WRITE; struct port_class *trivfs_protid_class; struct port_class *trivfs_cntl_class; +/* Our control port */ +static mach_port_t machdev_ctl; + /* Implementation of notify interface */ kern_return_t do_mach_notify_port_deleted (struct port_info *pi, @@ -183,7 +190,42 @@ S_i386_io_perm_create (mach_port_t master_port, return i386_io_perm_create (_hurd_device_master, from, to, io_perm); } -/* This is fraud */ +kern_return_t +trivfs_S_fsys_init (struct trivfs_control *tc, + mach_port_t reply, mach_msg_type_name_t replytype, + mach_port_t procserver, + mach_port_t authhandle) +{ + error_t err; + mach_port_t *portarray; + unsigned int i; + uid_t idlist[] = {0, 0, 0}; + mach_port_t root; + retry_type retry; + string_t retry_name; + + err = fsys_getroot (machdev_ctl, 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); + + portarray = mmap (0, INIT_PORT_MAX * sizeof *portarray, + PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); + for (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, NULL, portarray, INIT_PORT_MAX, NULL, 0); + + arrange_shutdown_notification (); + return 0; +} + kern_return_t trivfs_S_fsys_startup (mach_port_t bootport, mach_port_t reply, @@ -193,6 +235,8 @@ trivfs_S_fsys_startup (mach_port_t bootport, mach_port_t *realnode, mach_msg_type_name_t *realnodetype) { + machdev_ctl = cntl; + *realnode = MACH_PORT_NULL; *realnodetype = MACH_MSG_TYPE_MOVE_SEND; return 0; @@ -316,6 +360,7 @@ demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) if ((routine = device_server_routine (inp)) || (routine = notify_server_routine (inp)) || (routine = mach_i386_server_routine (inp)) || + (routine = startup_notify_server_routine (inp)) || (routine = NULL, trivfs_demuxer (inp, outp))) { if (routine) diff --git a/libmachdev/trivfs_server.h b/libmachdev/trivfs_server.h new file mode 100644 index 00000000..908feaf6 --- /dev/null +++ b/libmachdev/trivfs_server.h @@ -0,0 +1,30 @@ +/* + Copyright (C) 2020 Free Software Foundation, Inc. + + The GNU Hurd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The GNU Hurd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _TRIVFS_SERVER_H +#define _TRIVFS_SERVER_H + +#include <hurd/ports.h> +#include <hurd/trivfs.h> +#include <hurd.h> + +extern struct port_bucket *port_bucket; +extern struct port_class *trivfs_protid_class; +extern struct port_class *trivfs_cntl_class; + +#endif + diff --git a/rumpdisk/block-rump.c b/rumpdisk/block-rump.c index 474852cd..e094a199 100644 --- a/rumpdisk/block-rump.c +++ b/rumpdisk/block-rump.c @@ -151,6 +151,19 @@ device_dealloc (void *d) rump_sys_reboot (0, NULL); } +static void +device_shutdown (void) +{ + struct block_data *bd = block_head; + + while (bd) + { + device_close((void *)bd); + bd = bd->next; + } + rump_sys_reboot (0, NULL); +} + static io_return_t device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, dev_mode_t mode, char *name, device_t * devp, @@ -360,7 +373,8 @@ static struct machdev_device_emulation_ops rump_block_emulation_ops = { NULL, NULL, NULL, - NULL + NULL, + device_shutdown }; void -- 2.25.1