>From 92d45847b0c625b5bbb4b44e8f82494fc5551d02 Mon Sep 17 00:00:00 2001 From: Sergiu Ivanov <unlimitedscol...@gmail.com> Date: Thu, 16 Jul 2009 11:23:37 +0000 Subject: [PATCH 3/4] Conditionally forward some fsys_* RPCs to the mountee.
* mount.c (shutting_down): New variable. (mountee_server): Attempt to shutdown unionfs only it it is not already shutting down. Set shutting_down to 1 before shutting down unionfs. * mount.h (shutting_down): New variable. * netfs.c (netfs_append_args): Forward fsys_get_options to the mountee if unionmount is transparent. (netfs_set_options): New function. (netfs_attempt_syncfs): Forward fsys_syncfs to the mountee if unionmount is transparent. (netfs_shutdown): New function. * node.c (node_ulfs_free): Don't destroy the port to the mountee. --- mount.c | 9 +++++- mount.h | 3 ++ netfs.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ node.c | 2 +- 4 files changed, 116 insertions(+), 2 deletions(-) diff --git a/mount.c b/mount.c index 26cbd9f..4d0a0d4 100644 --- a/mount.c +++ b/mount.c @@ -46,6 +46,9 @@ int mountee_started = 0; operates (transparent/non-transparent). */ int transparent_mount = 1; +/* Shows whether unionmount is shutting down. */ +int shutting_down = 0; + /* The port for receiving the notification about the shutdown of the mountee. */ mach_port_t mountee_listen_port; @@ -192,8 +195,12 @@ start_mountee (node_t * np, char * argz, size_t argz_len, int flags, error_t mountee_server (mach_msg_header_t * inp, mach_msg_header_t * outp) { - if (inp->msgh_id == MACH_NOTIFY_DEAD_NAME) + /* If `shutting_down` is set, the mountee has just been shut down by + netfs_shutdown and unionfs is on its way to going away. */ + if (!shutting_down && (inp->msgh_id == MACH_NOTIFY_DEAD_NAME)) { + shutting_down = 1; + /* Terminate operations conducted by unionfs and shut down. */ netfs_shutdown (FSYS_GOAWAY_FORCE); exit (0); diff --git a/mount.h b/mount.h index fd8408b..ebbfa93 100644 --- a/mount.h +++ b/mount.h @@ -45,6 +45,9 @@ extern int mountee_started; operates (transparent/non-transparent). */ extern int transparent_mount; +/* Shows whether unionmount is shutting down. */ +extern int shutting_down; + /* Starts the mountee (given by `argz` and `argz_len`), sets it on node `np` and opens a port `port` to with `flags`. `port` is not modified when an error occurs. */ diff --git a/netfs.c b/netfs.c index fc2572f..7e81771 100644 --- a/netfs.c +++ b/netfs.c @@ -33,6 +33,7 @@ #include <stdio.h> #include <hurd/paths.h> #include <sys/mman.h> +#include <hurd/fsys.h> #include "unionfs.h" #include "ulfs.h" @@ -50,6 +51,36 @@ netfs_append_args (char **argz, size_t *argz_len) { error_t err = 0; + if (transparent_mount) + { + /* We need to receive the mountee's arguments into a local + buffer first, because in the case of an error + netfs_S_fsys_get_options will try to free `*argz`, which + might have already been freed in the mountee. + + The ``static'' bit is required because fsys_get_options + returns an mmapped region. */ + static char * m_argz = NULL; + static size_t m_argz_len; + + /* Forward this RPC directly to the mountee. */ + err = fsys_get_options (mountee_control, &m_argz, &m_argz_len); + if (err) + return err; + + /* netfs_S_fsys_get_options has already malloced `*argz` for us, + we will copy `m_argz` into it, because netfs_append_args is + expected to return a malloced buffer, while fsys_get_options + returns an mmapped buffer. */ + *argz = realloc (*argz, m_argz_len); + if(!*argz) + return ENOMEM; + memcpy (*argz, m_argz, m_argz_len); + *argz_len = m_argz_len; + + return 0; + } + /* Add the --mount or --no-mount option to the result. */ if (mountee_argz) { @@ -108,6 +139,24 @@ netfs_append_args (char **argz, size_t *argz_len) return err; } +error_t +netfs_set_options (char *argz, size_t argz_len) +{ + if (transparent_mount) + { + error_t err; + + /* Forward this RPC directly to the mountee. */ + err = fsys_set_options (mountee_control, argz, argz_len, 0); + return err; + } + + if (netfs_runtime_argp) + return fshelp_set_options (netfs_runtime_argp, 0, argz, argz_len, 0); + else + return EOPNOTSUPP; +} + #ifndef __USE_FILE_OFFSET64 #define OFFSET_T __off_t /* Size in bytes. */ #else @@ -318,6 +367,61 @@ netfs_attempt_sync (struct iouser *cred, struct node *np, error_t netfs_attempt_syncfs (struct iouser *cred, int wait) { + error_t err = 0; + + if (transparent_mount) + { + /* Sync the mountee (and its children, too). */ + err = fsys_syncfs (mountee_control, wait, 1); + } + + return err; +} + +/* Shutdown the filesystem; flags are as for fsys_goaway. */ +error_t +netfs_shutdown (int flags) +{ + int nports; + int err; + + if ((flags & FSYS_GOAWAY_UNLINK) + && S_ISDIR (netfs_root_node->nn_stat.st_mode)) + return EBUSY; + + /* Permit all current RPC's to finish, and then suspend any new ones. */ + err = ports_inhibit_class_rpcs (netfs_protid_class); + if (err) + 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); + + return EBUSY; + } + + if (!(flags & FSYS_GOAWAY_NOSYNC)) + { + err = netfs_attempt_syncfs (0, flags); + if (err) + return err; + } + + /* If `shutting_down` is set, unionfs is going away because the + mounee has just died, so we don't need to attempt to shut it + down. */ + if (!shutting_down) + { + shutting_down = 1; + err = fsys_goaway (mountee_control, flags); + if (err) + return err; + } + return 0; } diff --git a/node.c b/node.c index d9f26ba..9d86872 100644 --- a/node.c +++ b/node.c @@ -336,7 +336,7 @@ node_ulfs_free (node_t *node) node_ulfs_iterate_unlocked (node) { if (port_valid (node_ulfs->port) - && node_ulfs->port != underlying_node) + && (node_ulfs->port != underlying_node) && (node_ulfs->port != mountee_port)) port_dealloc (node_ulfs->port); } -- 1.6.3.3