[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
- [PATCH] libmachdev: Install as translator when bootstrapping && fix rumpdisk injection,
Damien Zammit <=