summaryrefslogtreecommitdiff
path: root/nsmux.c
diff options
context:
space:
mode:
authorSergiu Ivanov <unlimitedscolobb@gmail.com>2009-04-13 01:03:40 +0300
committerSergiu Ivanov <unlimitedscolobb@gmail.com>2009-04-13 01:03:40 +0300
commitc9110f9c7d71fa9b157540a7aa2ade7f34b79968 (patch)
tree86723a412757f6d44ac60e8efec921fd14777987 /nsmux.c
parent0a5fcd403943fbbdc0a2ba35283f1135f97c48dc (diff)
nsmux can shutdown all dynamic translators on exit
Now nsmux can shutdown all of its dynamic translators on exit, thus doing sufficient cleanup. One can tell nsmux to shutdown dynamic translators using the ``--recursive'' option to settrans. Note that because fsys_goaway returns immediately as the RPC is processed, while the receiver may still remain in memory, doing something like settrans -g --recursive foo where nsmux is sitting on foo will almost always result in a ``Server busy'' error message. The reason is that libnetfs counts how many open ports to its nodes there are at shutdown and in most cases it does the check *before* the dynamic translators manage to drop their references. Therefore, the aforementioned command gracefully kills all dynamic translators. Invoked the second time, this command will shutdown nsmux, too. Immediate shutdown with killing dynamic translators can be achieved via settrans -gf --recursive foo
Diffstat (limited to 'nsmux.c')
-rw-r--r--nsmux.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/nsmux.c b/nsmux.c
index 9e5d28a4e..2eb539e07 100644
--- a/nsmux.c
+++ b/nsmux.c
@@ -34,6 +34,7 @@
#include <hurd/netfs.h>
#include <fcntl.h>
#include <hurd/paths.h>
+#include <hurd/fsys.h>
/*---------------------------------------------------------------------------*/
#include "debug.h"
#include "options.h"
@@ -1640,6 +1641,96 @@ kern_return_t
} /*netfs_S_file_get_translator_cntl */
/*---------------------------------------------------------------------------*/
+/* Shutdown the filesystem; flags are as for fsys_goaway. */
+error_t
+netfs_shutdown (int flags)
+{
+ error_t
+ helper (struct node *node)
+ {
+ error_t err;
+ mach_port_t control;
+
+ err = fshelp_fetch_control (&node->transbox, &control);
+ if (!err && (control != MACH_PORT_NULL))
+ {
+ mutex_unlock (&node->lock);
+ err = fsys_goaway (control, flags);
+ mach_port_deallocate (mach_task_self (), control);
+ mutex_lock (&node->lock);
+ }
+ else
+ err = 0;
+
+ if ((err == MIG_SERVER_DIED) || (err == MACH_SEND_INVALID_DEST))
+ err = 0;
+
+ return err;
+ }
+
+ int nports;
+ int err;
+
+ if ((flags & FSYS_GOAWAY_UNLINK)
+ && S_ISDIR (netfs_root_node->nn_stat.st_mode))
+ return EBUSY;
+
+ if (flags & FSYS_GOAWAY_NOWAIT)
+ LOG_MSG("NOWAIT");
+ LOG_MSG("WAIT");
+
+ if (flags & FSYS_GOAWAY_RECURSE)
+ {
+ /*nsmux has been requested shut down recursively. Shut down all
+ dynamic translators. Statically set translators will not be
+ shut down, because libnetfs does not (yet?) do this itself, as
+ different from libdiskfs. */
+ err = trans_shutdown_all (flags);
+
+#ifdef NOTYET
+ err = netfs_node_iterate (helper);
+#endif
+ if (err)
+ return err;
+ }
+
+#ifdef NOTYET
+ rwlock_writer_lock (&netfs_fsys_lock);
+#endif
+
+ /* Permit all current RPC's to finish, and then suspend any new ones. */
+ err = ports_inhibit_class_rpcs (netfs_protid_class);
+ if (err)
+ {
+#ifdef NOTYET
+ rwlock_writer_unlock (&netfs_fsys_lock);
+#endif
+ return err;
+ }
+
+ nports = ports_count_class (netfs_protid_class);
+ if (((flags & FSYS_GOAWAY_FORCE) == 0) && nports)
+ /* There are outstanding user ports; resume operations. */
+ {
+ ports_enable_class (netfs_protid_class);
+ ports_resume_class_rpcs (netfs_protid_class);
+#ifdef NOTYET
+ rwlock_writer_unlock (&netfs_fsys_lock);
+#endif
+ return EBUSY;
+ }
+
+ if (!(flags & FSYS_GOAWAY_NOSYNC))
+ {
+ err = netfs_attempt_syncfs (0, flags);
+ if (err)
+ return err;
+ }
+
+ return 0;
+} /*netfs_shutdown */
+
+/*---------------------------------------------------------------------------*/
/*Entry point*/
int main (int argc, char **argv)
{