summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2020-08-01 14:40:02 +1000
committerDamien Zammit <damien@zamaudio.com>2020-11-14 14:13:31 +1100
commit87b1ef74999311cdb3d0a1379bc1d3d0bc957708 (patch)
tree16a81c01457d7812fcaf0608c42b42ab550ab8a8
parent986c7a7d686a850830f9fc5bea1fadcfe9f4999c (diff)
libmachdev: Install as translator when bootstrapping && fix rumpdisk injectionrumpdisk-bootstrap
-rw-r--r--libmachdev/trivfs_server.c85
-rw-r--r--rumpdisk/block-rump.c65
-rw-r--r--rumpdisk/main.c2
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;