summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2020-08-01 15:05:38 +1000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2020-08-02 23:33:36 +0200
commit49eae3b568ca925e9f0f928f8fb6dd8457d7d0b0 (patch)
tree7d54b9ff7c9fafa3e70960d12f0a98c957a815dd
parent304adff10d5bdeeb618a6633e3b80e51aa4585c6 (diff)
libmachdev: Introduce startup notification for clean rumpdisk shutdown
Message-Id: <20200801050538.273196-1-damien@zamaudio.com>
-rw-r--r--libmachdev/Makefile4
-rw-r--r--libmachdev/ds_routines.c10
-rw-r--r--libmachdev/machdev-device_emul.h1
-rw-r--r--libmachdev/machdev.h1
-rw-r--r--libmachdev/trivfs_server.c118
-rw-r--r--libmachdev/trivfs_server.h33
-rw-r--r--rumpdisk/block-rump.c16
7 files changed, 177 insertions, 6 deletions
diff --git a/libmachdev/Makefile b/libmachdev/Makefile
index 15b98cf1..3cd278f2 100644
--- a/libmachdev/Makefile
+++ b/libmachdev/Makefile
@@ -19,10 +19,10 @@ dir := libmachdev
makemode := library
libname = libmachdev
-SRCS = ds_routines.c trivfs_server.c \
+SRCS = ds_routines.c trivfs_server.c startup_notifyServer.c \
deviceServer.c notifyServer.c mach_i386Server.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 trivfs_server.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/trivfs_server.c b/libmachdev/trivfs_server.c
index eec8585e..c5407145 100644
--- a/libmachdev/trivfs_server.c
+++ b/libmachdev/trivfs_server.c
@@ -21,21 +21,30 @@
/* This manages the master ports obtained when opening the libmachdev-based
translator node. */
+#include <unistd.h>
#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/paths.h>
+#include <hurd/startup.h>
#include <hurd.h>
#include <device/device.h> /* mach console */
#include "libdiskfs/diskfs.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;
+#include "trivfs_server.h"
+#include "libmachdev/machdev.h"
+
+struct port_bucket *port_bucket;
/* Trivfs hooks. */
int trivfs_fstype = FSTYPE_MISC;
@@ -49,6 +58,14 @@ 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;
+
+/* Startup and shutdown notifications management */
+struct port_class *machdev_shutdown_notify_class;
+
+static void arrange_shutdown_notification (void);
+
/* Implementation of notify interface */
kern_return_t
do_mach_notify_port_deleted (struct port_info *pi,
@@ -183,7 +200,6 @@ 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_startup (mach_port_t bootport,
mach_port_t reply,
@@ -193,11 +209,88 @@ 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;
}
+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;
+}
+
+static void
+arrange_shutdown_notification (void)
+{
+ 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);
+}
+
/* Override the privileged ports for booting the system */
kern_return_t
trivfs_S_fsys_getpriv (struct diskfs_control *init_bootstrap_port,
@@ -260,7 +353,7 @@ resume_bootstrap_server(mach_port_t server_task, const char *server_name)
stdout = stderr = mach_open_devstream (cons, "w");
mach_port_deallocate (mach_task_self (), cons);
- printf (" %s", server_name);
+ printf ("Hurd bootstrap %s ", server_name);
fflush (stdout);
}
@@ -286,6 +379,24 @@ machdev_trivfs_init(mach_port_t bootstrap_resume_task, const char *name, mach_po
return 0;
}
+/* 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);
+}
+
error_t
trivfs_goaway (struct trivfs_control *fsys, int flags)
{
@@ -316,6 +427,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..ae30a830
--- /dev/null
+++ b/libmachdev/trivfs_server.h
@@ -0,0 +1,33 @@
+/*
+ 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 _MACHDEV_TRIVFS_SERVER_H
+#define _MACHDEV_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;
+extern struct port_class *machdev_shutdown_notify_class;
+
+void arrange_shutdown_notification (void);
+
+#endif /* _MACHDEV_TRIVFS_SERVER_H */
+
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