commit-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[hurd] 01/02: New upstream snapshot


From: Samuel Thibault
Subject: [hurd] 01/02: New upstream snapshot
Date: Sun, 19 Nov 2017 15:27:16 +0000

This is an automated email from the git hooks/post-receive script.

sthibault pushed a commit to branch master
in repository hurd.

commit 9ae7e004beec6f582e23ce537f742261af8f0f1d
Author: Samuel Thibault <address@hidden>
Date:   Sun Nov 19 13:23:11 2017 +0000

    New upstream snapshot
---
 eth-multiplexer/device_impl.c                      |   9 +-
 eth-multiplexer/util.h                             |   6 +-
 eth-multiplexer/vdev.c                             |  45 ++--
 eth-multiplexer/vdev.h                             |  11 +-
 hurd/fs.defs                                       |  20 +-
 hurd/fsys.defs                                     |  25 +-
 libdiskfs/Makefile                                 |   2 +-
 libdiskfs/dir-lookup.c                             |  72 +++---
 libdiskfs/file-get-children.c                      |  96 --------
 libdiskfs/file-set-trans.c                         |   2 +-
 libdiskfs/file-syncfs.c                            |  35 ++-
 libdiskfs/fsys-get-children.c                      |  74 ++++++
 libdiskfs/{file-get-source.c => fsys-get-source.c} |  26 +-
 libdiskfs/fsys-options.c                           |  44 ++--
 libdiskfs/fsys-syncfs.c                            |  33 ++-
 libdiskfs/init-main.c                              |   2 +-
 libdiskfs/init-startup.c                           |  34 +--
 libdiskfs/shutdown.c                               |  45 ++--
 libfshelp/fetch-control.c                          |   6 +-
 libfshelp/fshelp.h                                 |  30 ++-
 libfshelp/translator-list.c                        | 200 +++++++++------
 libnetfs/Makefile                                  |   8 +-
 libnetfs/dir-lookup.c                              |  80 +++---
 libnetfs/file-get-children.c                       | 108 ---------
 libnetfs/file-set-translator.c                     |   2 +-
 libnetfs/file-syncfs.c                             |  23 +-
 libnetfs/fsys-get-children.c                       |  74 ++++++
 libnetfs/{file-get-source.c => fsys-get-source.c}  |  24 +-
 libnetfs/fsys-set-options.c                        |  53 ++--
 libnetfs/fsys-syncfs.c                             |  22 ++
 libnetfs/shutdown.c                                |  45 ++--
 libtrivfs/Makefile                                 |   5 +-
 libtrivfs/file-get-children.c                      |  36 ---
 libtrivfs/fsys-get-children.c                      |  41 ++++
 libtrivfs/{file-get-source.c => fsys-get-source.c} |  22 +-
 pfinet/iioctl-ops.c                                |   2 +-
 pfinet/linux-src/net/ipv4/udp.c                    |  27 +--
 pflocal/Makefile                                   |   2 +
 pflocal/fs.c                                       | 267 ---------------------
 pflocal/io.c                                       | 109 ---------
 trans/Makefile                                     |   2 +-
 trans/mtab.c                                       | 225 +++++++----------
 utils/devprobe.c                                   |  13 +
 43 files changed, 774 insertions(+), 1233 deletions(-)

diff --git a/eth-multiplexer/device_impl.c b/eth-multiplexer/device_impl.c
index d7c8bee..3be4fb5 100644
--- a/eth-multiplexer/device_impl.c
+++ b/eth-multiplexer/device_impl.c
@@ -33,9 +33,6 @@
 #include "netfs_impl.h"
 #include "util.h"
 
-extern struct port_bucket *port_bucket;
-extern struct port_class *vdev_portclass;
-extern struct port_class *other_portclass;
 extern struct port_info *notify_pi;
 
 /* Implementation of device interface */
@@ -60,15 +57,11 @@ ds_device_open (mach_port_t master_port, mach_port_t 
reply_port,
    * create it now. */
   if (pi->po->np->nn->ln == NULL)
     {
-      extern struct port_bucket *port_bucket;
-      extern struct port_class *vdev_portclass;
       extern struct stat underlying_node_stat;
       static int ino_count = 0;
       /* Create a new light node (virtual device). */
       struct lnode *ln = (struct lnode *) add_vdev (pi->po->np->nn->name,
-                                                   sizeof (*ln),
-                                                   vdev_portclass,
-                                                   port_bucket);
+                                                   sizeof (*ln));
       if (ln == NULL)
        {
          ports_port_deref (pi);
diff --git a/eth-multiplexer/util.h b/eth-multiplexer/util.h
index 1e062c4..e1b6885 100644
--- a/eth-multiplexer/util.h
+++ b/eth-multiplexer/util.h
@@ -36,9 +36,9 @@
 
 #define debug(format, ...) do                          \
 {                                                      \
-  char buf[1024];                                       \
-  snprintf (buf, 1024, "multiplexer: %s: %s\n", __func__, format);       \
-  fprintf (stderr , buf, ## __VA_ARGS__);              \
+  fprintf (stderr, "eth-multiplexer: %s: ", __func__);  \
+  fprintf (stderr, format, ## __VA_ARGS__);            \
+  fprintf (stderr, "\n");                               \
   fflush (stderr);                                     \
 } while (0)
 
diff --git a/eth-multiplexer/vdev.c b/eth-multiplexer/vdev.c
index 9a1f7b2..367623d 100644
--- a/eth-multiplexer/vdev.c
+++ b/eth-multiplexer/vdev.c
@@ -125,8 +125,7 @@ remove_dead_port_from_dev (mach_port_t dead_port)
 
 /* Add a new virtual interface to the multiplexer. */
 struct vether_device *
-add_vdev (char *name, int size,
-         struct port_class *class, struct port_bucket *bucket)
+add_vdev (char *name, size_t size)
 {
   error_t err;
   uint32_t hash;
@@ -134,7 +133,7 @@ add_vdev (char *name, int size,
 
   if (size < sizeof (*vdev))
     size = sizeof (*vdev);
-  err = ports_create_port (class, bucket, size, &vdev);
+  err = ports_create_port (vdev_portclass, port_bucket, size, &vdev);
   if (err)
     return NULL;
 
@@ -194,36 +193,13 @@ destroy_vdev (void *port)
   destroy_filters (&vdev->port_list);
 }
 
-/* Test if there are devices existing in the list */
-int
-has_vdev ()
-{
-  return dev_head != NULL;
-}
+static int deliver_msg (struct net_rcv_msg *msg, struct vether_device *vdev);
 
 /* Broadcast the packet to all virtual interfaces
  * except the one the packet is from */
 int
 broadcast_pack (char *data, int datalen, struct vether_device *from_vdev)
 {
-  int internal_deliver_pack (struct vether_device *vdev)
-    {
-      /* Skip current interface.  */
-      if (from_vdev == vdev)
-       return 0;
-      /* Skip interfaces that are down.  */
-      if ((vdev->if_flags & IFF_UP) == 0)
-        return 0;
-      return deliver_pack (data, datalen, vdev);
-    }
-
-  return foreach_dev_do (internal_deliver_pack);
-}
-
-/* Create a message, and deliver it. */
-int
-deliver_pack (char *data, int datalen, struct vether_device *vdev)
-{
   struct net_rcv_msg msg;
   int pack_size;
   struct ethhdr *header;
@@ -244,7 +220,18 @@ deliver_pack (char *data, int datalen, struct 
vether_device *vdev)
   packet->length = pack_size + sizeof (struct packet_header);
   msg.packet_type.msgt_number = packet->length;
 
-  return deliver_msg (&msg, vdev);
+  int internal_deliver_pack (struct vether_device *vdev)
+    {
+      /* Skip current interface.  */
+      if (from_vdev == vdev)
+       return 0;
+      /* Skip interfaces that are down.  */
+      if ((vdev->if_flags & IFF_UP) == 0)
+        return 0;
+      return deliver_msg (&msg, vdev);
+    }
+
+  return foreach_dev_do (internal_deliver_pack);
 }
 
 /* Broadcast the message to all virtual interfaces. */
@@ -273,7 +260,7 @@ broadcast_msg (struct net_rcv_msg *msg)
  * Deliver the message to all right pfinet servers that
  * connects to the virtual network interface.
  */
-int
+static int
 deliver_msg(struct net_rcv_msg *msg, struct vether_device *vdev)
 {
   mach_msg_return_t err;
diff --git a/eth-multiplexer/vdev.h b/eth-multiplexer/vdev.h
index 3c3c320..8270fed 100644
--- a/eth-multiplexer/vdev.h
+++ b/eth-multiplexer/vdev.h
@@ -33,7 +33,9 @@
 #include "queue.h"
 #include "util.h"
 
-#define MAX_SERVERS 10
+struct port_bucket *port_bucket;
+struct port_class *vdev_portclass;
+
 #define ETH_MTU 1500
 
 struct vether_device
@@ -63,13 +65,8 @@ int serv_connect (mach_port_t port);
 int serv_disconnect ();
 struct vether_device *lookup_dev_by_name (char *name);
 int remove_dead_port_from_dev (mach_port_t dead_port);
-struct vether_device *add_vdev (char *name, int size,
-                               struct port_class *class,
-                               struct port_bucket *bucket);
+struct vether_device *add_vdev (char *name, size_t size);
 void destroy_vdev (void *port);
-int has_vdev ();
-int deliver_msg (struct net_rcv_msg *msg, struct vether_device *vdev);
-int deliver_pack (char *data, int datalen, struct vether_device *vdev);
 boolean_t all_dev_close ();
 int broadcast_pack (char *data, int datalen, struct vether_device *from_vdev);
 int broadcast_msg (struct net_rcv_msg *msg);
diff --git a/hurd/fs.defs b/hurd/fs.defs
index a4a48cc..6c0b573 100644
--- a/hurd/fs.defs
+++ b/hurd/fs.defs
@@ -353,21 +353,5 @@ routine file_reparent (
        parent: mach_port_t;
        out new_file: mach_port_send_t);
 
-/* Return any active translators bound to nodes below FILE.  CHILDREN
-   is an argz vector containing file names relative to the path of
-   FILE.  */
-routine file_get_children (
-       file: file_t;
-       RPT
-       out children: data_t);
-
-/* Return information about the source of FILE.  If the concept of a
-   source is applicable, SOURCE should refer to the source of FILE and
-   should be a description considered appropriate in the context of
-   the translator.  For example, if FILE refers to a node on a
-   filesystems, SOURCE should be the file name of the underlying block
-   device.  */
-routine file_get_source (
-       file: file_t;
-       RPT
-       out source: string_t);
+skip;  /* Was: file_get_children.  */
+skip;  /* Was: file_get_source.  */
diff --git a/hurd/fsys.defs b/hurd/fsys.defs
index b36b944..35d483c 100644
--- a/hurd/fsys.defs
+++ b/hurd/fsys.defs
@@ -128,5 +128,26 @@ routine fsys_get_options (
        RPT
        out options: data_t, dealloc);
 
-skip;  /* Was fsys_get_children */
-skip;  /* Was fsys_get_source */
+/* Return any active child translators.  NAMES is an argz vector
+   containing file names relative to the root of the translator.
+   CONTROLS is an array containing the corresponding control ports.
+   Note that translators are bound to nodes, and nodes can have zero
+   or more links in the file system, therefore there is no guarantee
+   that a translators name refers to an existing link in the file
+   system.  */
+routine fsys_get_children (
+       server: fsys_t;
+       RPT
+       out names: data_t;
+       out controls: portarray_t);
+
+/* Return information about the source of the translator.  If the
+   concept of a source is applicable, SOURCE should refer to the
+   source of the translator and should be a description considered
+   appropriate in the context of the translator.  For example, if the
+   translator is a filesystem residing on a block device, then SOURCE
+   should be the file name of the underlying block device.  */
+routine fsys_get_source (
+       server: fsys_t;
+       RPT
+       out source: string_t);
diff --git a/libdiskfs/Makefile b/libdiskfs/Makefile
index 93c96fa..5716ac5 100644
--- a/libdiskfs/Makefile
+++ b/libdiskfs/Makefile
@@ -35,7 +35,7 @@ IOSRCS= io-async-icky.c io-async.c io-duplicate.c 
io-get-conch.c io-revoke.c \
        io-select.c io-stat.c io-stubs.c io-write.c io-version.c io-sigio.c
 FSYSSRCS=fsys-getroot.c fsys-goaway.c fsys-startup.c fsys-getfile.c \
        fsys-options.c fsys-syncfs.c fsys-forward.c \
-       file-get-children.c file-get-source.c
+       fsys-get-children.c fsys-get-source.c
 IFSOCKSRCS=ifsock.c
 OTHERSRCS = conch-fetch.c conch-set.c dir-clear.c dir-init.c dir-renamed.c \
        extern-inline.c \
diff --git a/libdiskfs/dir-lookup.c b/libdiskfs/dir-lookup.c
index 3c7198f..eafeefc 100644
--- a/libdiskfs/dir-lookup.c
+++ b/libdiskfs/dir-lookup.c
@@ -249,13 +249,6 @@ diskfs_S_dir_lookup (struct protid *dircred,
          if (np != dnp)
            pthread_mutex_unlock (&dnp->lock);
 
-         /* Check if an active translator is currently running.  If
-            not, fshelp_fetch_root will start one.  In that case, we
-            need to register it in the list of active
-            translators.  */
-         boolean_t register_translator =
-           np->transbox.active == MACH_PORT_NULL;
-
          struct fshelp_stat_cookie2 cookie = {
            .statp = &np->dn_stat,
            .modep = &np->dn_stat.st_mode,
@@ -291,36 +284,43 @@ diskfs_S_dir_lookup (struct protid *dircred,
                  }
                }
 
-             if (register_translator)
-               {
-                 char *translator_path = strdupa (relpath);
-                 char *complete_path;
-                 if (nextname != NULL)
-                   {
-                     /* This was not the last path component.
-                        NEXTNAME points to the next component, locate
-                        the end of the current component and use it
-                        to trim TRANSLATOR_PATH.  */
-                     char *end = nextname;
-                     while (*end != 0)
-                       end--;
-                     translator_path[end - filename_start] = '\0';
-                   }
+             {
+               char *translator_path = strdupa (relpath);
+               char *end;
+               char *complete_path;
+               if (nextname != NULL)
+                 {
+                   /* This was not the last path component.
+                      NEXTNAME points to the next component, locate
+                      the end of the current component and use it
+                      to trim TRANSLATOR_PATH.  */
+                   end = nextname;
+                   while (*end != 0)
+                     end--;
+                   translator_path[end - filename_start] = '\0';
+                 }
 
-                 if (dircred->po->path == NULL || !strcmp 
(dircred->po->path,"."))
-                     /* dircred is the root directory.  */
-                     complete_path = translator_path;
-                 else
-                     asprintf (&complete_path, "%s/%s", dircred->po->path, 
translator_path);
-
-                 err = fshelp_set_active_translator (&newpi->pi,
-                                                       complete_path,
-                                                       np->transbox.active);
-                 if (complete_path != translator_path)
-                   free(complete_path);
-                 if (err)
-                   goto out;
-               }
+               /* Trim trailing slashes.  */
+               end = &translator_path[strlen (translator_path) - 1];
+               while (*end == '/' && end >= translator_path)
+                 *end = '\0', end--;
+
+               if (dircred->po->path == NULL
+                   || !strcmp (dircred->po->path,"."))
+                 /* dircred is the root directory.  */
+                 complete_path = translator_path;
+               else
+                 asprintf (&complete_path, "%s/%s", dircred->po->path,
+                           translator_path);
+
+               err = fshelp_set_active_translator (&newpi->pi,
+                                                   complete_path,
+                                                   &np->transbox);
+               if (complete_path != translator_path)
+                 free(complete_path);
+               if (err)
+                 goto out;
+             }
 
              goto out;
            }
diff --git a/libdiskfs/file-get-children.c b/libdiskfs/file-get-children.c
deleted file mode 100644
index 98d5d60..0000000
--- a/libdiskfs/file-get-children.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* file_get_children
-
-   Copyright (C) 2013 Free Software Foundation, Inc.
-
-   Written by Justus Winter <address@hidden>
-
-   This file is part of the GNU Hurd.
-
-   The GNU Hurd is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   The GNU Hurd is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#include "priv.h"
-#include "fs_S.h"
-
-#include <argz.h>
-
-/* Return any active translators bound to nodes below CRED.  CHILDREN
-   is an argz vector containing file names relative to the path of
-   CRED.  */
-error_t
-diskfs_S_file_get_children (struct protid *cred,
-                           char **children,
-                           mach_msg_type_number_t *children_len)
-{
-  error_t err;
-  if (! cred
-      || cred->pi.bucket != diskfs_port_bucket
-      || cred->pi.class != diskfs_protid_class)
-    return EOPNOTSUPP;
-
-  /* check_access performs the same permission check as is normally
-     done, i.e. it checks that all but the last path components are
-     executable by the requesting user and that the last component is
-     readable. */
-  error_t check_access (const char *path)
-  {
-    error_t err;
-    char *elements = NULL;
-    size_t elements_len = 0;
-
-    err = argz_create_sep (path, '/', &elements, &elements_len);
-    if (err)
-      return err;
-
-    struct node *dp = diskfs_root_node;
-
-    for (char *entry = elements;
-        entry;
-        entry = argz_next (elements, elements_len, entry))
-      {
-       struct node *next;
-       err = diskfs_lookup (dp, entry, LOOKUP, &next, NULL, cred);
-
-       if (dp != diskfs_root_node)
-         diskfs_nput (dp);
-
-       if (err)
-         return err;
-
-       dp = next;
-      }
-
-    err = fshelp_access (&dp->dn_stat, S_IRUSR, cred->user);
-    diskfs_nput (dp);
-    return err;
-  }
-
-
-  char *c = NULL;
-  size_t c_len = 0;
-
-  err = fshelp_get_active_translators (&c, &c_len, check_access,
-                                      cred->po->path);
-  if (err)
-    goto errout;
-
-  err = iohelp_return_malloced_buffer (c, c_len, children, children_len);
-  if (err)
-    goto errout;
-
-  c = NULL; /* c was freed by iohelp_return_malloced_buffer. */
-
- errout:
-  free (c);
-  return err;
-}
diff --git a/libdiskfs/file-set-trans.c b/libdiskfs/file-set-trans.c
index 6a73e23..de52ba4 100644
--- a/libdiskfs/file-set-trans.c
+++ b/libdiskfs/file-set-trans.c
@@ -222,7 +222,7 @@ diskfs_S_file_set_translator (struct protid *cred,
   pthread_mutex_unlock (&np->lock);
 
   if (! err && cred->po->path && active_flags & FS_TRANS_SET)
-    err = fshelp_set_active_translator (&cred->pi, cred->po->path, active);
+    err = fshelp_set_active_translator (&cred->pi, cred->po->path, 
&np->transbox);
 
   return err;
 }
diff --git a/libdiskfs/file-syncfs.c b/libdiskfs/file-syncfs.c
index 2faab6a..8cd4003 100644
--- a/libdiskfs/file-syncfs.c
+++ b/libdiskfs/file-syncfs.c
@@ -19,34 +19,33 @@
 #include "fs_S.h"
 #include <hurd/fsys.h>
 
+struct args
+{
+  int wait;
+};
+
+static error_t
+helper (void *cookie, const char *name, mach_port_t control)
+{
+  struct args *args = cookie;
+  (void) name;
+  fsys_syncfs (control, args->wait, 1);
+  return 0;
+}
+
 /* Implement file_syncfs as described in <hurd/fs.defs>. */
 kern_return_t
 diskfs_S_file_syncfs (struct protid *cred,
                      int wait,
                      int dochildren)
 {
-  error_t 
-    helper (struct node *np)
-      {
-       error_t err;
-       mach_port_t control;
-       
-       err = fshelp_fetch_control (&np->transbox, &control);
-       pthread_mutex_unlock (&np->lock);
-       if (!err && (control != MACH_PORT_NULL))
-         {
-           fsys_syncfs (control, wait, 1);
-           mach_port_deallocate (mach_task_self (), control);
-         }
-       pthread_mutex_lock (&np->lock);
-       return 0;
-      }
-  
+  struct args args = { wait };
+
   if (!cred)
     return EOPNOTSUPP;
 
   if (dochildren)
-    diskfs_node_iterate (helper);
+    fshelp_map_active_translators (helper, &args);
 
   if (diskfs_synchronous)
     wait = 1;
diff --git a/libdiskfs/fsys-get-children.c b/libdiskfs/fsys-get-children.c
new file mode 100644
index 0000000..7e2a37b
--- /dev/null
+++ b/libdiskfs/fsys-get-children.c
@@ -0,0 +1,74 @@
+/* fsys_get_children
+
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   The GNU Hurd is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "priv.h"
+#include "fsys_S.h"
+
+#include <argz.h>
+
+/* Return any active child translators.  NAMES is an argz vector
+   containing file names relative to the root of the translator.
+   CONTROLS is an array containing the corresponding control ports.
+   Note that translators are bound to nodes, and nodes can have zero
+   or more links in the file system, therefore there is no guarantee
+   that a translators name refers to an existing link in the file
+   system.  */
+error_t
+diskfs_S_fsys_get_children (struct diskfs_control *fsys,
+                            mach_port_t reply,
+                            mach_msg_type_name_t replytype,
+                           char **names,
+                           mach_msg_type_number_t *names_len,
+                            mach_port_t **controls,
+                            mach_msg_type_name_t *controlsPoly,
+                           mach_msg_type_number_t *controlsCnt)
+{
+  error_t err;
+  char *n = NULL;
+  size_t n_len = 0;
+  mach_port_t *c;
+  size_t c_count;
+
+  if (! fsys)
+    return EOPNOTSUPP;
+
+
+  err = fshelp_get_active_translators (&n, &n_len, &c, &c_count);
+  if (err)
+    goto errout;
+
+  err = iohelp_return_malloced_buffer (n, n_len, names, names_len);
+  if (err)
+    goto errout;
+  n = NULL; /* n was freed by iohelp_return_malloced_buffer. */
+
+  err = iohelp_return_malloced_buffer ((char *) c, c_count * sizeof *c,
+                                       (char **) controls, controlsCnt);
+  if (err)
+    goto errout;
+  c = NULL; /* c was freed by iohelp_return_malloced_buffer. */
+
+  *controlsPoly = MACH_MSG_TYPE_MOVE_SEND;
+  *controlsCnt = c_count;
+
+ errout:
+  free (n);
+  free (c);
+  return err;
+}
diff --git a/libdiskfs/file-get-source.c b/libdiskfs/fsys-get-source.c
similarity index 54%
rename from libdiskfs/file-get-source.c
rename to libdiskfs/fsys-get-source.c
index d983a82..59eee55 100644
--- a/libdiskfs/file-get-source.c
+++ b/libdiskfs/fsys-get-source.c
@@ -1,8 +1,6 @@
-/* file_get_source
+/* fsys_get_source
 
-   Copyright (C) 2013 Free Software Foundation, Inc.
-
-   Written by Justus Winter <address@hidden>
+   Copyright (C) 2017 Free Software Foundation, Inc.
 
    This file is part of the GNU Hurd.
 
@@ -20,17 +18,21 @@
    along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "priv.h"
-#include "fs_S.h"
-
-/* Return information about the source of the receiving
-   filesystem. */
+#include "fsys_S.h"
+
+/* Return information about the source of the translator.  If the
+   concept of a source is applicable, SOURCE should refer to the
+   source of the translator and should be a description considered
+   appropriate in the context of the translator.  For example, if the
+   translator is a filesystem residing on a block device, then SOURCE
+   should be the file name of the underlying block device.  */
 error_t
-diskfs_S_file_get_source (struct protid *cred,
+diskfs_S_fsys_get_source (struct diskfs_control *fsys,
+                          mach_port_t reply,
+                          mach_msg_type_name_t replytype,
                          char *source)
 {
-  if (! cred
-      || cred->pi.bucket != diskfs_port_bucket
-      || cred->pi.class != diskfs_protid_class)
+  if (! fsys)
     return EOPNOTSUPP;
 
   return diskfs_get_source (source, 1024 /* XXX */);
diff --git a/libdiskfs/fsys-options.c b/libdiskfs/fsys-options.c
index f676ed0..6114882 100644
--- a/libdiskfs/fsys-options.c
+++ b/libdiskfs/fsys-options.c
@@ -26,6 +26,25 @@
 #include "priv.h"
 #include "fsys_S.h"
 
+struct args
+{
+  char *data;
+  mach_msg_type_number_t len;
+  int do_children;
+};
+
+static error_t
+helper (void *cookie, const char *name, mach_port_t control)
+{
+  struct args *args = cookie;
+  error_t err;
+  (void) name;
+  err = fsys_set_options (control, args->data, args->len, args->do_children);
+  if (err == MIG_SERVER_DIED || err == MACH_SEND_INVALID_DEST)
+    err = 0;
+  return err;
+}
+
 /* Implement fsys_set_options as described in <hurd/fsys.defs>. */
 kern_return_t
 diskfs_S_fsys_set_options (struct diskfs_control *pt,
@@ -35,28 +54,7 @@ diskfs_S_fsys_set_options (struct diskfs_control *pt,
                           int do_children)
 {
   error_t err = 0;
-
-  error_t
-    helper (struct node *np)
-      {
-       error_t error;
-       mach_port_t control;
-
-       error = fshelp_fetch_control (&np->transbox, &control);
-       pthread_mutex_unlock (&np->lock);
-       if (!error && (control != MACH_PORT_NULL))
-         {
-           error = fsys_set_options (control, data, len, do_children);
-           mach_port_deallocate (mach_task_self (), control);
-         }
-       else
-         error = 0;
-       pthread_mutex_lock (&np->lock);
-
-       if ((error == MIG_SERVER_DIED) || (error == MACH_SEND_INVALID_DEST))
-         error = 0;
-       return error;
-      }
+  struct args args = { data, len, do_children };
 
   if (!pt)
     return EOPNOTSUPP;
@@ -64,7 +62,7 @@ diskfs_S_fsys_set_options (struct diskfs_control *pt,
   if (do_children)
     {
       pthread_rwlock_wrlock (&diskfs_fsys_lock);
-      err = diskfs_node_iterate (helper);
+      err = fshelp_map_active_translators (helper, &args);
       pthread_rwlock_unlock (&diskfs_fsys_lock);
     }
 
diff --git a/libdiskfs/fsys-syncfs.c b/libdiskfs/fsys-syncfs.c
index 17b83ee..1a40fcd 100644
--- a/libdiskfs/fsys-syncfs.c
+++ b/libdiskfs/fsys-syncfs.c
@@ -22,6 +22,20 @@
 #include "fsys_S.h"
 #include <hurd/fsys.h>
 
+struct args
+{
+  int wait;
+};
+
+static error_t
+helper (void *cookie, const char *name, mach_port_t control)
+{
+  struct args *args = cookie;
+  (void) name;
+  fsys_syncfs (control, args->wait, 1);
+  return 0;
+}
+
 /* Implement fsys_syncfs as described in <hurd/fsys.defs>. */
 kern_return_t
 diskfs_S_fsys_syncfs (struct diskfs_control *pi,
@@ -30,22 +44,7 @@ diskfs_S_fsys_syncfs (struct diskfs_control *pi,
                      int wait,
                      int children)
 {
-  error_t 
-    helper (struct node *np)
-      {
-       error_t error;
-       mach_port_t control;
-       
-       error = fshelp_fetch_control (&np->transbox, &control);
-       pthread_mutex_unlock (&np->lock);
-       if (!error && (control != MACH_PORT_NULL))
-         {
-           fsys_syncfs (control, wait, 1);
-           mach_port_deallocate (mach_task_self (), control);
-         }
-       pthread_mutex_lock (&np->lock);
-       return 0;
-      }
+  struct args args = { wait };
 
   if (!pi)
     return EOPNOTSUPP;
@@ -53,7 +52,7 @@ diskfs_S_fsys_syncfs (struct diskfs_control *pi,
   pthread_rwlock_rdlock (&diskfs_fsys_lock);
 
   if (children)
-    diskfs_node_iterate (helper);
+    fshelp_map_active_translators (helper, &args);
 
   if (diskfs_synchronous)
     wait = 1;
diff --git a/libdiskfs/init-main.c b/libdiskfs/init-main.c
index 5c29b7b..69c30fd 100644
--- a/libdiskfs/init-main.c
+++ b/libdiskfs/init-main.c
@@ -61,7 +61,7 @@ diskfs_init_main (struct argp *startup_argp,
   /* Initialize the diskfs library.  Must come before any other diskfs call. */
   err = diskfs_init_diskfs ();
   if (err)
-    error (4, err, "init");
+    error (4, err, "diskfs_init_diskfs");
 
   err = store_parsed_open (*store_parsed, diskfs_readonly ? STORE_READONLY : 0,
                           &store);
diff --git a/libdiskfs/init-startup.c b/libdiskfs/init-startup.c
index a2e3638..4251e0b 100644
--- a/libdiskfs/init-startup.c
+++ b/libdiskfs/init-startup.c
@@ -126,47 +126,15 @@ diskfs_startup_diskfs (mach_port_t bootstrap, int flags)
 error_t
 diskfs_S_startup_dosync (mach_port_t handle)
 {
-  error_t err = 0;
   struct port_info *pi
     = ports_lookup_port (diskfs_port_bucket, handle,
                         diskfs_shutdown_notification_class);
 
   if (!pi)
     return EOPNOTSUPP;
-
-  if (! diskfs_readonly)
-    {
-      /* First start a sync so that if something goes wrong
-        we at least get this much done. */
-      diskfs_sync_everything (0);
-      diskfs_set_hypermetadata (0, 0);
-
-      pthread_rwlock_wrlock (&diskfs_fsys_lock);
-
-      /* Permit all the current RPC's to finish, and then suspend new ones */
-      err = ports_inhibit_class_rpcs (diskfs_protid_class);
-      if (! err)
-       {
-         diskfs_sync_everything (1);
-         diskfs_set_hypermetadata (1, 1);
-         _diskfs_diskdirty = 0;
-
-         /* XXX: if some application writes something after that, we will
-          * crash. That is still better than creating pending writes before
-          * poweroff, and thus fsck on next reboot.
-          */
-         diskfs_readonly = 1;
-         diskfs_readonly_changed (1);
-
-         ports_resume_class_rpcs (diskfs_protid_class);
-       }
-
-      pthread_rwlock_unlock (&diskfs_fsys_lock);
-    }
-
   ports_port_deref (pi);
 
-  return err;
+  return diskfs_shutdown (FSYS_GOAWAY_FORCE || FSYS_GOAWAY_RECURSE);
 }
 
 /* This is called when we have an ordinary environment, complete
diff --git a/libdiskfs/shutdown.c b/libdiskfs/shutdown.c
index 2436d52..3f774c3 100644
--- a/libdiskfs/shutdown.c
+++ b/libdiskfs/shutdown.c
@@ -22,35 +22,30 @@
 #include "priv.h"
 #include <hurd/fsys.h>
 
+struct args
+{
+  int flags;
+};
+
+static error_t
+helper (void *cookie, const char *name, mach_port_t control)
+{
+  struct args *args = cookie;
+  error_t err;
+  (void) name;
+  err = fsys_goaway (control, args->flags);
+  if (err == MIG_SERVER_DIED || err == MACH_SEND_INVALID_DEST)
+    err = 0;
+  return err;
+}
+
 /* Shutdown the filesystem; flags are as for fsys_goaway. */
 error_t
 diskfs_shutdown (int flags)
 {
   int nports = -1;
-  int err;
-
-  error_t
-    helper (struct node *np)
-      {
-       error_t error;
-       mach_port_t control;
-
-       error = fshelp_fetch_control (&np->transbox, &control);
-       pthread_mutex_unlock (&np->lock);
-       if (!error && (control != MACH_PORT_NULL))
-         {
-           error = fsys_goaway (control, flags);
-           mach_port_deallocate (mach_task_self (), control);
-         }
-       else
-         error = 0;
-       pthread_mutex_lock (&np->lock);
-
-       if ((error == MIG_SERVER_DIED) || (error == MACH_SEND_INVALID_DEST))
-         error = 0;
-
-       return error;
-      }
+  error_t err;
+  struct args args = { flags };
 
   if ((flags & FSYS_GOAWAY_UNLINK)
        && S_ISDIR (diskfs_root_node->dn_stat.st_mode))
@@ -58,7 +53,7 @@ diskfs_shutdown (int flags)
 
   if (flags & FSYS_GOAWAY_RECURSE)
     {
-      err = diskfs_node_iterate (helper);
+      err = fshelp_map_active_translators (helper, &args);
       if (err)
        return err;
     }
diff --git a/libfshelp/fetch-control.c b/libfshelp/fetch-control.c
index 0a11197..3b05e11 100644
--- a/libfshelp/fetch-control.c
+++ b/libfshelp/fetch-control.c
@@ -32,11 +32,7 @@ fshelp_fetch_control (struct transbox *box,
                               MACH_PORT_RIGHT_SEND, 1);
 
   if (err == KERN_INVALID_RIGHT)
-    {
-      err = mach_port_deallocate (mach_task_self (), *control);
-      assert_perror_backtrace (err);
-      *control = box->active = MACH_PORT_NULL;
-    }
+    *control = box->active = MACH_PORT_NULL;
 
   return err;
 }
diff --git a/libfshelp/fshelp.h b/libfshelp/fshelp.h
index ecd9335..e8ce973 100644
--- a/libfshelp/fshelp.h
+++ b/libfshelp/fshelp.h
@@ -38,16 +38,16 @@
    require multi threading but depend on the ports library.  */
 
 struct port_info;
+struct transbox;
 
 /* Record an active translator being bound to the given file name
-   NAME.  ACTIVE is the control port of the translator.  PI references
-   a receive port that is used to request dead name notifications,
-   typically the port for the underlying node passed to the
-   translator.  */
+   NAME.  TRANSBOX is the nodes transbox.  PI references a receive
+   port that is used to request dead name notifications, typically the
+   port for the underlying node passed to the translator.  */
 error_t
 fshelp_set_active_translator (struct port_info *pi,
                              const char *name,
-                             mach_port_t active);
+                             const struct transbox *transbox);
 
 /* Remove the active translator specified by its control port ACTIVE.
    If there is no active translator with the given control port, this
@@ -55,12 +55,6 @@ fshelp_set_active_translator (struct port_info *pi,
 error_t
 fshelp_remove_active_translator (mach_port_t active);
 
-/* This kind of function is used by fshelp_get_active_translators to
-   filter the list of translators to return.  If a filter returns an
-   error for a given PATH, the translator bound to the PATH is not
-   included in the list.  */
-typedef error_t (*fshelp_filter) (const char *path);
-
 /* Records the list of active translators below PREFIX into the argz
    vector specified by TRANSLATORS filtered by FILTER.  If PREFIX is
    NULL, entries with any prefix are considered.  If FILTER is NULL,
@@ -68,8 +62,18 @@ typedef error_t (*fshelp_filter) (const char *path);
 error_t
 fshelp_get_active_translators (char **translators,
                               size_t *translators_len,
-                              fshelp_filter filter,
-                              const char *prefix);
+                              mach_port_t **controls,
+                               size_t *controls_count);
+
+/* Call FUN for each active translator.  If FUN returns non-zero, the
+   iteration immediately stops, and returns that value.  FUN is called
+   with COOKIE, the name of the translator, and the translators
+   control port.  */
+error_t
+fshelp_map_active_translators (error_t (*fun)(void *cookie,
+                                             const char *name,
+                                             mach_port_t control),
+                              void *cookie);
 
 
 /* Passive translator linkage */
diff --git a/libfshelp/translator-list.c b/libfshelp/translator-list.c
index e043a67..92b31dd 100644
--- a/libfshelp/translator-list.c
+++ b/libfshelp/translator-list.c
@@ -1,6 +1,6 @@
 /* A list of active translators.
 
-   Copyright (C) 2013,14 Free Software Foundation, Inc.
+   Copyright (C) 2013,14,15 Free Software Foundation, Inc.
 
    Written by Justus Winter <address@hidden>
 
@@ -20,6 +20,7 @@
    along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <argz.h>
+#include <assert-backtrace.h>
 #include <hurd/fsys.h>
 #include <hurd/ihash.h>
 #include <hurd/ports.h>
@@ -34,22 +35,20 @@
 
 struct translator
 {
-  struct port_info *pi;
-  char *name;
-  mach_port_t active;
+  hurd_ihash_locp_t locp;      /* Slot in the hash table.  */
+  struct port_info *pi;                /* We get dead-name notifications
+                                  here.  */
+  char *name;                  /* The path to the node the translator
+                                  is bound to, relative to the root.
+                                  This is a best effort.  */
+  mach_port_t active;          /* Translator control port.  */
 };
 
-/* The list of active translators.  */
-static struct hurd_ihash translator_ihash
-  = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP);
-
-/* The lock protecting the translator_ihash.  */
-static pthread_mutex_t translator_ihash_lock = PTHREAD_MUTEX_INITIALIZER;
-
+/* The hash table requires some callback functions.  */
 static void
-translator_ihash_cleanup (void *element, void *arg)
+cleanup (void *value, void *arg)
 {
-  struct translator *translator = element;
+  struct translator *translator = value;
 
   if (translator->pi)
     ports_port_deref (translator->pi);
@@ -58,28 +57,50 @@ translator_ihash_cleanup (void *element, void *arg)
   free (translator);
 }
 
+static hurd_ihash_key_t
+hash (const void *key)
+{
+  return (hurd_ihash_key_t) hurd_ihash_hash32 (key, sizeof (void *), 0);
+}
+
+static int
+compare (const void *a, const void *b)
+{
+  return *(void **) a == *(void **) b;
+}
+
+/* The list of active translators.  */
+static struct hurd_ihash translator_ihash
+  = HURD_IHASH_INITIALIZER_GKI (offsetof (struct translator, locp),
+                               cleanup, NULL, hash, compare);
+
+/* The lock protecting the translator_ihash.  */
+static pthread_mutex_t translator_ihash_lock = PTHREAD_MUTEX_INITIALIZER;
+
 /* Record an active translator being bound to the given file name
-   NAME.  ACTIVE is the control port of the translator.  */
+   NAME.  TRANSBOX is the nodes transbox.  PI references a receive
+   port that is used to request dead name notifications, typically the
+   port for the underlying node passed to the translator.  */
 error_t
 fshelp_set_active_translator (struct port_info *pi,
                              const char *name,
-                             mach_port_t active)
+                             const struct transbox *transbox)
 {
   error_t err = 0;
-  pthread_mutex_lock (&translator_ihash_lock);
+  struct translator *t;
+  hurd_ihash_locp_t slot;
 
-  if (! translator_ihash.cleanup)
-    hurd_ihash_set_cleanup (&translator_ihash, translator_ihash_cleanup, NULL);
+  pthread_mutex_lock (&translator_ihash_lock);
+  t = hurd_ihash_locp_find (&translator_ihash, (hurd_ihash_key_t) transbox,
+                           &slot);
+  if (t)
+    goto update; /* Entry exists.  */
 
-  struct translator *t = NULL;
-  HURD_IHASH_ITERATE (&translator_ihash, value)
-    {
-      t = value;
-      if (strcmp (name, t->name) == 0)
-       goto update; /* Entry exists.  */
-    }
+  if (! MACH_PORT_VALID (transbox->active))
+    /* Avoid allocating an entry just to delete it.  */
+    goto out;
 
-  t = malloc (sizeof (struct translator));
+  t = malloc (sizeof *t);
   if (! t)
     {
       err = errno;
@@ -96,41 +117,47 @@ fshelp_set_active_translator (struct port_info *pi,
       goto out;
     }
 
-  err = hurd_ihash_add (&translator_ihash, (hurd_ihash_key_t) t, t);
+  err = hurd_ihash_locp_add (&translator_ihash, slot,
+                            (hurd_ihash_key_t) transbox, t);
   if (err)
-    goto out;
+    {
+      free (t->name);
+      free (t);
+      goto out;
+    }
 
  update:
-  if (active)
+  if (MACH_PORT_VALID (transbox->active) && transbox->active != t->active)
     {
-      if (t->pi != pi)
-       {
-         mach_port_t old;
-         err = mach_port_request_notification (mach_task_self (), active,
-                                               MACH_NOTIFY_DEAD_NAME, 0,
-                                               pi->port_right,
-                                               MACH_MSG_TYPE_MAKE_SEND_ONCE,
-                                               &old);
-         if (err)
-           goto out;
-         if (old != MACH_PORT_NULL)
-           mach_port_deallocate (mach_task_self (), old);
-
-         if (t->pi)
-           ports_port_deref (t->pi);
-
-         ports_port_ref (pi);
-         t->pi = pi;
-       }
+      mach_port_t old;
+      err = mach_port_request_notification (mach_task_self (), 
transbox->active,
+                                           MACH_NOTIFY_DEAD_NAME, 0,
+                                           pi->port_right,
+                                           MACH_MSG_TYPE_MAKE_SEND_ONCE,
+                                           &old);
+      if (err)
+       goto out;
+      if (MACH_PORT_VALID (old))
+       mach_port_deallocate (mach_task_self (), old);
+
+      if (t->pi)
+       ports_port_deref (t->pi);
+
+      ports_port_ref (pi);
+      t->pi = pi;
 
       if (MACH_PORT_VALID (t->active))
        mach_port_deallocate (mach_task_self (), t->active);
-      mach_port_mod_refs (mach_task_self (), active,
+      mach_port_mod_refs (mach_task_self (), transbox->active,
                          MACH_PORT_RIGHT_SEND, +1);
-      t->active = active;
+      t->active = transbox->active;
+    }
+  else if (! MACH_PORT_VALID (transbox->active))
+    {
+      int ok;
+      ok = hurd_ihash_remove (&translator_ihash, (hurd_ihash_key_t) transbox);
+      assert_backtrace (ok);
     }
-  else
-    hurd_ihash_remove (&translator_ihash, (hurd_ihash_key_t) t);
 
  out:
   pthread_mutex_unlock (&translator_ihash_lock);
@@ -158,7 +185,7 @@ fshelp_remove_active_translator (mach_port_t active)
     }
 
   if (t)
-    hurd_ihash_remove (&translator_ihash, (hurd_ihash_key_t) t);
+    hurd_ihash_locp_remove (&translator_ihash, t->locp);
 
   pthread_mutex_unlock (&translator_ihash_lock);
   return err;
@@ -171,45 +198,58 @@ fshelp_remove_active_translator (mach_port_t active)
 error_t
 fshelp_get_active_translators (char **translators,
                               size_t *translators_len,
-                              fshelp_filter filter,
-                              const char *prefix)
+                              mach_port_t **controls,
+                               size_t *controls_count)
 {
   error_t err = 0;
   pthread_mutex_lock (&translator_ihash_lock);
 
-  if (prefix && strlen (prefix) == 0)
-    prefix = NULL;
+  *controls = calloc (translator_ihash.nr_items, sizeof **controls);
+  if (*controls == NULL)
+    {
+      pthread_mutex_unlock (&translator_ihash_lock);
+      return ENOMEM;
+    }
+  *controls_count = 0;
 
   HURD_IHASH_ITERATE (&translator_ihash, value)
     {
       struct translator *t = value;
 
-      if (prefix != NULL
-         && (strncmp (t->name, prefix, strlen (prefix)) != 0
-             || t->name[strlen (prefix)] != '/'))
-       /* Skip this entry, as it is not below PREFIX.  */
+      err = mach_port_mod_refs (mach_task_self (), t->active,
+                               MACH_PORT_RIGHT_SEND, +1);
+      if (err)
        continue;
+      (*controls)[*controls_count] = t->active;
+      (*controls_count)++;
 
-      if (filter)
-       {
-         char *dir = strdup (t->name);
-         if (! dir)
-           {
-             err = ENOMEM;
-             break;
-           }
-
-         err = filter (dirname (dir));
-         free (dir);
-         if (err)
-           {
-             err = 0;
-             continue; /* Skip this entry.  */
-           }
-       }
+      err = argz_add (translators, translators_len, t->name);
+      if (err)
+       break;
+    }
+
+  pthread_mutex_unlock (&translator_ihash_lock);
+  return err;
+}
+
+/* Call FUN for each active translator.  If FUN returns non-zero, the
+   iteration immediately stops, and returns that value.  FUN is called
+   with COOKIE, the name of the translator, and the translators
+   control port.  */
+error_t
+fshelp_map_active_translators (error_t (*fun)(void *cookie,
+                                             const char *name,
+                                             mach_port_t control),
+                              void *cookie)
+{
+  error_t err = 0;
+  pthread_mutex_lock (&translator_ihash_lock);
+
+  HURD_IHASH_ITERATE (&translator_ihash, value)
+    {
+      struct translator *t = value;
 
-      err = argz_add (translators, translators_len,
-                     &t->name[prefix? strlen (prefix) + 1: 0]);
+      err = fun (cookie, t->name, t->active);
       if (err)
        break;
     }
diff --git a/libnetfs/Makefile b/libnetfs/Makefile
index c3830c0..de06816 100644
--- a/libnetfs/Makefile
+++ b/libnetfs/Makefile
@@ -34,8 +34,7 @@ FSSRCS= dir-link.c dir-lookup.c dir-mkdir.c dir-mkfile.c \
        file-get-translator.c file-getcontrol.c file-getlinknode.c \
        file-lock-stat.c file-lock.c file-set-size.c \
        file-set-translator.c file-statfs.c file-sync.c file-syncfs.c \
-       file-utimes.c file-reparent.c fsstubs.c file-get-transcntl.c \
-       get-source.c
+       file-utimes.c file-reparent.c fsstubs.c file-get-transcntl.c
 
 IOSRCS=        io-read.c io-readable.c io-seek.c io-write.c io-stat.c 
io-async.c     \
        io-set-all-openmodes.c io-get-openmodes.c io-set-some-openmodes.c     \
@@ -45,7 +44,7 @@ IOSRCS=       io-read.c io-readable.c io-seek.c io-write.c 
io-stat.c io-async.c     \
        io-version.c
 
 FSYSSRCS= fsys-syncfs.c fsys-getroot.c fsys-get-options.c fsys-set-options.c \
-       fsys-goaway.c fsysstubs.c file-get-children.c file-get-source.c
+       fsys-goaway.c fsysstubs.c fsys-get-children.c fsys-get-source.c
 
 IFSOCKSRCS=
 OTHERSRCS= drop-node.c init-init.c make-node.c make-peropen.c make-protid.c   \
@@ -53,7 +52,8 @@ OTHERSRCS= drop-node.c init-init.c make-node.c make-peropen.c 
make-protid.c   \
        init-startup.c startup-argp.c set-options.c append-args.c             \
        runtime-argp.c std-runtime-argp.c std-startup-argp.c                  \
        append-std-options.c trans-callback.c set-get-trans.c                 \
-       nref.c nrele.c nput.c file-get-storage-info-default.c dead-name.c
+       nref.c nrele.c nput.c file-get-storage-info-default.c dead-name.c     \
+       get-source.c
 
 SRCS= $(OTHERSRCS) $(FSSRCS) $(IOSRCS) $(FSYSSRCS) $(IFSOCKSRCS)
 
diff --git a/libnetfs/dir-lookup.c b/libnetfs/dir-lookup.c
index c24a498..a135917 100644
--- a/libnetfs/dir-lookup.c
+++ b/libnetfs/dir-lookup.c
@@ -235,7 +235,6 @@ netfs_S_dir_lookup (struct protid *dircred,
                }
            }
 
-         boolean_t register_translator = 0;
          if (! err)
            {
              struct fshelp_stat_cookie2 cookie = {
@@ -246,12 +245,6 @@ netfs_S_dir_lookup (struct protid *dircred,
 
              dirport = ports_get_send_right (newpi);
 
-             /* Check if an active translator is currently running.  If
-                not, fshelp_fetch_root will start one.  In that case, we
-                need to register it in the list of active
-                translators.  */
-             register_translator = np->transbox.active == MACH_PORT_NULL;
-
              err = fshelp_fetch_root (&np->transbox,
                                       &cookie,
                                       dirport,
@@ -282,39 +275,46 @@ netfs_S_dir_lookup (struct protid *dircred,
                  }
                }
 
-             if (register_translator)
-               {
-                 char *translator_path = strdupa (relpath);
-                 char *complete_path;
-                 if (nextname != NULL)
-                   {
-                     /* This was not the last path component.
-                        NEXTNAME points to the next component, locate
-                        the end of the current component and use it
-                        to trim TRANSLATOR_PATH.  */
-                     char *end = nextname;
-                     while (*end != 0)
-                       end--;
-                     translator_path[end - filename_start] = '\0';
-                   }
-
-                 if (dircred->po->path == NULL || !strcmp 
(dircred->po->path,"."))
-                     /* dircred is the root directory.  */
-                     complete_path = translator_path;
-                 else
-                     asprintf (&complete_path, "%s/%s", dircred->po->path, 
translator_path);
-
-                 err = fshelp_set_active_translator (&newpi->pi,
-                                                     complete_path,
-                                                     np->transbox.active);
-                 if (complete_path != translator_path)
-                   free(complete_path);
-                 if (err)
-                   {
-                     ports_port_deref (newpi);
-                     goto out;
-                   }
-               }
+             {
+               char *translator_path = strdupa (relpath);
+               char *end;
+               char *complete_path;
+               if (nextname != NULL)
+                 {
+                   /* This was not the last path component.
+                      NEXTNAME points to the next component, locate
+                      the end of the current component and use it
+                      to trim TRANSLATOR_PATH.  */
+                   end = nextname;
+                   while (*end != 0)
+                     end--;
+                   translator_path[end - filename_start] = '\0';
+                 }
+
+               /* Trim trailing slashes.  */
+               end = &translator_path[strlen (translator_path) - 1];
+               while (*end == '/' && end >= translator_path)
+                 *end = '\0', end--;
+
+               if (dircred->po->path == NULL
+                   || !strcmp (dircred->po->path,"."))
+                 /* dircred is the root directory.  */
+                 complete_path = translator_path;
+               else
+                 asprintf (&complete_path, "%s/%s", dircred->po->path,
+                           translator_path);
+
+               err = fshelp_set_active_translator (&newpi->pi,
+                                                   complete_path,
+                                                   &np->transbox);
+               if (complete_path != translator_path)
+                 free(complete_path);
+               if (err)
+                 {
+                   ports_port_deref (newpi);
+                   goto out;
+                 }
+             }
 
              ports_port_deref (newpi);
              goto out;
diff --git a/libnetfs/file-get-children.c b/libnetfs/file-get-children.c
deleted file mode 100644
index 5a0ddf0..0000000
--- a/libnetfs/file-get-children.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* file_get_children
-
-   Copyright (C) 2013 Free Software Foundation, Inc.
-
-   Written by Justus Winter <address@hidden>
-
-   This file is part of the GNU Hurd.
-
-   The GNU Hurd is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   The GNU Hurd is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#include "priv.h"
-#include "fs_S.h"
-
-#include <argz.h>
-
-/* Return any active translators bound to nodes below CRED.  CHILDREN
-   is an argz vector containing file names relative to the path of
-   CRED.  */
-error_t
-netfs_S_file_get_children (struct protid *cred,
-                          char **children,
-                          mach_msg_type_number_t *children_len)
-{
-  error_t err;
-  if (! cred)
-    return EOPNOTSUPP;
-
-  /* check_access performs the same permission check as is normally
-     done, i.e. it checks that all but the last path components are
-     executable by the requesting user and that the last component is
-     readable. */
-  error_t check_access (const char *path)
-  {
-    error_t err;
-    char *elements = NULL;
-    size_t elements_len = 0;
-
-    err = argz_create_sep (path, '/', &elements, &elements_len);
-    if (err)
-      return err;
-
-    struct node *dp = netfs_root_node;
-
-    /* Lock the root node. netfs_attempt_lookup expects the directory to
-       be locked.  */
-    pthread_mutex_lock (&dp->lock);
-
-    /* Increase the reference count, it will be decremented in the loop
-       ahead.  */
-    netfs_nref (dp);
-
-    for (char *entry = elements;
-        entry;
-        entry = argz_next (elements, elements_len, entry))
-      {
-       struct node *next;
-       err = netfs_attempt_lookup (cred->user, dp, entry, &next);
-       /* netfs_attempt_lookup has unlocked dp and returned next
-          locked, so there is no locking to do here.  */
-
-       /* Decrease reference count.  */
-       netfs_nrele (dp);
-
-       if (err)
-         goto errout;
-
-       dp = next;
-      }
-
-    err = fshelp_access (&dp->nn_stat, S_IRUSR, cred->user);
-
-  errout:
-    /* Unlock and unreference the last node.  */
-    netfs_nput (dp);
-
-    free (elements);
-    return err;
-  }
-
-  char *c = NULL;
-  size_t c_len = 0;
-
-  err = fshelp_get_active_translators (&c, &c_len, check_access,
-                                      cred->po->path);
-  if (err)
-    goto errout;
-
-  err = iohelp_return_malloced_buffer (c, c_len, children, children_len);
-  if (err)
-    goto errout;
-
-  c = NULL; /* c was freed by iohelp_return_malloced_buffer. */
-
- errout:
-  free (c);
-  return err;
-}
diff --git a/libnetfs/file-set-translator.c b/libnetfs/file-set-translator.c
index bac950e..2b71848 100644
--- a/libnetfs/file-set-translator.c
+++ b/libnetfs/file-set-translator.c
@@ -178,7 +178,7 @@ netfs_S_file_set_translator (struct protid *user,
     }
 
   if (! err && user->po->path && active_flags & FS_TRANS_SET)
-    err = fshelp_set_active_translator (&user->pi, user->po->path, active);
+    err = fshelp_set_active_translator (&user->pi, user->po->path, 
&np->transbox);
 
  out:
   pthread_mutex_unlock (&np->lock);
diff --git a/libnetfs/file-syncfs.c b/libnetfs/file-syncfs.c
index 2302e92..0b14bb8 100644
--- a/libnetfs/file-syncfs.c
+++ b/libnetfs/file-syncfs.c
@@ -20,6 +20,21 @@
 
 #include "netfs.h"
 #include "fs_S.h"
+#include <hurd/fsys.h>
+
+struct args
+{
+  int wait;
+};
+
+static error_t
+helper (void *cookie, const char *name, mach_port_t control)
+{
+  struct args *args = cookie;
+  (void) name;
+  fsys_syncfs (control, args->wait, 1);
+  return 0;
+}
 
 error_t
 netfs_S_file_syncfs (struct protid *user,
@@ -27,11 +42,13 @@ netfs_S_file_syncfs (struct protid *user,
                     int dochildren)
 {
   error_t err;
-  
+  struct args args = { wait };
+
   if (!user)
     return EOPNOTSUPP;
-  
-  /* Translators not yet supported by netfs. XXX */
+
+  if (dochildren)
+    fshelp_map_active_translators (helper, &args);
 
   pthread_mutex_lock (&user->po->np->lock);
   err = netfs_attempt_syncfs (user->user, wait);
diff --git a/libnetfs/fsys-get-children.c b/libnetfs/fsys-get-children.c
new file mode 100644
index 0000000..c4bd0f1
--- /dev/null
+++ b/libnetfs/fsys-get-children.c
@@ -0,0 +1,74 @@
+/* fsys_get_children
+
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   The GNU Hurd is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "priv.h"
+#include "fsys_S.h"
+
+#include <argz.h>
+
+/* Return any active child translators.  NAMES is an argz vector
+   containing file names relative to the root of the translator.
+   CONTROLS is an array containing the corresponding control ports.
+   Note that translators are bound to nodes, and nodes can have zero
+   or more links in the file system, therefore there is no guarantee
+   that a translators name refers to an existing link in the file
+   system.  */
+error_t
+netfs_S_fsys_get_children (struct netfs_control *fsys,
+                          mach_port_t reply,
+                          mach_msg_type_name_t reply_type,
+                          char **names,
+                          mach_msg_type_number_t *names_len,
+                          mach_port_t **controls,
+                          mach_msg_type_name_t *controlsPoly,
+                          mach_msg_type_number_t *controlsCnt)
+{
+  error_t err;
+  char *n = NULL;
+  size_t n_len = 0;
+  mach_port_t *c;
+  size_t c_count;
+
+  if (! fsys)
+    return EOPNOTSUPP;
+
+
+  err = fshelp_get_active_translators (&n, &n_len, &c, &c_count);
+  if (err)
+    goto errout;
+
+  err = iohelp_return_malloced_buffer (n, n_len, names, names_len);
+  if (err)
+    goto errout;
+  n = NULL; /* n was freed by iohelp_return_malloced_buffer. */
+
+  err = iohelp_return_malloced_buffer ((char *) c, c_count * sizeof *c,
+                                       (char **) controls, controlsCnt);
+  if (err)
+    goto errout;
+  c = NULL; /* c was freed by iohelp_return_malloced_buffer. */
+
+  *controlsPoly = MACH_MSG_TYPE_MOVE_SEND;
+  *controlsCnt = c_count;
+
+ errout:
+  free (n);
+  free (c);
+  return err;
+}
diff --git a/libnetfs/file-get-source.c b/libnetfs/fsys-get-source.c
similarity index 54%
rename from libnetfs/file-get-source.c
rename to libnetfs/fsys-get-source.c
index acd3230..bd33cb2 100644
--- a/libnetfs/file-get-source.c
+++ b/libnetfs/fsys-get-source.c
@@ -1,8 +1,6 @@
-/* file_get_source
+/* fsys_get_source
 
-   Copyright (C) 2013 Free Software Foundation, Inc.
-
-   Written by Justus Winter <address@hidden>
+   Copyright (C) 2017 Free Software Foundation, Inc.
 
    This file is part of the GNU Hurd.
 
@@ -20,15 +18,21 @@
    along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "priv.h"
-#include "fs_S.h"
-
-/* Return information about the source of the receiving
-   filesystem.  */
+#include "fsys_S.h"
+
+/* Return information about the source of the translator.  If the
+   concept of a source is applicable, SOURCE should refer to the
+   source of the translator and should be a description considered
+   appropriate in the context of the translator.  For example, if the
+   translator is a filesystem residing on a block device, then SOURCE
+   should be the file name of the underlying block device.  */
 error_t
-netfs_S_file_get_source (struct protid *cred,
+netfs_S_fsys_get_source (struct netfs_control *fsys,
+                         mach_port_t reply,
+                         mach_msg_type_name_t reply_type,
                         char *source)
 {
-  if (! cred)
+  if (! fsys)
     return EOPNOTSUPP;
 
   return netfs_get_source (source, 1024 /* XXX */);
diff --git a/libnetfs/fsys-set-options.c b/libnetfs/fsys-set-options.c
index fb1c87e..afa480f 100644
--- a/libnetfs/fsys-set-options.c
+++ b/libnetfs/fsys-set-options.c
@@ -26,8 +26,24 @@
 #include "netfs.h"
 #include "fsys_S.h"
 
-/* This code is originally from libdiskfs; things surrounded by `#if NOT_YET'
-   are pending libnetfs being fleshed out some more.  */
+struct args
+{
+  char *data;
+  mach_msg_type_number_t len;
+  int do_children;
+};
+
+static error_t
+helper (void *cookie, const char *name, mach_port_t control)
+{
+  struct args *args = cookie;
+  error_t err;
+  (void) name;
+  err = fsys_set_options (control, args->data, args->len, args->do_children);
+  if (err == MIG_SERVER_DIED || err == MACH_SEND_INVALID_DEST)
+    err = 0;
+  return err;
+}
 
 /* Implement fsys_set_options as described in <hurd/fsys.defs>. */
 error_t
@@ -38,40 +54,21 @@ netfs_S_fsys_set_options (struct netfs_control *pt,
                          int do_children)
 {
   error_t err = 0;
+  struct args args = { data, data_len, do_children };
+
   if (!pt)
     return EOPNOTSUPP;
 
-  error_t
-    helper (struct node *np)
-      {
-       error_t error;
-       mach_port_t control;
-
-       error = fshelp_fetch_control (&np->transbox, &control);
-       pthread_mutex_unlock (&np->lock);
-       if (!error && (control != MACH_PORT_NULL))
-         {
-           error = fsys_set_options (control, data, data_len, do_children);
-           mach_port_deallocate (mach_task_self (), control);
-         }
-       else
-         error = 0;
-       pthread_mutex_lock (&np->lock);
-
-       if ((error == MIG_SERVER_DIED) || (error == MACH_SEND_INVALID_DEST))
-         error = 0;
-
-       return error;
-      }
-
-#if NOT_YET
   if (do_children)
     {
+#if NOT_YET
       pthread_rwlock_wrlock (&netfs_fsys_lock);
-      err = netfs_node_iterate (helper);
+#endif
+      err = fshelp_map_active_translators (helper, &args);
+#if NOT_YET
       pthread_rwlock_unlock (&netfs_fsys_lock);
-    }
 #endif
+    }
 
   if (!err)
     {
diff --git a/libnetfs/fsys-syncfs.c b/libnetfs/fsys-syncfs.c
index e232936..904e924 100644
--- a/libnetfs/fsys-syncfs.c
+++ b/libnetfs/fsys-syncfs.c
@@ -20,6 +20,21 @@
 
 #include "netfs.h"
 #include "fsys_S.h"
+#include <hurd/fsys.h>
+
+struct args
+{
+  int wait;
+};
+
+static error_t
+helper (void *cookie, const char *name, mach_port_t control)
+{
+  struct args *args = cookie;
+  (void) name;
+  fsys_syncfs (control, args->wait, 1);
+  return 0;
+}
 
 error_t
 netfs_S_fsys_syncfs (struct netfs_control *cntl,
@@ -30,6 +45,13 @@ netfs_S_fsys_syncfs (struct netfs_control *cntl,
 {
   struct iouser *cred;
   error_t err;
+  struct args args = { wait };
+
+  if (! cntl)
+    return EOPNOTSUPP;
+
+  if (children)
+    fshelp_map_active_translators (helper, &args);
 
   err = iohelp_create_simple_iouser (&cred, 0, 0);
   if (err)
diff --git a/libnetfs/shutdown.c b/libnetfs/shutdown.c
index 7fa05cd..082f2bc 100644
--- a/libnetfs/shutdown.c
+++ b/libnetfs/shutdown.c
@@ -26,33 +26,28 @@
 #include <hurd/fshelp.h>
 #include <pthread.h>
 
+struct args
+{
+  int flags;
+};
+
+static error_t
+helper (void *cookie, const char *name, mach_port_t control)
+{
+  struct args *args = cookie;
+  error_t err;
+  (void) name;
+  err = fsys_goaway (control, args->flags);
+  if (err == MIG_SERVER_DIED || err == MACH_SEND_INVALID_DEST)
+    err = 0;
+  return err;
+}
+
 /* 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))
-        {
-          pthread_mutex_unlock (&node->lock);
-          err = fsys_goaway (control, flags);
-          mach_port_deallocate (mach_task_self (), control);
-          pthread_mutex_lock (&node->lock);
-        }
-      else
-        err = 0;
-
-      if ((err == MIG_SERVER_DIED) || (err == MACH_SEND_INVALID_DEST))
-        err = 0;
-
-      return err;
-    }
-
+  struct args args = { flags };
   int nports;
   int err;
 
@@ -60,14 +55,12 @@ netfs_shutdown (int flags)
       && S_ISDIR (netfs_root_node->nn_stat.st_mode))
     return EBUSY;
 
-#ifdef NOTYET
   if (flags & FSYS_GOAWAY_RECURSE)
     {
-      err = netfs_node_iterate (helper);
+      err = fshelp_map_active_translators (helper, &args);
       if (err)
        return err;
     }
-#endif
 
 #ifdef NOTYET
   pthread_rwlock_wrlock (&netfs_fsys_lock);
diff --git a/libtrivfs/Makefile b/libtrivfs/Makefile
index 4f9c71f..4fd3150 100644
--- a/libtrivfs/Makefile
+++ b/libtrivfs/Makefile
@@ -25,7 +25,7 @@ FSSRCS= dir-link.c dir-mkdir.c dir-mkfile.c dir-lookup.c 
dir-readdir.c \
        file-getlinknode.c file-lock.c file-set-trans.c file-statfs.c \
        file-sync.c file-syncfs.c file-set-size.c file-utimes.c file-exec.c \
        file-access.c dir-chg.c file-chg.c file-get-storage-info.c \
-       file-get-fs-options.c file-reparent.c get-source.c
+       file-get-fs-options.c file-reparent.c \
 
 IOSRCS=io-async-icky.c io-async.c io-duplicate.c io-map.c io-modes-get.c \
        io-modes-off.c io-modes-on.c io-modes-set.c io-owner-get.c \
@@ -35,11 +35,12 @@ IOSRCS=io-async-icky.c io-async.c io-duplicate.c io-map.c 
io-modes-get.c \
 
 FSYSSRCS=fsys-getroot.c fsys-goaway.c fsys-stubs.c fsys-syncfs.c \
        fsys-forward.c fsys-set-options.c fsys-get-options.c \
-       file-get-children.c file-get-source.c
+       fsys-get-children.c fsys-get-source.c \
 
 OTHERSRCS=demuxer.c protid-clean.c protid-dup.c cntl-create.c \
        cntl-clean.c times.c startup.c open.c \
        runtime-argp.c set-options.c append-args.c dyn-classes.c \
+       get-source.c
 
 SRCS=$(FSSRCS) $(IOSRCS) $(FSYSSRCS) $(OTHERSRCS)
 
diff --git a/libtrivfs/file-get-children.c b/libtrivfs/file-get-children.c
deleted file mode 100644
index 4126119..0000000
--- a/libtrivfs/file-get-children.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* file_get_children
-
-   Copyright (C) 2013 Free Software Foundation, Inc.
-
-   Written by Justus Winter <address@hidden>
-
-   This file is part of the GNU Hurd.
-
-   The GNU Hurd is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   The GNU Hurd is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#include "priv.h"
-#include "trivfs_fs_S.h"
-
-/* Return any active translators bound to nodes of the receiving
-   filesystem.  CHILDREN is an argz vector containing file names
-   relative to the root of the receiving translator.  */
-error_t
-trivfs_S_file_get_children (struct trivfs_protid *cred,
-                           mach_port_t reply,
-                           mach_msg_type_name_t replyPoly,
-                           char **children,
-                           mach_msg_type_number_t *children_len)
-{
-  return EOPNOTSUPP;
-}
diff --git a/libtrivfs/fsys-get-children.c b/libtrivfs/fsys-get-children.c
new file mode 100644
index 0000000..f0cd28c
--- /dev/null
+++ b/libtrivfs/fsys-get-children.c
@@ -0,0 +1,41 @@
+/* fsys_get_children
+
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   The GNU Hurd is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "priv.h"
+#include "trivfs_fsys_S.h"
+
+/* Return any active child translators.  NAMES is an argz vector
+   containing file names relative to the root of the translator.
+   CONTROLS is an array containing the corresponding control ports.
+   Note that translators are bound to nodes, and nodes can have zero
+   or more links in the file system, therefore there is no guarantee
+   that a translators name refers to an existing link in the file
+   system.  */
+error_t
+trivfs_S_fsys_get_children (struct trivfs_control *fsys,
+                           mach_port_t reply,
+                           mach_msg_type_name_t replyPoly,
+                           char **names,
+                           mach_msg_type_number_t *names_len,
+                            mach_port_t **controls,
+                            mach_msg_type_name_t *controlsPoly,
+                           mach_msg_type_number_t *controlsCnt)
+{
+  return EOPNOTSUPP;
+}
diff --git a/libtrivfs/file-get-source.c b/libtrivfs/fsys-get-source.c
similarity index 56%
rename from libtrivfs/file-get-source.c
rename to libtrivfs/fsys-get-source.c
index c2420fb..5d063eb 100644
--- a/libtrivfs/file-get-source.c
+++ b/libtrivfs/fsys-get-source.c
@@ -1,8 +1,6 @@
-/* file_get_source
+/* fsys_get_source
 
-   Copyright (C) 2013 Free Software Foundation, Inc.
-
-   Written by Justus Winter <address@hidden>
+   Copyright (C) 2017 Free Software Foundation, Inc.
 
    This file is part of the GNU Hurd.
 
@@ -20,15 +18,19 @@
    along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "priv.h"
-#include "trivfs_fs_S.h"
-
-/* Return information about the source of the receiving
-   filesystem. */
+#include "trivfs_fsys_S.h"
+
+/* Return information about the source of the translator.  If the
+   concept of a source is applicable, SOURCE should refer to the
+   source of the translator and should be a description considered
+   appropriate in the context of the translator.  For example, if the
+   translator is a filesystem residing on a block device, then SOURCE
+   should be the file name of the underlying block device.  */
 error_t
-trivfs_S_file_get_source (struct trivfs_protid *cred,
+trivfs_S_fsys_get_source (struct trivfs_control *fsys,
                          mach_port_t reply,
                          mach_msg_type_name_t replyPoly,
                          char *source)
 {
-  return cred ? trivfs_get_source (source, 1024 /* XXX */) : EOPNOTSUPP;
+  return fsys ? trivfs_get_source (source, 1024 /* XXX */) : EOPNOTSUPP;
 }
diff --git a/pfinet/iioctl-ops.c b/pfinet/iioctl-ops.c
index f1c503d..be65958 100644
--- a/pfinet/iioctl-ops.c
+++ b/pfinet/iioctl-ops.c
@@ -49,7 +49,7 @@ extern void inquire_device (struct device *dev, uint32_t 
*addr,
 /* Truncate name, take the global lock and find device with this name.  */
 struct device *get_dev (char *name)
 {
-  char ifname[16];
+  char ifname[IFNAMSIZ];
   struct device *dev;
 
   memcpy (ifname, name, IFNAMSIZ-1);
diff --git a/pfinet/linux-src/net/ipv4/udp.c b/pfinet/linux-src/net/ipv4/udp.c
index ff5812a..36dc801 100644
--- a/pfinet/linux-src/net/ipv4/udp.c
+++ b/pfinet/linux-src/net/ipv4/udp.c
@@ -467,30 +467,15 @@ void udp_err(struct sk_buff *skb, unsigned char *dp, int 
len)
        }
 
        /*
-        *      Various people wanted BSD UDP semantics. Well they've come
-        *      back out because they slow down response to stuff like dead
-        *      or unreachable name servers and they screw term users something
-        *      chronic. Oh and it violates RFC1122. So basically fix your
-        *      client code people.
-        */
-
-       /*
         *      RFC1122: OK.  Passes ICMP errors back to application, as per
-        *      4.1.3.3. After the comment above, that should be no surprise.
+        *      4.1.3.3.
         */
-
-       if (!harderr && !sk->ip_recverr)
-               return;
-
-       /*
-        *      4.x BSD compatibility item. Break RFC1122 to
-        *      get BSD socket semantics.
-        */
-       if(sk->bsdism && sk->state!=TCP_ESTABLISHED)
-               return;
-
-       if (sk->ip_recverr)
+       if (!sk->ip_recverr) {
+               if (!harderr || sk->state != TCP_ESTABLISHED)
+                       return;
+       } else {
                ip_icmp_error(sk, skb, err, uh->dest, info, (u8*)(uh+1));
+       }
        sk->err = err;
        sk->error_report(sk);
 }
diff --git a/pflocal/Makefile b/pflocal/Makefile
index 3a07975..0419c3e 100644
--- a/pflocal/Makefile
+++ b/pflocal/Makefile
@@ -29,5 +29,7 @@ HURDLIBS = pipe trivfs iohelp fshelp ports ihash 
shouldbeinlibc
 LDLIBS = -lpthread
 
 MIGSFLAGS = -imacros $(srcdir)/mig-mutate.h
+fsServer-CFLAGS = "-DMIG_EOPNOTSUPP=EOPNOTSUPP"
+ioServer-CFLAGS = "-DMIG_EOPNOTSUPP=EOPNOTSUPP"
 
 include ../Makeconf
diff --git a/pflocal/fs.c b/pflocal/fs.c
index d77f00b..10ed915 100644
--- a/pflocal/fs.c
+++ b/pflocal/fs.c
@@ -26,97 +26,6 @@
 #include "fs_S.h"
 
 error_t
-S_dir_notice_changes (struct sock_user *cred,
-                     mach_port_t notify)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_dir_link (struct sock_user *dircred,
-           struct sock_user *filecred,
-           char *name,
-           int excl)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_dir_lookup (struct sock_user *dircred,
-             char *path,
-             int flags,
-             mode_t mode,
-             enum retry_type *retry,
-             char *retryname,
-             file_t *returned_port,
-             mach_msg_type_name_t *returned_port_poly)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_dir_mkdir (struct sock_user *dircred,
-            char *name,
-            mode_t mode)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_dir_mkfile (struct sock_user *cred,
-             int flags,
-             mode_t mode,
-             mach_port_t *newnode,
-             mach_msg_type_name_t *newnodetype)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_dir_readdir (struct sock_user *cred,
-              char **data,
-              size_t *datacnt,
-              boolean_t *data_dealloc,
-              int entry,
-              int nentries,
-              vm_size_t bufsiz,
-              int *amt)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_dir_rename (struct sock_user *fromcred,
-             char *fromname,
-             struct sock_user *tocred,
-             char *toname,
-             int excl)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_dir_rmdir (struct sock_user *dircred,
-            char *name)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_dir_unlink (struct sock_user *dircred,
-             char *name)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_chauthor (struct sock_user *user,
-                uid_t author)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
 S_file_check_access (struct sock_user *cred, int *type)
 {
   if (!cred)
@@ -130,179 +39,3 @@ S_file_check_access (struct sock_user *cred, int *type)
 
   return 0;
 }
-
-error_t
-S_file_chflags (struct sock_user *cred, int flags)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_notice_changes (struct sock_user *cred, mach_port_t notify)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_chmod (struct sock_user *cred, mode_t mode)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_chown (struct sock_user *cred, uid_t uid, gid_t gid)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_exec (struct sock_user *cred,
-            task_t task,
-            int flags,
-            char *argv,
-            size_t argvlen,
-            char *envp,
-            size_t envplen,
-            mach_port_t *fds,
-            size_t fdslen,
-            mach_port_t *portarray,
-            size_t portarraylen,
-            int *intarray,
-            size_t intarraylen,
-            mach_port_t *deallocnames,
-            size_t deallocnameslen,
-            mach_port_t *destroynames,
-            size_t destroynameslen)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_get_children (struct sock_user *cred,
-                    char **children,
-                    mach_msg_type_number_t *children_len)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_getcontrol (struct sock_user *cred,
-                  mach_port_t *control,
-                  mach_msg_type_name_t *controltype)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_getfh (struct sock_user *cred, char **fh, size_t *fh_len)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_get_fs_options (struct sock_user *cred, char **data, size_t *data_len)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_getlinknode (struct sock_user *cred,
-                   file_t *port,
-                   mach_msg_type_name_t *portpoly)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_get_source (struct sock_user *cred, char *source)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_get_storage_info (struct sock_user *cred,
-                        mach_port_t **ports,
-                        mach_msg_type_name_t *ports_type,
-                        mach_msg_type_number_t *num_ports,
-                        int **ints, mach_msg_type_number_t *num_ints,
-                        off_t **offsets,
-                        mach_msg_type_number_t *num_offsets,
-                        char **data, mach_msg_type_number_t *data_len)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_get_translator (struct sock_user *cred, char **trans, size_t *translen)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_get_translator_cntl (struct sock_user *cred,
-                           mach_port_t *ctl,
-                           mach_msg_type_name_t *ctltype)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_lock (struct sock_user *cred, int flags)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_lock_stat (struct sock_user *cred, int *mystatus, int *otherstatus)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_reparent (struct sock_user *cred, mach_port_t parent,
-                mach_port_t *new, mach_msg_type_name_t *new_type)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_set_size (struct sock_user *cred, off_t size)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_set_translator (struct sock_user *cred,
-                      int passive_flags,
-                      int active_flags,
-                      int killtrans_flags,
-                      char *passive,
-                      size_t passivelen,
-                      fsys_t active)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_statfs (struct sock_user *file, fsys_statfsbuf_t *statbuf)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_sync (struct sock_user *cred, int wait, int omitmetadata)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_syncfs (struct sock_user *cred, int wait, int dochildren)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_file_utimes (struct sock_user *cred, time_value_t atime, time_value_t mtime)
-{
-  return EOPNOTSUPP;
-}
diff --git a/pflocal/io.c b/pflocal/io.c
index 77e9df6..2c23df4 100644
--- a/pflocal/io.c
+++ b/pflocal/io.c
@@ -546,112 +546,3 @@ S_io_identity (struct sock_user *user,
 
   return err;
 }
-
-
-/* Stubs for currently unsupported rpcs.  */
-
-error_t
-S_io_revoke (struct sock_user *user)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_async(struct sock_user *user,
-          mach_port_t notify_port,
-          mach_port_t *async_id_port,
-          mach_msg_type_name_t *async_id_port_type)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_mod_owner(struct sock_user *user, pid_t owner)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_get_owner(struct sock_user *user, pid_t *owner)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_get_icky_async_id (struct sock_user *user,
-                       mach_port_t *icky_async_id_port,
-                       mach_msg_type_name_t *icky_async_id_port_type)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_map (struct sock_user *user,
-         mach_port_t *memobj_rd, mach_msg_type_name_t *memobj_rd_type,
-         mach_port_t *memobj_wt, mach_msg_type_name_t *memobj_wt_type)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_map_cntl (struct sock_user *user,
-              mach_port_t *mem, mach_msg_type_name_t *mem_type)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_get_conch (struct sock_user *user)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_release_conch (struct sock_user *user)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_eofnotify (struct sock_user *user)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_prenotify (struct sock_user *user, vm_offset_t start, vm_offset_t end)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_postnotify (struct sock_user *user, vm_offset_t start, vm_offset_t end)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_readsleep (struct sock_user *user)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_readnotify (struct sock_user *user)
-{
-  return EOPNOTSUPP;
-}
-
-
-error_t
-S_io_sigio (struct sock_user *user)
-{
-  return EOPNOTSUPP;
-}
-
-error_t
-S_io_server_version (struct sock_user *user,
-                    char *name, int *maj, int *min, int *edit)
-{
-  return EOPNOTSUPP;
-}
diff --git a/trans/Makefile b/trans/Makefile
index 02718df..8048d6f 100644
--- a/trans/Makefile
+++ b/trans/Makefile
@@ -73,7 +73,7 @@ vpath elfcore.c $(top_srcdir)/exec
 
 crash: crashServer.o crash_replyUser.o msgServer.o elfcore.o
 ifsock: ifsockServer.o
-mtab: fsUser.o
+mtab: fsysUser.o
 password: passwordServer.o
 proxy-defpager: default_pagerServer.o default_pagerUser.o
 streamio: device_replyServer.o
diff --git a/trans/mtab.c b/trans/mtab.c
index a69ede6..794c07f 100644
--- a/trans/mtab.c
+++ b/trans/mtab.c
@@ -26,6 +26,12 @@
 #include <hurd.h>
 #include <hurd/ihash.h>
 #include <hurd/trivfs.h>
+#if XXX_libc_has_included_our_new_rpc
+#include <hurd/fsys.h>
+... also remember to remove the client code from the Makefile...
+#else
+#include "fsys_U.h"
+#endif
 #include <inttypes.h>
 #include <mntent.h>
 #include <nullauth.h>
@@ -39,11 +45,13 @@
 #include <version.h>
 
 #include "libtrivfs/trivfs_io_S.h"
-#include "fs_U.h"
+
+/* The targets control port.  */
+static mach_port_t target_control;
 
 static char *target_path = NULL;
-static int insecure = 0;
-static int all_translators = 0;
+#define MAX_DEPTH      10
+static int max_depth = MAX_DEPTH;
 
 /* Our control port.  */
 struct trivfs_control *control;
@@ -63,25 +71,21 @@ const char *argp_program_version = STANDARD_HURD_VERSION 
(mtab);
 
 static const struct argp_option options[] =
 {
-  {"insecure", 'I', 0, 0,
-   "Follow translators not bound to nodes owned by you or root"},
-  {"all-translators", 'A', 0, 0,
-   "List all translators, even those that are probably not "
-   "filesystem translators"},
+  {"depth", 'd', "DEPTH", 0,
+   "Maximum depth to traverse"},
   {}
 };
 
 /* Parse a command line option.         */
 error_t parse_opt (int key, char *arg, struct argp_state *state)
 {
+  char *end;
   switch (key)
     {
-    case 'I':
-      insecure = 1;
-      break;
-
-    case 'A':
-      all_translators = 1;
+    case 'd':
+      max_depth = strtoull (arg, &end, 10);
+      if (arg == end || end[0] != 0)
+        argp_error (state, "Could not parse depth '%s'.", arg);
       break;
 
     case ARGP_KEY_ARG:
@@ -117,9 +121,14 @@ trivfs_append_args (struct trivfs_control *fsys,
 {
   error_t err;
 
-  if (insecure)
+  if (max_depth != MAX_DEPTH)
     {
-      err = argz_add (argz, argz_len, target_path);
+      char *arg;
+      if (asprintf (&arg, "--depth=%d", max_depth) < 0)
+        return errno;
+
+      err = argz_add (argz, argz_len, arg);
+      free (arg);
       if (err)
        return err;
     }
@@ -201,7 +210,8 @@ is_owner (io_statbuf_t *st)
 }
 
 error_t
-mtab_populate (struct mtab *mtab, const char *path, int insecure);
+mtab_populate (struct mtab *mtab, const char *path, mach_port_t control,
+               int depth);
 
 error_t
 argz_add_device (char **options, size_t *options_len, const char *device);
@@ -213,6 +223,7 @@ int
 main (int argc, char *argv[])
 {
   error_t err;
+  mach_port_t node;
 
   err = argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);
   if (err)
@@ -222,14 +233,27 @@ main (int argc, char *argv[])
   if (err)
     error (2, err, "getting credentials");
 
+  /* Do the lookup without O_NOTRANS to get the root node.  */
+  node = file_name_lookup (target_path, 0, 0);
+  if (! MACH_PORT_VALID (node))
+    error (2, errno, "%s", target_path);
+
+  /* Get the control port.  */
+  err = file_getcontrol (node, &target_control);
+  if (err)
+    error (2, err, "file_getcontrol");
+
+  /* Now that we have the control port, we can drop our
+     privileges.  */
+  err = setnullauth ();
+  if (err)
+    error (3, err, "dropping credentials");
+
   mach_port_t bootstrap;
   task_get_bootstrap_port (mach_task_self (), &bootstrap);
   if (bootstrap != MACH_PORT_NULL)
     {
       /* Started as a translator.  */
-      err = setnullauth ();
-      if (err)
-        error (3, err, "dropping credentials");
 
       /* Reply to our parent.  */
       err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &control);
@@ -254,7 +278,7 @@ main (int argc, char *argv[])
           .lock = PTHREAD_MUTEX_INITIALIZER,
           .ports_seen = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP),
         };
-      err = mtab_populate (&mtab, target_path, insecure);
+      err = mtab_populate (&mtab, target_path, target_control, max_depth);
       if (err)
        error (5, err, "%s", target_path);
 
@@ -284,56 +308,23 @@ mtab_add_entry (struct mtab *mtab, const char *entry, 
size_t length)
   return 0;
 }
 
-/* Check whether the given NODE is a directory on a filesystem
-   translator.  */
-static boolean_t
-is_filesystem_translator (file_t node)
-{
-  error_t err;
-  char *data = NULL;
-  size_t datacnt = 0;
-  int amount;
-  err = dir_readdir (node, &data, &datacnt, 0, 1, 0, &amount);
-  if (data != NULL && datacnt > 0)
-    vm_deallocate (mach_task_self (), (vm_address_t) data, datacnt);
-
-  /* Filesystem translators return either no error, or, if NODE has
-     not been looked up with O_READ, EBADF to dir_readdir
-     requests.  */
-  switch (err)
-    {
-    case 0:
-    case EBADF:
-      return TRUE;
-    default:
-      return FALSE;
-    }
-}
-
-/* Records NODE's idport in ports_seen, returns true if we have
-   already seen this node or there was an error getting the id
-   port.  */
+/* Records CONTROL in ports_seen, returns true if we have already seen
+   this port.  */
 boolean_t
-mtab_mark_as_seen (struct mtab *mtab, mach_port_t node)
+mtab_mark_as_seen (struct mtab *mtab, mach_port_t control)
 {
   error_t err;
-  mach_port_t idport, fsidport;
-  ino_t fileno;
+  if (hurd_ihash_find (&mtab->ports_seen, (hurd_ihash_key_t) control))
+    return TRUE;
 
-  err = io_identity (node, &idport, &fsidport, &fileno);
+  err = mach_port_mod_refs (mach_task_self (), control,
+                            MACH_PORT_RIGHT_SEND, +1);
   if (err)
+    /* Ewww.  */
     return TRUE;
 
-  mach_port_deallocate (mach_task_self (), fsidport);
-
-  if (hurd_ihash_find (&mtab->ports_seen, idport))
-    {
-      /* Already seen.  Get rid of the extra reference.  */
-      mach_port_deallocate (mach_task_self (), idport);
-      return TRUE;
-    }
-
-  hurd_ihash_add (&mtab->ports_seen, idport, (hurd_ihash_value_t) idport);
+  hurd_ihash_add (&mtab->ports_seen,
+                  (hurd_ihash_key_t) control, (hurd_ihash_value_t) control);
   return FALSE;
 }
 
@@ -342,12 +333,13 @@ mtab_mark_as_seen (struct mtab *mtab, mach_port_t node)
    by root or the current user.  */
 /* XXX split up */
 error_t
-mtab_populate (struct mtab *mtab, const char *path, int insecure)
+mtab_populate (struct mtab *mtab, const char *path, mach_port_t control,
+               int depth)
 {
   error_t err = 0;
 
   /* These resources are freed in the epilogue.         */
-  file_t node = MACH_PORT_NULL, underlying_node = MACH_PORT_NULL;
+  file_t node = MACH_PORT_NULL;
   char *argz = NULL;
   size_t argz_len = 0;
   char **argv = NULL;
@@ -359,53 +351,22 @@ mtab_populate (struct mtab *mtab, const char *path, int 
insecure)
   size_t entry_len = 0;
   char *children = NULL;
   size_t children_len = 0;
+  mach_port_t *controls = NULL;
+  size_t controls_count = 0;
+  size_t i;
 
-  /* Get the underlying node.  */
-  underlying_node = file_name_lookup (path, O_NOTRANS, 0666);
-  if (underlying_node == MACH_PORT_NULL)
-    {
-      err = errno;
-      goto errout;
-    }
-
-  if (! insecure)
-    {
-      /* Check who owns the node the translator is bound to.  */
-      io_statbuf_t st;
-      err = io_stat (underlying_node, &st);
-      if (err)
-       goto errout;
-
-      if (st.st_uid != 0 && st.st_gid != 0 && ! is_owner (&st))
-       {
-         err = EPERM;
-         goto errout;
-       }
-    }
-
-  /* (Re-)do the lookup without O_NOTRANS to get the root node.  */
-  node = file_name_lookup (path, 0, 0666);
-  if (node == MACH_PORT_NULL)
-    {
-      err = errno;
-      goto errout;
-    }
-
-  if (! (all_translators || is_filesystem_translator (node)))
-    {
-      err = 0;
-      goto errout;
-    }
+  if (depth < 0)
+    return 0;
 
   /* Avoid running in circles.  */
-  if (mtab_mark_as_seen (mtab, underlying_node))
+  if (mtab_mark_as_seen (mtab, control))
     {
       err = 0;
       goto errout;
     }
 
   /* Query its options.         */
-  err = file_get_fs_options (node, &argz, &argz_len);
+  err = fsys_get_options (control, &argz, &argz_len);
   if (err)
     {
       if (err == EOPNOTSUPP)
@@ -452,7 +413,7 @@ mtab_populate (struct mtab *mtab, const char *path, int 
insecure)
   argz_stringify (options, options_len, ',');
 
   string_t source;
-  err = file_get_source (node, source);
+  err = fsys_get_source (control, source);
   if (err)
     goto errout;
 
@@ -473,8 +434,9 @@ mtab_populate (struct mtab *mtab, const char *path, int 
insecure)
   if (err)
     goto errout;
 
-  /* path has an active translator, query its children.         */
-  err = file_get_children (node, &children, &children_len);
+  /* Recurse.  */
+  err = fsys_get_children (control, &children, &children_len,
+                           &controls, &controls_count);
   if (err == EOPNOTSUPP)
     {
       err = 0;
@@ -484,10 +446,16 @@ mtab_populate (struct mtab *mtab, const char *path, int 
insecure)
   if (err)
     goto errout;
 
-  if (children_len)
-    for (char *c = children; c; c = argz_next (children, children_len, c))
+  char *c;
+  if (children_len && controls_count)
+    for (c = children, i = 0; c && i < controls_count;
+         c = argz_next (children, children_len, c), i++)
       {
        char *p = NULL;
+
+        if (! MACH_PORT_VALID (controls[i]))
+          continue;
+
        asprintf (&p, "%s%s%s",
                  path,
                  path[strlen (path) - 1] == '/'? "": "/",
@@ -498,7 +466,7 @@ mtab_populate (struct mtab *mtab, const char *path, int 
insecure)
            goto errout;
          }
 
-       err = mtab_populate (mtab, p, insecure);
+       err = mtab_populate (mtab, p, controls[i], depth - 1);
        if (err)
          {
            /* There is really not much we can do about errors here.  */
@@ -507,11 +475,12 @@ mtab_populate (struct mtab *mtab, const char *path, int 
insecure)
          }
 
        free (p);
+        err = mach_port_deallocate (mach_task_self (), controls[i]);
+        assert_perror_backtrace (err);
+        controls[i] = MACH_PORT_NULL;
       }
 
  errout:
-  if (underlying_node != MACH_PORT_NULL)
-    mach_port_deallocate (mach_task_self (), underlying_node);
   if (node != MACH_PORT_NULL)
     mach_port_deallocate (mach_task_self (), node);
 
@@ -529,6 +498,9 @@ mtab_populate (struct mtab *mtab, const char *path, int 
insecure)
 
   if (children)
     vm_deallocate (mach_task_self (), (vm_address_t) children, children_len);
+  if (controls)
+    vm_deallocate (mach_task_self (), (vm_address_t) controls,
+                   controls_count * sizeof *controls);
 
   return err;
 }
@@ -647,29 +619,6 @@ open_hook (struct trivfs_peropen *peropen)
   mtab->contents_len = 0;
   hurd_ihash_init (&mtab->ports_seen, HURD_IHASH_NO_LOCP);
 
-  /* The mtab object is initialized, but not yet populated.  We delay
-     that until that data is really needed.  This avoids the following
-     problems:
-
-     Suppose you have
-
-     settrans -ac /foo /hurd/mtab /
-
-     If you now access /foo, the mtab translator will walk the tree of
-     all active translators starting from /.  If it visits /foo, it
-     will talk to itself.  Previously the translator migitated this by
-     comparing the control port of the translator with its own.  This
-     does not work if you got two mtab translators like this:
-
-     settrans -ac /foo /hurd/mtab /
-     settrans -ac /bar /hurd/mtab /
-
-     With a single-threaded mtab server this results in a dead-lock,
-     with a multi-threaded server this will create more and more
-     threads.
-
-     Delaying the data generation until it is really needed cleanly
-     avoids these kind of problems.  */
   return 0;
 }
 
@@ -710,7 +659,7 @@ trivfs_S_io_read (struct trivfs_protid *cred,
 
   if (op->contents == NULL)
     {
-      err = mtab_populate (op, target_path, insecure);
+      err = mtab_populate (op, target_path, target_control, max_depth);
       if (err)
        goto out;
     }
@@ -766,7 +715,7 @@ trivfs_S_io_seek (struct trivfs_protid *cred,
 
   if (op->contents == NULL)
     {
-      err = mtab_populate (op, target_path, insecure);
+      err = mtab_populate (op, target_path, target_control, max_depth);
       if (err)
        goto out;
     }
@@ -823,7 +772,7 @@ trivfs_S_io_readable (struct trivfs_protid *cred,
 
   if (op->contents == NULL)
     {
-      error_t err = mtab_populate (op, target_path, insecure);
+      error_t err = mtab_populate (op, target_path, target_control, max_depth);
       if (err)
        goto out;
     }
diff --git a/utils/devprobe.c b/utils/devprobe.c
index d702032..69b15b2 100644
--- a/utils/devprobe.c
+++ b/utils/devprobe.c
@@ -19,6 +19,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 #include <stdio.h>
+#include <fcntl.h>
 #include <argp.h>
 
 #include <hurd.h>
@@ -32,6 +33,7 @@ static const struct argp_option options[] = {
   {"silent", 's', 0, 0, "Don't print devices found"},
   {"quiet", 0, 0, OPTION_ALIAS},
   {"first", 'f', 0, 0, "Stop after the first device found"},
+  {"master-device", 'M', "FILE", 0, "Get a pseudo master device port"},
   {0}
 };
 static const char *args_doc = "DEVNAME...";
@@ -66,6 +68,17 @@ main (int argc, char **argv)
        case 'f':
          all = 0; break;
 
+       case 'M':
+         if (device_master != MACH_PORT_NULL)
+           mach_port_deallocate (mach_task_self (), device_master);
+
+         device_master = file_name_lookup (arg, O_READ | O_WRITE, 0);
+         if (device_master == MACH_PORT_NULL)
+           argp_failure (state, 3, errno, "Can't open device master port %s",
+                         arg);
+
+         break;
+
        case ARGP_KEY_ARG:
          if (device_master == MACH_PORT_NULL)
            {

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-hurd/hurd.git



reply via email to

[Prev in Thread] Current Thread [Next in Thread]