bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 3/4] libmachdev: Introduce startup notification for clean rumpdis


From: Damien Zammit
Subject: [PATCH 3/4] libmachdev: Introduce startup notification for clean rumpdisk shutdown
Date: Tue, 28 Jul 2020 20:08:36 +1000

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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]