diff options
Diffstat (limited to 'rumpdisk/block-rump.c')
-rw-r--r-- | rumpdisk/block-rump.c | 65 |
1 files changed, 51 insertions, 14 deletions
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; |