summaryrefslogtreecommitdiff
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
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
-rw-r--r--node.c10
-rw-r--r--node.h8
-rw-r--r--nsmux.c91
-rw-r--r--nsmux.h4
-rw-r--r--trans.c4
-rw-r--r--trans.h8
6 files changed, 112 insertions, 13 deletions
diff --git a/node.c b/node.c
index 778a73be5..a7c85fd4c 100644
--- a/node.c
+++ b/node.c
@@ -98,7 +98,7 @@ error_t node_create (lnode_t * lnode, node_t ** node)
/*initialize the data fields dealing with positioning this node
in the dynamic translator stack */
- node_new->nn->trans_cntl = MACH_PORT_NULL;
+ node_new->nn->dyntrans = NULL;
node_new->nn->below = NULL;
/*store the result of creation in the second parameter */
@@ -155,7 +155,7 @@ error_t node_create_proxy (lnode_t * lnode, node_t ** node)
/*initialize the data fields dealing with positioning this node
in the dynamic translator stack */
- node_new->nn->trans_cntl = MACH_PORT_NULL;
+ node_new->nn->dyntrans = NULL;
node_new->nn->below = NULL;
/*store the result of creation in the second parameter */
@@ -214,7 +214,7 @@ error_t node_create_from_port (mach_port_t port, node_t ** node)
/*initialize the data fields dealing with positioning this node
in the dynamic translator stack */
- node_new->nn->trans_cntl = MACH_PORT_NULL;
+ node_new->nn->dyntrans = NULL;
node_new->nn->below = NULL;
/*store the result of creation in the second parameter */
@@ -913,8 +913,8 @@ error_t
if (err)
return err;
- /*Store the current control port in the new supplied shadow node */
- np->nn->trans_cntl = active_control;
+ /*Register the new translator*/
+ err = trans_register (active_control, &np->nn->dyntrans);
/*Obtain the port to the top of the newly-set translator */
err = fsys_getroot
diff --git a/node.h b/node.h
index 72adcbebb..d930a3b69 100644
--- a/node.h
+++ b/node.h
@@ -32,6 +32,7 @@
#include <hurd/netfs.h>
/*---------------------------------------------------------------------------*/
#include "lnode.h"
+#include "trans.h"
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
@@ -74,9 +75,10 @@ struct netnode
/*a port to the underlying filesystem */
file_t port;
- /*the control port of the translator sitting on this node, in case
- this node is a shadow node */
- fsys_t trans_cntl;
+ /*a reference to the element in the list of dynamic translators
+ corresponding to the translator sitting on this node, in case this
+ node is a shadow node */
+ struct trans_el * dyntrans;
/*the reference to the shadow node that is below the current shadow
node in the dynamic translator stack */
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)
{
diff --git a/nsmux.h b/nsmux.h
index 8c6082fd1..38cf8c810 100644
--- a/nsmux.h
+++ b/nsmux.h
@@ -238,4 +238,8 @@ kern_return_t
netfs_S_file_get_translator_cntl
(struct protid *user, mach_port_t * cntl, mach_msg_type_name_t * cntltype);
/*---------------------------------------------------------------------------*/
+/* Shutdown the filesystem; flags are as for fsys_goaway. */
+error_t
+netfs_shutdown (int flags);
+/*---------------------------------------------------------------------------*/
#endif /*__NSMUX_H__*/
diff --git a/trans.c b/trans.c
index 8d05286ce..4b77f473d 100644
--- a/trans.c
+++ b/trans.c
@@ -42,7 +42,7 @@ trans_el_t * dyntrans = NULL;
/*Adds a translator control port to the list of ports. One should use
only this function to add a new element to the list of ports. */
error_t
-trans_register (mach_port_t cntl)
+trans_register (fsys_t cntl, trans_el_t ** new_trans)
{
/*The new entry in the list */
trans_el_t * el;
@@ -57,6 +57,8 @@ trans_register (mach_port_t cntl)
el->next = dyntrans;
dyntrans = el;
+ *new_trans = el;
+
return 0;
} /*trans_register */
diff --git a/trans.h b/trans.h
index 86e21c9d6..e28060f5e 100644
--- a/trans.h
+++ b/trans.h
@@ -21,8 +21,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.*/
/*---------------------------------------------------------------------------*/
-#ifndef __DEBUG_H__
-#define __DEBUG_H__
+#ifndef __TRANS_H__
+#define __TRANS_H__
/*---------------------------------------------------------------------------*/
#include <hurd.h>
@@ -35,7 +35,7 @@
struct trans_el
{
/*the control port to the translator */
- mach_port_t cntl;
+ fsys_t cntl;
/*the next and the previous elements in the list */
struct trans_el * next, * prev;
@@ -55,7 +55,7 @@ extern trans_el_t * dyntrans;
/*Adds a translator control port to the list of ports. One should use
only this function to add a new element to the list of ports. */
error_t
-trans_register (mach_port_t cntl);
+trans_register (fsys_t cntl, trans_el_t ** new_trans);
/*---------------------------------------------------------------------------*/
/*Removes a translator control port from the list of ports. One should
use only this function to remove an element from the list of