diff options
author | Sergiu Ivanov <unlimitedscolobb@gmail.com> | 2009-04-13 01:03:40 +0300 |
---|---|---|
committer | Sergiu Ivanov <unlimitedscolobb@gmail.com> | 2009-04-13 01:03:40 +0300 |
commit | c9110f9c7d71fa9b157540a7aa2ade7f34b79968 (patch) | |
tree | 86723a412757f6d44ac60e8efec921fd14777987 | |
parent | 0a5fcd403943fbbdc0a2ba35283f1135f97c48dc (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.c | 10 | ||||
-rw-r--r-- | node.h | 8 | ||||
-rw-r--r-- | nsmux.c | 91 | ||||
-rw-r--r-- | nsmux.h | 4 | ||||
-rw-r--r-- | trans.c | 4 | ||||
-rw-r--r-- | trans.h | 8 |
6 files changed, 112 insertions, 13 deletions
@@ -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 @@ -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 */ @@ -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) { @@ -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__*/ @@ -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 */ @@ -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 |