bug-hurd
[Top][All Lists]
Advanced

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

[PATCH] libmachdev: Install as translator when bootstrapping && fix rump


From: Damien Zammit
Subject: [PATCH] libmachdev: Install as translator when bootstrapping && fix rumpdisk injection
Date: Sat, 14 Nov 2020 14:37:37 +1100

Previous problems mentioned with 2x rumpdisk partitions all fixed.

Booted off rumpdisk / and mounted second partition in userspace:

root@zamhurd:~# showtrans /dev/wd0
/hurd/storeio -T typed device:@/dev/rumpdisk:/dev/wd0

root@zamhurd:~# fdisk -l /dev/wd0
Disk /dev/wd0: 298.9 GiB, 320072933376 bytes, 625142448 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x90a2468d

Device     Boot     Start       End   Sectors  Size Id Type
/dev/wd0s1           2048   1953791   1951744  953M 82 Linux swap / Solaris
/dev/wd0s2        1953792  22925312  20971521   10G 83 Linux
/dev/wd0s3      106811392 316526592 209715201  100G 83 Linux
/dev/wd0s4      316528640 368962049  52433410   25G 83 Linux

root@zamhurd:~# mount /dev/wd0s3 /part3
root@zamhurd:~# ls /part3
demo  lost+found
 

---
 libmachdev/trivfs_server.c | 85 +++++++++++++++++++++++++++-----------
 rumpdisk/block-rump.c      | 65 ++++++++++++++++++++++-------
 rumpdisk/main.c            |  2 +-
 3 files changed, 114 insertions(+), 38 deletions(-)

diff --git a/libmachdev/trivfs_server.c b/libmachdev/trivfs_server.c
index c5407145..5d01e61d 100644
--- a/libmachdev/trivfs_server.c
+++ b/libmachdev/trivfs_server.c
@@ -54,18 +54,47 @@ int trivfs_support_write = 0;
 int trivfs_support_exec = 0;
 int trivfs_allow_open = O_READ | O_WRITE;
 
-/* Our port classes.  */
-struct port_class *trivfs_protid_class;
+/* Our port classes */
 struct port_class *trivfs_cntl_class;
+struct port_class *trivfs_protid_class;
+
+/* Our control struct */
+struct trivfs_control *control;
+
+/* Are we providing bootstrap translator? */
+static boolean_t bootstrapped;
+
+/* Our underlying node for bootstrap */
+static mach_port_t underlying;
 
 /* Our control port */
-static mach_port_t machdev_ctl;
+static mach_port_t control_port;
+
+/* Our device path for injecting bootstrapped translator onto */
+static char *devnode;
 
 /* Startup and shutdown notifications management */
 struct port_class *machdev_shutdown_notify_class;
 
 static void arrange_shutdown_notification (void);
 
+static void
+install_as_translator (mach_port_t bootport)
+{
+  error_t err;
+
+  underlying = file_name_lookup (devnode, O_NOTRANS, 0);
+  if (! MACH_PORT_VALID (underlying))
+    return;
+
+  /* Install translator */
+  err = file_set_translator (underlying,
+                             0, FS_TRANS_SET, 0,
+                             NULL, 0,
+                             bootport, MACH_MSG_TYPE_COPY_SEND);
+  assert_perror_backtrace (err);
+}
+
 /* Implementation of notify interface */
 kern_return_t
 do_mach_notify_port_deleted (struct port_info *pi,
@@ -209,15 +238,14 @@ trivfs_S_fsys_startup (mach_port_t bootport,
                        mach_port_t *realnode,
                        mach_msg_type_name_t *realnodetype)
 {
-  machdev_ctl = cntl;
-
+  control_port = cntl;
   *realnode = MACH_PORT_NULL;
   *realnodetype = MACH_MSG_TYPE_MOVE_SEND;
   return 0;
 }
 
 kern_return_t
-trivfs_S_fsys_init (struct trivfs_control *tc,
+trivfs_S_fsys_init (struct trivfs_control *fsys,
                     mach_port_t reply, mach_msg_type_name_t replytype,
                     mach_port_t procserver,
                     mach_port_t authhandle)
@@ -229,10 +257,11 @@ trivfs_S_fsys_init (struct trivfs_control *tc,
   mach_port_t root;
   retry_type retry;
   string_t retry_name;
+  mach_port_t right = MACH_PORT_NULL;
 
-  err = fsys_getroot (machdev_ctl, MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND,
-                          idlist, 3, idlist, 3, 0,
-                          &retry, retry_name, &root);
+  err = fsys_getroot (control_port, MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND,
+                      idlist, 3, idlist, 3, 0,
+                      &retry, retry_name, &root);
   assert_perror_backtrace (err);
   assert_backtrace (retry == FS_RETRY_NORMAL);
   assert_backtrace (retry_name[0] == '\0');
@@ -249,6 +278,15 @@ trivfs_S_fsys_init (struct trivfs_control *tc,
   _hurd_init (0, NULL, portarray, INIT_PORT_MAX, NULL, 0);
 
   arrange_shutdown_notification ();
+
+  /* Install the bootstrap port on /dev/something so users
+   * can still access the bootstrapped device */
+  if (bootstrapped)
+    {
+      right = ports_get_send_right (&control->pi);
+      install_as_translator (right);
+      control->underlying = underlying;
+    }
   return 0;
 }
 
@@ -301,14 +339,8 @@ trivfs_S_fsys_getpriv (struct diskfs_control 
*init_bootstrap_port,
 {
   error_t err;
   mach_port_t right;
-  struct port_info *server_info;
-
-  err = ports_create_port (trivfs_protid_class, port_bucket,
-                           sizeof (struct port_info), &server_info);
-  assert_perror_backtrace (err);
-  right = ports_get_send_right (server_info);
-  ports_port_deref (server_info);
 
+  right = ports_get_send_right (&control->pi);
   err = get_privileged_ports (host_priv, NULL);
   if (!err)
     {
@@ -326,20 +358,14 @@ resume_bootstrap_server(mach_port_t server_task, const 
char *server_name)
   error_t err;
   mach_port_t right;
   mach_port_t dev, cons;
-  struct port_info *server_info;
 
   assert_backtrace (server_task != MACH_PORT_NULL);
 
-  err = ports_create_port (trivfs_cntl_class, port_bucket,
-                           sizeof (struct port_info), &server_info);
-  assert_perror_backtrace (err);
-  right = ports_get_send_right (server_info);
-  ports_port_deref (server_info);
+  right = ports_get_send_right (&control->pi);
   err = task_set_special_port (server_task, TASK_BOOTSTRAP_PORT, right);
   assert_perror_backtrace (err);
   err = mach_port_deallocate (mach_task_self (), right);
   assert_perror_backtrace (err);
-
   err = task_resume (server_task);
   assert_perror_backtrace (err);
 
@@ -363,17 +389,25 @@ machdev_trivfs_init(mach_port_t bootstrap_resume_task, 
const char *name, mach_po
   port_bucket = ports_create_bucket ();
   trivfs_cntl_class = ports_create_class (trivfs_clean_cntl, 0);
   trivfs_protid_class = ports_create_class (trivfs_clean_protid, 0);
+  trivfs_create_control (MACH_PORT_NULL, trivfs_cntl_class, port_bucket,
+                         trivfs_protid_class, 0, &control);
 
   if (bootstrap_resume_task != MACH_PORT_NULL)
     {
+      devnode = strdup(name);
       resume_bootstrap_server(bootstrap_resume_task, name);
       *bootstrap = MACH_PORT_NULL;
+      /* We need to install as a translator later */
+      bootstrapped = TRUE;
     }
   else
     {
       task_get_bootstrap_port (mach_task_self (), bootstrap);
       if (*bootstrap == MACH_PORT_NULL)
         error (1, 0, "must be started as a translator");
+
+      /* We do not need to install as a translator later */
+      bootstrapped = FALSE;
     }
 
   return 0;
@@ -451,6 +485,7 @@ machdev_trivfs_server(mach_port_t bootstrap)
 
   if (bootstrap != MACH_PORT_NULL)
     {
+      /* This path is executed when a parent exists */
       err = trivfs_startup (bootstrap, 0,
                             trivfs_cntl_class, port_bucket,
                             trivfs_protid_class, port_bucket, &fsys);
@@ -458,6 +493,10 @@ machdev_trivfs_server(mach_port_t bootstrap)
       if (err)
         error (1, err, "Contacting parent");
     }
+  else
+    {
+      fsys = control;
+    }
 
   /* Launch.  */
   do
diff --git a/rumpdisk/block-rump.c b/rumpdisk/block-rump.c
index f7444260..9727328f 100644
--- a/rumpdisk/block-rump.c
+++ b/rumpdisk/block-rump.c
@@ -53,7 +53,7 @@ struct block_data
   char name[DISK_NAME_LEN];    /* eg /dev/wd0 */
   off_t media_size;            /* total block device size */
   uint32_t block_size;         /* size in bytes of 1 sector */
-  bool taken;                  /* simple refcount */
+  bool opening;                        /* simple lock */
   struct block_data *next;
 };
 
@@ -75,18 +75,31 @@ search_bd (char *name)
   while (bd)
     {
       if (!strcmp (bd->name, name))
-       return bd;
+        return bd;
       bd = bd->next;
     }
   return NULL;
 }
 
 /* BSD name of whole disk device is /dev/wdXd
- * but we will receive /dev/wdX as the name */
+ * but we will receive /dev/wdX as the name 
+ * or @/dev/master:/dev/wdX */
 static void
 translate_name (char *output, int len, char *name)
 {
-  snprintf (output, len - 1, "%sd", name);
+  char *pos;
+  char *rest;
+
+  /* Parse @master:/dev/hello */
+  if ( (name[0] == '@') && (pos = strchr (name, ':')) )
+    {
+      rest = pos+1;
+      snprintf (output, len - 1, "%sd", rest);
+    }
+  else
+    {
+      snprintf (output, len - 1, "%sd", name);
+    }
 }
 
 static boolean_t
@@ -105,7 +118,7 @@ is_disk_device (char *name, int len)
   for (i = 0; i < MAX_DISK_DEV; i++)
     {
       dev = (char *)allowed_devs[i];
-      /* /dev/XXN but we only care about /dev/XX prefix */
+      /* /dev/XXNd but we only care about /dev/XX prefix */
       if (! strncmp (dev, name, 7))
         return TRUE;
     }
@@ -142,6 +155,8 @@ device_close (void *d)
 {
   struct block_data *bd = d;
 
+  ports_port_deref (bd);
+  ports_destroy_right (bd);
   return rump_errno2host (rump_sys_close (bd->rump_fd));
 }
 
@@ -175,18 +190,19 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t 
reply_port_type,
   off_t media_size;
   uint32_t block_size;
 
-  if (! is_disk_device (name, 8))
-    return D_NO_SUCH_DEVICE;
-
   translate_name (dev_name, DISK_NAME_LEN, name);
 
+  if (! is_disk_device (dev_name, 8))
+    return D_NO_SUCH_DEVICE;
+
   /* Find previous device or open if new */
-  bd = search_bd (name);
+  bd = search_bd (dev_name);
   if (!bd)
     {
       err = machdev_create_device_port (sizeof (*bd), &bd);
 
-      snprintf (bd->name, DISK_NAME_LEN, "%s", name);
+      snprintf (bd->name, DISK_NAME_LEN, "%s", dev_name);
+      bd->opening = true;
       bd->mode = mode;
       bd->device.emul_data = bd;
       bd->device.emul_ops = &rump_block_emulation_ops;
@@ -194,8 +210,8 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t 
reply_port_type,
       err = rump_sys_open (dev_name, dev_mode_to_rump_mode (bd->mode));
       if (err < 0)
        {
-         err = rump_errno2host (errno);
-         goto out;
+          err = rump_errno2host (errno);
+          goto out;
        }
       bd->rump_fd = err;
 
@@ -221,6 +237,20 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t 
reply_port_type,
     }
 
 out:
+  if (err == D_ALREADY_OPEN)
+    {
+      if (bd)
+        {
+          *devp = ports_get_right (bd);
+          *devicePoly = MACH_MSG_TYPE_MAKE_SEND;
+          return D_SUCCESS;
+        }
+      else
+        {
+         return D_ALREADY_OPEN;
+       }
+    }
+
   if (err)
     {
       if (bd)
@@ -233,10 +263,11 @@ out:
 
   if (bd)
     {
-      bd->next = block_head;
-      block_head = bd;
       *devp = ports_get_right (bd);
       *devicePoly = MACH_MSG_TYPE_MAKE_SEND;
+      bd->next = block_head;
+      bd->opening = false;
+      block_head = bd;
     }
   return err;
 }
@@ -253,6 +284,9 @@ device_write (void *d, mach_port_t reply_port,
   if ((bd->mode & D_WRITE) == 0)
     return D_INVALID_OPERATION;
 
+  if (bd->opening)
+    return D_WOULD_BLOCK;
+
   written = rump_sys_pwrite (bd->rump_fd, (const void *)data, (size_t)count, 
(off_t)bn * bd->block_size);
   if (written < 0)
     {
@@ -281,6 +315,9 @@ device_read (void *d, mach_port_t reply_port,
   if ((bd->mode & D_READ) == 0)
     return D_INVALID_OPERATION;
 
+  if (bd->opening)
+    return D_WOULD_BLOCK;
+
   if (count == 0)
     return D_SUCCESS;
 
diff --git a/rumpdisk/main.c b/rumpdisk/main.c
index 27a8ea38..3ee24341 100644
--- a/rumpdisk/main.c
+++ b/rumpdisk/main.c
@@ -118,7 +118,7 @@ main (int argc, char **argv)
 
   rump_register_block ();
   machdev_device_init ();
-  machdev_trivfs_init (bootstrap_resume_task, "fs", &bootstrap);
+  machdev_trivfs_init (bootstrap_resume_task, "/dev/rumpdisk", &bootstrap);
   err = pthread_create (&t, NULL, machdev_server, NULL);
   if (err)
     return err;
-- 
2.28.0




reply via email to

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