[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 3/4] Conditionally forward some fsys_* RPCs to the mountee.
From: |
Sergiu Ivanov |
Subject: |
[PATCH 3/4] Conditionally forward some fsys_* RPCs to the mountee. |
Date: |
Fri, 17 Jul 2009 13:58:01 +0300 |
User-agent: |
Mutt/1.5.18 (2008-05-17) |
>From 92d45847b0c625b5bbb4b44e8f82494fc5551d02 Mon Sep 17 00:00:00 2001
From: Sergiu Ivanov <unlimitedscolobb@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