qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/4] linux-user: kpartx fixes
@ 2012-01-31 21:49 Alexander Graf
  2012-01-31 21:49 ` [Qemu-devel] [PATCH 1/4] linux-user: implement device mapper ioctls Alexander Graf
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Alexander Graf @ 2012-01-31 21:49 UTC (permalink / raw)
  To: qemu-devel Developers; +Cc: riku.voipio

As part of our OBS build process, we also want to be able to create kiwi images
for ARM on x86 hardware. One of the crucial bits there is the kpartx tool, since
that allows us to map images on the fly through device mapper.

So this patch set goes in and implements all the device mapper ioctls and fixes
a few hickups to actually make things work along the way. With this applied, I
can successfully run kpartx -av on an image file and have that available in the
system. As far as possible, I also verified all the other ioctls to actually
work.

Alex

Alexander Graf (4):
  linux-user: implement device mapper ioctls
  linux-user: add struct old_dev_t compat
  linux-user: fix BLK ioctl arguments
  linux-user: add BLKSSZGET ioctl wrapper

 linux-user/ioctls.h        |   34 +++++++
 linux-user/syscall.c       |  226 ++++++++++++++++++++++++++++++++++++++++++++
 linux-user/syscall_defs.h  |   26 +++++-
 linux-user/syscall_types.h |   40 ++++++++-
 thunk.c                    |   28 ++++++
 thunk.h                    |   28 ++++++
 6 files changed, 377 insertions(+), 5 deletions(-)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH 1/4] linux-user: implement device mapper ioctls
  2012-01-31 21:49 [Qemu-devel] [PATCH 0/4] linux-user: kpartx fixes Alexander Graf
@ 2012-01-31 21:49 ` Alexander Graf
  2012-02-06 15:06   ` Alexander Graf
  2012-01-31 21:49 ` [Qemu-devel] [PATCH 2/4] linux-user: add struct old_dev_t compat Alexander Graf
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Alexander Graf @ 2012-01-31 21:49 UTC (permalink / raw)
  To: qemu-devel Developers; +Cc: riku.voipio

This patch implements all ioctls currently implemented by device mapper,
enabling us to run dmsetup and kpartx inside of linux-user.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 linux-user/ioctls.h        |   33 +++++++
 linux-user/syscall.c       |  226 ++++++++++++++++++++++++++++++++++++++++++++
 linux-user/syscall_defs.h  |   18 ++++
 linux-user/syscall_types.h |   36 +++++++
 4 files changed, 313 insertions(+), 0 deletions(-)

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 6514502..a9d333a 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -345,3 +345,36 @@
   IOCTL(VT_SETMODE, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_vt_mode)))
   IOCTL(VT_RELDISP, 0, TYPE_INT)
   IOCTL(VT_DISALLOCATE, 0, TYPE_INT)
+
+  IOCTL(DM_VERSION, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_REMOVE_ALL,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_LIST_DEVICES, IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_CREATE,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_REMOVE,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_RENAME,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_SUSPEND,  IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_STATUS,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_WAIT,     IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_TABLE_LOAD,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_TABLE_CLEAR,  IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_TABLE_DEPS,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_TABLE_STATUS, IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_LIST_VERSIONS,IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_TARGET_MSG,   IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+  IOCTL_SPECIAL(DM_DEV_SET_GEOMETRY, IOC_RW, do_ioctl_dm,
+                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 2bf9e7e..27a3131 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -95,6 +95,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 #endif
 #include <linux/fb.h>
 #include <linux/vt.h>
+#include <linux/dm-ioctl.h>
 #include "linux_loop.h"
 #include "cpu-uname.h"
 
@@ -3317,6 +3318,231 @@ static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
     return ret;
 }
 
+static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
+                            abi_long cmd, abi_long arg)
+{
+    void *argptr;
+    struct dm_ioctl *host_dm;
+    abi_long guest_data;
+    uint32_t guest_data_size;
+    int target_size;
+    const argtype *arg_type = ie->arg_type;
+    abi_long ret;
+    void *big_buf = NULL;
+    char *host_data;
+
+    arg_type++;
+    target_size = thunk_type_size(arg_type, 0);
+    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+    if (!argptr) {
+        ret = -TARGET_EFAULT;
+        goto out;
+    }
+    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+    unlock_user(argptr, arg, 0);
+
+    /* buf_temp is too small, so fetch things into a bigger buffer */
+    big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
+    memcpy(big_buf, buf_temp, target_size);
+    buf_temp = big_buf;
+    host_dm = big_buf;
+
+    guest_data = arg + host_dm->data_start;
+    if ((guest_data - arg) < 0) {
+        ret = -EINVAL;
+        goto out;
+    }
+    guest_data_size = host_dm->data_size - host_dm->data_start;
+    host_data = (char*)host_dm + host_dm->data_start;
+
+    argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
+    switch (ie->host_cmd) {
+    case DM_REMOVE_ALL:
+    case DM_LIST_DEVICES:
+    case DM_DEV_CREATE:
+    case DM_DEV_REMOVE:
+    case DM_DEV_SUSPEND:
+    case DM_DEV_STATUS:
+    case DM_DEV_WAIT:
+    case DM_TABLE_STATUS:
+    case DM_TABLE_CLEAR:
+    case DM_TABLE_DEPS:
+    case DM_LIST_VERSIONS:
+        /* no input data */
+        break;
+    case DM_DEV_RENAME:
+    case DM_DEV_SET_GEOMETRY:
+        /* data contains only strings */
+        memcpy(host_data, argptr, guest_data_size);
+        break;
+    case DM_TARGET_MSG:
+        memcpy(host_data, argptr, guest_data_size);
+        *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
+        break;
+    case DM_TABLE_LOAD:
+    {
+        void *gspec = argptr;
+        void *cur_data = host_data;
+        const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
+        int spec_size = thunk_type_size(arg_type, 0);
+        int i;
+
+        for (i = 0; i < host_dm->target_count; i++) {
+            struct dm_target_spec *spec = cur_data;
+            uint32_t next;
+            int slen;
+
+            thunk_convert(spec, gspec, arg_type, THUNK_HOST);
+            slen = strlen((char*)gspec + spec_size) + 1;
+            next = spec->next;
+            spec->next = sizeof(*spec) + slen;
+            strcpy((char*)&spec[1], gspec + spec_size);
+            gspec += next;
+            cur_data += spec->next;
+        }
+        break;
+    }
+    default:
+        ret = -TARGET_EINVAL;
+        goto out;
+    }
+    unlock_user(argptr, guest_data, 0);
+
+    ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+    if (!is_error(ret)) {
+        guest_data = arg + host_dm->data_start;
+        guest_data_size = host_dm->data_size - host_dm->data_start;
+        argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
+        switch (ie->host_cmd) {
+        case DM_REMOVE_ALL:
+        case DM_DEV_CREATE:
+        case DM_DEV_REMOVE:
+        case DM_DEV_RENAME:
+        case DM_DEV_SUSPEND:
+        case DM_DEV_STATUS:
+        case DM_TABLE_LOAD:
+        case DM_TABLE_CLEAR:
+        case DM_TARGET_MSG:
+        case DM_DEV_SET_GEOMETRY:
+            /* no return data */
+            break;
+        case DM_LIST_DEVICES:
+        {
+            struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
+            uint32_t remaining_data = guest_data_size;
+            void *cur_data = argptr;
+            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
+            int nl_size = 12; /* can't use thunk_size due to alignment */
+
+            while (1) {
+                uint32_t next = nl->next;
+                if (next) {
+                    nl->next = nl_size + (strlen(nl->name) + 1);
+                }
+                if (remaining_data < nl->next) {
+                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
+                    break;
+                }
+                thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
+                strcpy(cur_data + nl_size, nl->name);
+                cur_data += nl->next;
+                remaining_data -= nl->next;
+                if (!next) {
+                    break;
+                }
+                nl = (void*)nl + next;
+            }
+            break;
+        }
+        case DM_DEV_WAIT:
+        case DM_TABLE_STATUS:
+        {
+            struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
+            void *cur_data = argptr;
+            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
+            int spec_size = thunk_type_size(arg_type, 0);
+            int i;
+
+            for (i = 0; i < host_dm->target_count; i++) {
+                uint32_t next = spec->next;
+                int slen = strlen((char*)&spec[1]) + 1;
+                spec->next = (cur_data - argptr) + spec_size + slen;
+                if (guest_data_size < spec->next) {
+                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
+                    break;
+                }
+                thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
+                strcpy(cur_data + spec_size, (char*)&spec[1]);
+                cur_data = argptr + spec->next;
+                spec = (void*)host_dm + host_dm->data_start + next;
+            }
+            break;
+        }
+        case DM_TABLE_DEPS:
+        {
+            void *hdata = (void*)host_dm + host_dm->data_start;
+            int count = *(uint32_t*)hdata;
+            uint64_t *hdev = hdata + 8;
+            uint64_t *gdev = argptr + 8;
+            int i;
+
+            *(uint32_t*)argptr = tswap32(count);
+            for (i = 0; i < count; i++) {
+                *gdev = tswap64(*hdev);
+                gdev++;
+                hdev++;
+            }
+            break;
+        }
+        case DM_LIST_VERSIONS:
+        {
+            struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
+            uint32_t remaining_data = guest_data_size;
+            void *cur_data = argptr;
+            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
+            int vers_size = thunk_type_size(arg_type, 0);
+
+            while (1) {
+                uint32_t next = vers->next;
+                if (next) {
+                    vers->next = vers_size + (strlen(vers->name) + 1);
+                }
+                if (remaining_data < vers->next) {
+                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
+                    break;
+                }
+                thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
+                strcpy(cur_data + vers_size, vers->name);
+                cur_data += vers->next;
+                remaining_data -= vers->next;
+                if (!next) {
+                    break;
+                }
+                vers = (void*)vers + next;
+            }
+            break;
+        }
+        default:
+            ret = -TARGET_EINVAL;
+            goto out;
+        }
+        unlock_user(argptr, guest_data, guest_data_size);
+
+        argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+        if (!argptr) {
+            ret = -TARGET_EFAULT;
+            goto out;
+        }
+        thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
+        unlock_user(argptr, arg, target_size);
+    }
+out:
+    if (big_buf) {
+        free(big_buf);
+    }
+    return ret;
+}
+
 static IOCTLEntry ioctl_entries[] = {
 #define IOCTL(cmd, access, ...) \
     { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 2857805..f5e0c41 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -989,6 +989,24 @@ struct target_pollfd {
 #define TARGET_VT_RELDISP             0x5605
 #define TARGET_VT_DISALLOCATE         0x5608
 
+/* device mapper */
+#define TARGET_DM_VERSION             TARGET_IOWRU(0xfd, 0x00)
+#define TARGET_DM_REMOVE_ALL          TARGET_IOWRU(0xfd, 0x01)
+#define TARGET_DM_LIST_DEVICES        TARGET_IOWRU(0xfd, 0x02)
+#define TARGET_DM_DEV_CREATE          TARGET_IOWRU(0xfd, 0x03)
+#define TARGET_DM_DEV_REMOVE          TARGET_IOWRU(0xfd, 0x04)
+#define TARGET_DM_DEV_RENAME          TARGET_IOWRU(0xfd, 0x05)
+#define TARGET_DM_DEV_SUSPEND         TARGET_IOWRU(0xfd, 0x06)
+#define TARGET_DM_DEV_STATUS          TARGET_IOWRU(0xfd, 0x07)
+#define TARGET_DM_DEV_WAIT            TARGET_IOWRU(0xfd, 0x08)
+#define TARGET_DM_TABLE_LOAD          TARGET_IOWRU(0xfd, 0x09)
+#define TARGET_DM_TABLE_CLEAR         TARGET_IOWRU(0xfd, 0x0a)
+#define TARGET_DM_TABLE_DEPS          TARGET_IOWRU(0xfd, 0x0b)
+#define TARGET_DM_TABLE_STATUS        TARGET_IOWRU(0xfd, 0x0c)
+#define TARGET_DM_LIST_VERSIONS       TARGET_IOWRU(0xfd, 0x0d)
+#define TARGET_DM_TARGET_MSG          TARGET_IOWRU(0xfd, 0x0e)
+#define TARGET_DM_DEV_SET_GEOMETRY    TARGET_IOWRU(0xfd, 0x0f)
+
 /* from asm/termbits.h */
 
 #define TARGET_NCC 8
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index c370125..fb8c9c9 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -186,6 +186,42 @@ STRUCT(vt_mode,
        TYPE_SHORT, /* acqsig */
        TYPE_SHORT) /* frsig  */
 
+STRUCT(dm_ioctl,
+       MK_ARRAY(TYPE_INT, 3), /* version */
+       TYPE_INT, /* data_size */
+       TYPE_INT, /* data_start */
+       TYPE_INT, /* target_count*/
+       TYPE_INT, /* open_count */
+       TYPE_INT, /* flags */
+       TYPE_INT, /* event_nr */
+       TYPE_INT, /* padding */
+       TYPE_ULONGLONG, /* dev */
+       MK_ARRAY(TYPE_CHAR, 128), /* name */
+       MK_ARRAY(TYPE_CHAR, 129), /* uuid */
+       MK_ARRAY(TYPE_CHAR, 7)) /* data */
+
+STRUCT(dm_target_spec,
+       TYPE_ULONGLONG, /* sector_start */
+       TYPE_ULONGLONG, /* length */
+       TYPE_INT, /* status */
+       TYPE_INT, /* next */
+       MK_ARRAY(TYPE_CHAR, 16)) /* target_type */
+
+STRUCT(dm_target_deps,
+       TYPE_INT, /* count */
+       TYPE_INT) /* padding */
+
+STRUCT(dm_name_list,
+       TYPE_ULONGLONG, /* dev */
+       TYPE_INT) /* next */
+
+STRUCT(dm_target_versions,
+       TYPE_INT, /* next */
+       MK_ARRAY(TYPE_INT, 3)) /* version*/
+
+STRUCT(dm_target_msg,
+       TYPE_ULONGLONG) /* sector */
+
 STRUCT(fiemap_extent,
        TYPE_ULONGLONG, /* fe_logical */
        TYPE_ULONGLONG, /* fe_physical */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH 2/4] linux-user: add struct old_dev_t compat
  2012-01-31 21:49 [Qemu-devel] [PATCH 0/4] linux-user: kpartx fixes Alexander Graf
  2012-01-31 21:49 ` [Qemu-devel] [PATCH 1/4] linux-user: implement device mapper ioctls Alexander Graf
@ 2012-01-31 21:49 ` Alexander Graf
  2012-01-31 22:23   ` Alexander Graf
  2012-01-31 21:49 ` [Qemu-devel] [PATCH 3/4] linux-user: fix BLK ioctl arguments Alexander Graf
  2012-01-31 21:49 ` [Qemu-devel] [PATCH 4/4] linux-user: add BLKSSZGET ioctl wrapper Alexander Graf
  3 siblings, 1 reply; 7+ messages in thread
From: Alexander Graf @ 2012-01-31 21:49 UTC (permalink / raw)
  To: qemu-devel Developers; +Cc: riku.voipio

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 4108 bytes --]

The compat LOOP_SET_STATUS ioctl uses struct old_dev_t in its passed
struct. That variable type is vastly different between different
architectures. Implement wrapping around it so we can use it.

This fixes running arm kpartx on an x86_64 host for me.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 linux-user/syscall_types.h |    4 ++--
 thunk.c                    |   28 ++++++++++++++++++++++++++++
 thunk.h                    |   28 ++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index fb8c9c9..601618d 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -83,9 +83,9 @@ STRUCT(mixer_info,
 /* loop device ioctls */
 STRUCT(loop_info,
        TYPE_INT,                 /* lo_number */
-       TYPE_SHORT,               /* lo_device */
+       TYPE_OLDDEVT,             /* lo_device */
        TYPE_ULONG,               /* lo_inode */
-       TYPE_SHORT,               /* lo_rdevice */
+       TYPE_OLDDEVT,             /* lo_rdevice */
        TYPE_INT,                 /* lo_offset */
        TYPE_INT,                 /* lo_encrypt_type */
        TYPE_INT,                 /* lo_encrypt_key_size */
diff --git a/thunk.c b/thunk.c
index 0657188..8ebbbb4 100644
--- a/thunk.c
+++ b/thunk.c
@@ -46,6 +46,7 @@ static inline const argtype *thunk_type_next(const argtype *type_ptr)
     case TYPE_LONG:
     case TYPE_ULONG:
     case TYPE_PTRVOID:
+    case TYPE_OLDDEVT:
         return type_ptr;
     case TYPE_PTR:
         return thunk_type_next_ptr(type_ptr);
@@ -188,6 +189,33 @@ const argtype *thunk_convert(void *dst, const void *src,
 #else
 #warning unsupported conversion
 #endif
+    case TYPE_OLDDEVT:
+    {
+        uint64_t val = 0;
+        switch (thunk_type_size(type_ptr - 1, !to_host)) {
+        case 2:
+            val = *(uint16_t *)src;
+            break;
+        case 4:
+            val = *(uint32_t *)src;
+            break;
+        case 8:
+            val = *(uint64_t *)src;
+            break;
+        }
+        switch (thunk_type_size(type_ptr - 1, to_host)) {
+        case 2:
+            *(uint16_t *)dst = tswap16(val);
+            break;
+        case 4:
+            *(uint32_t *)dst = tswap32(val);
+            break;
+        case 8:
+            *(uint64_t *)dst = tswap64(val);
+            break;
+        }
+        break;
+    }
     case TYPE_ARRAY:
         {
             int array_length, i, dst_size, src_size;
diff --git a/thunk.h b/thunk.h
index 109c541..3dcb1a8 100644
--- a/thunk.h
+++ b/thunk.h
@@ -37,6 +37,7 @@ typedef enum argtype {
     TYPE_PTR,
     TYPE_ARRAY,
     TYPE_STRUCT,
+    TYPE_OLDDEVT,
 } argtype;
 
 #define MK_PTR(type) TYPE_PTR, type
@@ -104,6 +105,31 @@ static inline int thunk_type_size(const argtype *type_ptr, int is_host)
             return TARGET_ABI_BITS / 8;
         }
         break;
+    case TYPE_OLDDEVT:
+        if (is_host) {
+#if defined(HOST_X86_64)
+            return 8;
+#elif defined(HOST_ALPHA) || defined(HOST_IA64) || defined(HOST_MIPS) || \
+      defined(HOST_PARISC) || defined(HOST_SPARC64)
+            return 4;
+#elif defined(HOST_PPC)
+            return HOST_LONG_SIZE;
+#else
+            return 2;
+#endif
+        } else {
+#if defined(TARGET_X86_64)
+            return 8;
+#elif defined(TARGET_ALPHA) || defined(TARGET_IA64) || defined(TARGET_MIPS) || \
+      defined(TARGET_PARISC) || defined(TARGET_SPARC64)
+            return 4;
+#elif defined(TARGET_PPC)
+            return TARGET_ABI_BITS / 8;
+#else
+            return 2;
+#endif
+        }
+        break;
     case TYPE_ARRAY:
         size = type_ptr[1];
         return size * thunk_type_size_array(type_ptr + 2, is_host);
@@ -141,6 +167,8 @@ static inline int thunk_type_align(const argtype *type_ptr, int is_host)
             return TARGET_ABI_BITS / 8;
         }
         break;
+    case TYPE_OLDDEVT:
+        return thunk_type_size(type_ptr, is_host);
     case TYPE_ARRAY:
         return thunk_type_align_array(type_ptr + 2, is_host);
     case TYPE_STRUCT:
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH 3/4] linux-user: fix BLK ioctl arguments
  2012-01-31 21:49 [Qemu-devel] [PATCH 0/4] linux-user: kpartx fixes Alexander Graf
  2012-01-31 21:49 ` [Qemu-devel] [PATCH 1/4] linux-user: implement device mapper ioctls Alexander Graf
  2012-01-31 21:49 ` [Qemu-devel] [PATCH 2/4] linux-user: add struct old_dev_t compat Alexander Graf
@ 2012-01-31 21:49 ` Alexander Graf
  2012-01-31 21:49 ` [Qemu-devel] [PATCH 4/4] linux-user: add BLKSSZGET ioctl wrapper Alexander Graf
  3 siblings, 0 replies; 7+ messages in thread
From: Alexander Graf @ 2012-01-31 21:49 UTC (permalink / raw)
  To: qemu-devel Developers; +Cc: riku.voipio

Some BLK ioctls passed sizeof(x) into a macro that already did sizeof() on
the passed in argument, rendering the size information inside the ioctl be
the size of the host default integer type.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 linux-user/syscall_defs.h |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index f5e0c41..6e44c4a 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -832,9 +832,11 @@ struct target_pollfd {
 #define TARGET_BLKSECTGET TARGET_IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
 #define TARGET_BLKSSZGET  TARGET_IO(0x12,104)/* get block device sector size */
 /* A jump here: 108-111 have been used for various private purposes. */
-#define TARGET_BLKBSZGET  TARGET_IOR(0x12,112,sizeof(int))
-#define TARGET_BLKBSZSET  TARGET_IOW(0x12,113,sizeof(int))
-#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */
+#define TARGET_BLKBSZGET  TARGET_IOR(0x12,112,int)
+#define TARGET_BLKBSZSET  TARGET_IOW(0x12,113,int)
+#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,abi_ulong)
+                                             /* return device size in bytes
+                                                (u64 *arg) */
 #define TARGET_FIBMAP     TARGET_IO(0x00,1)  /* bmap access */
 #define TARGET_FIGETBSZ   TARGET_IO(0x00,2)  /* get the block size used for bmap */
 #define TARGET_FS_IOC_FIEMAP TARGET_IOWR('f',11,struct fiemap)
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH 4/4] linux-user: add BLKSSZGET ioctl wrapper
  2012-01-31 21:49 [Qemu-devel] [PATCH 0/4] linux-user: kpartx fixes Alexander Graf
                   ` (2 preceding siblings ...)
  2012-01-31 21:49 ` [Qemu-devel] [PATCH 3/4] linux-user: fix BLK ioctl arguments Alexander Graf
@ 2012-01-31 21:49 ` Alexander Graf
  3 siblings, 0 replies; 7+ messages in thread
From: Alexander Graf @ 2012-01-31 21:49 UTC (permalink / raw)
  To: qemu-devel Developers; +Cc: riku.voipio

This patch adds an ioctl definition for BLKSSZGET.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 linux-user/ioctls.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index a9d333a..7245ff0 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -74,6 +74,7 @@
      IOCTL(BLKFLSBUF, 0, TYPE_NULL)
      IOCTL(BLKRASET, 0, TYPE_INT)
      IOCTL(BLKRAGET, IOC_R, MK_PTR(TYPE_LONG))
+     IOCTL(BLKSSZGET, IOC_R, MK_PTR(TYPE_LONG))
 #ifdef FIBMAP
      IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG))
 #endif
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH 2/4] linux-user: add struct old_dev_t compat
  2012-01-31 21:49 ` [Qemu-devel] [PATCH 2/4] linux-user: add struct old_dev_t compat Alexander Graf
@ 2012-01-31 22:23   ` Alexander Graf
  0 siblings, 0 replies; 7+ messages in thread
From: Alexander Graf @ 2012-01-31 22:23 UTC (permalink / raw)
  To: qemu-devel Developers; +Cc: riku.voipio

The compat LOOP_SET_STATUS ioctl uses struct old_dev_t in its passed
struct. That variable type is vastly different between different
architectures. Implement wrapping around it so we can use it.

This fixes running arm kpartx on an x86_64 host for me.

Signed-off-by: Alexander Graf <agraf@suse.de>
---

I messed up some whitespace in the previous patch. This one works better :).

---
 linux-user/syscall_types.h |    4 ++--
 thunk.c                    |   28 ++++++++++++++++++++++++++++
 thunk.h                    |   28 ++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index fb8c9c9..601618d 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -83,9 +83,9 @@ STRUCT(mixer_info,
 /* loop device ioctls */
 STRUCT(loop_info,
        TYPE_INT,                 /* lo_number */
-       TYPE_SHORT,               /* lo_device */
+       TYPE_OLDDEVT,             /* lo_device */
        TYPE_ULONG,               /* lo_inode */
-       TYPE_SHORT,               /* lo_rdevice */
+       TYPE_OLDDEVT,             /* lo_rdevice */
        TYPE_INT,                 /* lo_offset */
        TYPE_INT,                 /* lo_encrypt_type */
        TYPE_INT,                 /* lo_encrypt_key_size */
diff --git a/thunk.c b/thunk.c
index 0657188..8ebbbb4 100644
--- a/thunk.c
+++ b/thunk.c
@@ -46,6 +46,7 @@ static inline const argtype *thunk_type_next(const argtype *type_ptr)
     case TYPE_LONG:
     case TYPE_ULONG:
     case TYPE_PTRVOID:
+    case TYPE_OLDDEVT:
         return type_ptr;
     case TYPE_PTR:
         return thunk_type_next_ptr(type_ptr);
@@ -188,6 +189,33 @@ const argtype *thunk_convert(void *dst, const void *src,
 #else
 #warning unsupported conversion
 #endif
+    case TYPE_OLDDEVT:
+    {
+        uint64_t val = 0;
+        switch (thunk_type_size(type_ptr - 1, !to_host)) {
+        case 2:
+            val = *(uint16_t *)src;
+            break;
+        case 4:
+            val = *(uint32_t *)src;
+            break;
+        case 8:
+            val = *(uint64_t *)src;
+            break;
+        }
+        switch (thunk_type_size(type_ptr - 1, to_host)) {
+        case 2:
+            *(uint16_t *)dst = tswap16(val);
+            break;
+        case 4:
+            *(uint32_t *)dst = tswap32(val);
+            break;
+        case 8:
+            *(uint64_t *)dst = tswap64(val);
+            break;
+        }
+        break;
+    }
     case TYPE_ARRAY:
         {
             int array_length, i, dst_size, src_size;
diff --git a/thunk.h b/thunk.h
index 109c541..125c682 100644
--- a/thunk.h
+++ b/thunk.h
@@ -37,6 +37,7 @@ typedef enum argtype {
     TYPE_PTR,
     TYPE_ARRAY,
     TYPE_STRUCT,
+    TYPE_OLDDEVT,
 } argtype;
 
 #define MK_PTR(type) TYPE_PTR, type
@@ -104,6 +105,31 @@ static inline int thunk_type_size(const argtype *type_ptr, int is_host)
             return TARGET_ABI_BITS / 8;
         }
         break;
+    case TYPE_OLDDEVT:
+        if (is_host) {
+#if defined(HOST_X86_64)
+            return 8;
+#elif defined(HOST_ALPHA) || defined(HOST_IA64) || defined(HOST_MIPS) || \
+      defined(HOST_PARISC) || defined(HOST_SPARC64)
+            return 4;
+#elif defined(HOST_PPC)
+            return HOST_LONG_SIZE;
+#else
+            return 2;
+#endif
+        } else {
+#if defined(TARGET_X86_64)
+            return 8;
+#elif defined(TARGET_ALPHA) || defined(TARGET_IA64) || defined(TARGET_MIPS) || \
+      defined(TARGET_PARISC) || defined(TARGET_SPARC64)
+            return 4;
+#elif defined(TARGET_PPC)
+            return TARGET_ABI_BITS / 8;
+#else
+            return 2;
+#endif
+        }
+        break;
     case TYPE_ARRAY:
         size = type_ptr[1];
         return size * thunk_type_size_array(type_ptr + 2, is_host);
@@ -141,6 +167,8 @@ static inline int thunk_type_align(const argtype *type_ptr, int is_host)
             return TARGET_ABI_BITS / 8;
         }
         break;
+    case TYPE_OLDDEVT:
+        return thunk_type_size(type_ptr, is_host);
     case TYPE_ARRAY:
         return thunk_type_align_array(type_ptr + 2, is_host);
     case TYPE_STRUCT:
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH 1/4] linux-user: implement device mapper ioctls
  2012-01-31 21:49 ` [Qemu-devel] [PATCH 1/4] linux-user: implement device mapper ioctls Alexander Graf
@ 2012-02-06 15:06   ` Alexander Graf
  0 siblings, 0 replies; 7+ messages in thread
From: Alexander Graf @ 2012-02-06 15:06 UTC (permalink / raw)
  To: qemu-devel Developers; +Cc: riku.voipio, agk


On 31.01.2012, at 22:49, Alexander Graf wrote:

> This patch implements all ioctls currently implemented by device mapper,
> enabling us to run dmsetup and kpartx inside of linux-user.

Hi Alasdair,

Could you please have a quick glimpse through this wrapper and check that I handled the ioctls correctly?

Thanks!


Alex

> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
> linux-user/ioctls.h        |   33 +++++++
> linux-user/syscall.c       |  226 ++++++++++++++++++++++++++++++++++++++++++++
> linux-user/syscall_defs.h  |   18 ++++
> linux-user/syscall_types.h |   36 +++++++
> 4 files changed, 313 insertions(+), 0 deletions(-)
> 
> diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
> index 6514502..a9d333a 100644
> --- a/linux-user/ioctls.h
> +++ b/linux-user/ioctls.h
> @@ -345,3 +345,36 @@
>   IOCTL(VT_SETMODE, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_vt_mode)))
>   IOCTL(VT_RELDISP, 0, TYPE_INT)
>   IOCTL(VT_DISALLOCATE, 0, TYPE_INT)
> +
> +  IOCTL(DM_VERSION, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_REMOVE_ALL,   IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_LIST_DEVICES, IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_DEV_CREATE,   IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_DEV_REMOVE,   IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_DEV_RENAME,   IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_DEV_SUSPEND,  IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_DEV_STATUS,   IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_DEV_WAIT,     IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_TABLE_LOAD,   IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_TABLE_CLEAR,  IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_TABLE_DEPS,   IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_TABLE_STATUS, IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_LIST_VERSIONS,IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_TARGET_MSG,   IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +  IOCTL_SPECIAL(DM_DEV_SET_GEOMETRY, IOC_RW, do_ioctl_dm,
> +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
> +
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 2bf9e7e..27a3131 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -95,6 +95,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
> #endif
> #include <linux/fb.h>
> #include <linux/vt.h>
> +#include <linux/dm-ioctl.h>
> #include "linux_loop.h"
> #include "cpu-uname.h"
> 
> @@ -3317,6 +3318,231 @@ static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
>     return ret;
> }
> 
> +static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
> +                            abi_long cmd, abi_long arg)
> +{
> +    void *argptr;
> +    struct dm_ioctl *host_dm;
> +    abi_long guest_data;
> +    uint32_t guest_data_size;
> +    int target_size;
> +    const argtype *arg_type = ie->arg_type;
> +    abi_long ret;
> +    void *big_buf = NULL;
> +    char *host_data;
> +
> +    arg_type++;
> +    target_size = thunk_type_size(arg_type, 0);
> +    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
> +    if (!argptr) {
> +        ret = -TARGET_EFAULT;
> +        goto out;
> +    }
> +    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
> +    unlock_user(argptr, arg, 0);
> +
> +    /* buf_temp is too small, so fetch things into a bigger buffer */
> +    big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
> +    memcpy(big_buf, buf_temp, target_size);
> +    buf_temp = big_buf;
> +    host_dm = big_buf;
> +
> +    guest_data = arg + host_dm->data_start;
> +    if ((guest_data - arg) < 0) {
> +        ret = -EINVAL;
> +        goto out;
> +    }
> +    guest_data_size = host_dm->data_size - host_dm->data_start;
> +    host_data = (char*)host_dm + host_dm->data_start;
> +
> +    argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
> +    switch (ie->host_cmd) {
> +    case DM_REMOVE_ALL:
> +    case DM_LIST_DEVICES:
> +    case DM_DEV_CREATE:
> +    case DM_DEV_REMOVE:
> +    case DM_DEV_SUSPEND:
> +    case DM_DEV_STATUS:
> +    case DM_DEV_WAIT:
> +    case DM_TABLE_STATUS:
> +    case DM_TABLE_CLEAR:
> +    case DM_TABLE_DEPS:
> +    case DM_LIST_VERSIONS:
> +        /* no input data */
> +        break;
> +    case DM_DEV_RENAME:
> +    case DM_DEV_SET_GEOMETRY:
> +        /* data contains only strings */
> +        memcpy(host_data, argptr, guest_data_size);
> +        break;
> +    case DM_TARGET_MSG:
> +        memcpy(host_data, argptr, guest_data_size);
> +        *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
> +        break;
> +    case DM_TABLE_LOAD:
> +    {
> +        void *gspec = argptr;
> +        void *cur_data = host_data;
> +        const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
> +        int spec_size = thunk_type_size(arg_type, 0);
> +        int i;
> +
> +        for (i = 0; i < host_dm->target_count; i++) {
> +            struct dm_target_spec *spec = cur_data;
> +            uint32_t next;
> +            int slen;
> +
> +            thunk_convert(spec, gspec, arg_type, THUNK_HOST);
> +            slen = strlen((char*)gspec + spec_size) + 1;
> +            next = spec->next;
> +            spec->next = sizeof(*spec) + slen;
> +            strcpy((char*)&spec[1], gspec + spec_size);
> +            gspec += next;
> +            cur_data += spec->next;
> +        }
> +        break;
> +    }
> +    default:
> +        ret = -TARGET_EINVAL;
> +        goto out;
> +    }
> +    unlock_user(argptr, guest_data, 0);
> +
> +    ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
> +    if (!is_error(ret)) {
> +        guest_data = arg + host_dm->data_start;
> +        guest_data_size = host_dm->data_size - host_dm->data_start;
> +        argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
> +        switch (ie->host_cmd) {
> +        case DM_REMOVE_ALL:
> +        case DM_DEV_CREATE:
> +        case DM_DEV_REMOVE:
> +        case DM_DEV_RENAME:
> +        case DM_DEV_SUSPEND:
> +        case DM_DEV_STATUS:
> +        case DM_TABLE_LOAD:
> +        case DM_TABLE_CLEAR:
> +        case DM_TARGET_MSG:
> +        case DM_DEV_SET_GEOMETRY:
> +            /* no return data */
> +            break;
> +        case DM_LIST_DEVICES:
> +        {
> +            struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
> +            uint32_t remaining_data = guest_data_size;
> +            void *cur_data = argptr;
> +            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
> +            int nl_size = 12; /* can't use thunk_size due to alignment */
> +
> +            while (1) {
> +                uint32_t next = nl->next;
> +                if (next) {
> +                    nl->next = nl_size + (strlen(nl->name) + 1);
> +                }
> +                if (remaining_data < nl->next) {
> +                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
> +                    break;
> +                }
> +                thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
> +                strcpy(cur_data + nl_size, nl->name);
> +                cur_data += nl->next;
> +                remaining_data -= nl->next;
> +                if (!next) {
> +                    break;
> +                }
> +                nl = (void*)nl + next;
> +            }
> +            break;
> +        }
> +        case DM_DEV_WAIT:
> +        case DM_TABLE_STATUS:
> +        {
> +            struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
> +            void *cur_data = argptr;
> +            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
> +            int spec_size = thunk_type_size(arg_type, 0);
> +            int i;
> +
> +            for (i = 0; i < host_dm->target_count; i++) {
> +                uint32_t next = spec->next;
> +                int slen = strlen((char*)&spec[1]) + 1;
> +                spec->next = (cur_data - argptr) + spec_size + slen;
> +                if (guest_data_size < spec->next) {
> +                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
> +                    break;
> +                }
> +                thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
> +                strcpy(cur_data + spec_size, (char*)&spec[1]);
> +                cur_data = argptr + spec->next;
> +                spec = (void*)host_dm + host_dm->data_start + next;
> +            }
> +            break;
> +        }
> +        case DM_TABLE_DEPS:
> +        {
> +            void *hdata = (void*)host_dm + host_dm->data_start;
> +            int count = *(uint32_t*)hdata;
> +            uint64_t *hdev = hdata + 8;
> +            uint64_t *gdev = argptr + 8;
> +            int i;
> +
> +            *(uint32_t*)argptr = tswap32(count);
> +            for (i = 0; i < count; i++) {
> +                *gdev = tswap64(*hdev);
> +                gdev++;
> +                hdev++;
> +            }
> +            break;
> +        }
> +        case DM_LIST_VERSIONS:
> +        {
> +            struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
> +            uint32_t remaining_data = guest_data_size;
> +            void *cur_data = argptr;
> +            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
> +            int vers_size = thunk_type_size(arg_type, 0);
> +
> +            while (1) {
> +                uint32_t next = vers->next;
> +                if (next) {
> +                    vers->next = vers_size + (strlen(vers->name) + 1);
> +                }
> +                if (remaining_data < vers->next) {
> +                    host_dm->flags |= DM_BUFFER_FULL_FLAG;
> +                    break;
> +                }
> +                thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
> +                strcpy(cur_data + vers_size, vers->name);
> +                cur_data += vers->next;
> +                remaining_data -= vers->next;
> +                if (!next) {
> +                    break;
> +                }
> +                vers = (void*)vers + next;
> +            }
> +            break;
> +        }
> +        default:
> +            ret = -TARGET_EINVAL;
> +            goto out;
> +        }
> +        unlock_user(argptr, guest_data, guest_data_size);
> +
> +        argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
> +        if (!argptr) {
> +            ret = -TARGET_EFAULT;
> +            goto out;
> +        }
> +        thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
> +        unlock_user(argptr, arg, target_size);
> +    }
> +out:
> +    if (big_buf) {
> +        free(big_buf);
> +    }
> +    return ret;
> +}
> +
> static IOCTLEntry ioctl_entries[] = {
> #define IOCTL(cmd, access, ...) \
>     { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index 2857805..f5e0c41 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -989,6 +989,24 @@ struct target_pollfd {
> #define TARGET_VT_RELDISP             0x5605
> #define TARGET_VT_DISALLOCATE         0x5608
> 
> +/* device mapper */
> +#define TARGET_DM_VERSION             TARGET_IOWRU(0xfd, 0x00)
> +#define TARGET_DM_REMOVE_ALL          TARGET_IOWRU(0xfd, 0x01)
> +#define TARGET_DM_LIST_DEVICES        TARGET_IOWRU(0xfd, 0x02)
> +#define TARGET_DM_DEV_CREATE          TARGET_IOWRU(0xfd, 0x03)
> +#define TARGET_DM_DEV_REMOVE          TARGET_IOWRU(0xfd, 0x04)
> +#define TARGET_DM_DEV_RENAME          TARGET_IOWRU(0xfd, 0x05)
> +#define TARGET_DM_DEV_SUSPEND         TARGET_IOWRU(0xfd, 0x06)
> +#define TARGET_DM_DEV_STATUS          TARGET_IOWRU(0xfd, 0x07)
> +#define TARGET_DM_DEV_WAIT            TARGET_IOWRU(0xfd, 0x08)
> +#define TARGET_DM_TABLE_LOAD          TARGET_IOWRU(0xfd, 0x09)
> +#define TARGET_DM_TABLE_CLEAR         TARGET_IOWRU(0xfd, 0x0a)
> +#define TARGET_DM_TABLE_DEPS          TARGET_IOWRU(0xfd, 0x0b)
> +#define TARGET_DM_TABLE_STATUS        TARGET_IOWRU(0xfd, 0x0c)
> +#define TARGET_DM_LIST_VERSIONS       TARGET_IOWRU(0xfd, 0x0d)
> +#define TARGET_DM_TARGET_MSG          TARGET_IOWRU(0xfd, 0x0e)
> +#define TARGET_DM_DEV_SET_GEOMETRY    TARGET_IOWRU(0xfd, 0x0f)
> +
> /* from asm/termbits.h */
> 
> #define TARGET_NCC 8
> diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
> index c370125..fb8c9c9 100644
> --- a/linux-user/syscall_types.h
> +++ b/linux-user/syscall_types.h
> @@ -186,6 +186,42 @@ STRUCT(vt_mode,
>        TYPE_SHORT, /* acqsig */
>        TYPE_SHORT) /* frsig  */
> 
> +STRUCT(dm_ioctl,
> +       MK_ARRAY(TYPE_INT, 3), /* version */
> +       TYPE_INT, /* data_size */
> +       TYPE_INT, /* data_start */
> +       TYPE_INT, /* target_count*/
> +       TYPE_INT, /* open_count */
> +       TYPE_INT, /* flags */
> +       TYPE_INT, /* event_nr */
> +       TYPE_INT, /* padding */
> +       TYPE_ULONGLONG, /* dev */
> +       MK_ARRAY(TYPE_CHAR, 128), /* name */
> +       MK_ARRAY(TYPE_CHAR, 129), /* uuid */
> +       MK_ARRAY(TYPE_CHAR, 7)) /* data */
> +
> +STRUCT(dm_target_spec,
> +       TYPE_ULONGLONG, /* sector_start */
> +       TYPE_ULONGLONG, /* length */
> +       TYPE_INT, /* status */
> +       TYPE_INT, /* next */
> +       MK_ARRAY(TYPE_CHAR, 16)) /* target_type */
> +
> +STRUCT(dm_target_deps,
> +       TYPE_INT, /* count */
> +       TYPE_INT) /* padding */
> +
> +STRUCT(dm_name_list,
> +       TYPE_ULONGLONG, /* dev */
> +       TYPE_INT) /* next */
> +
> +STRUCT(dm_target_versions,
> +       TYPE_INT, /* next */
> +       MK_ARRAY(TYPE_INT, 3)) /* version*/
> +
> +STRUCT(dm_target_msg,
> +       TYPE_ULONGLONG) /* sector */
> +
> STRUCT(fiemap_extent,
>        TYPE_ULONGLONG, /* fe_logical */
>        TYPE_ULONGLONG, /* fe_physical */
> -- 
> 1.6.0.2
> 
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-02-06 15:06 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-31 21:49 [Qemu-devel] [PATCH 0/4] linux-user: kpartx fixes Alexander Graf
2012-01-31 21:49 ` [Qemu-devel] [PATCH 1/4] linux-user: implement device mapper ioctls Alexander Graf
2012-02-06 15:06   ` Alexander Graf
2012-01-31 21:49 ` [Qemu-devel] [PATCH 2/4] linux-user: add struct old_dev_t compat Alexander Graf
2012-01-31 22:23   ` Alexander Graf
2012-01-31 21:49 ` [Qemu-devel] [PATCH 3/4] linux-user: fix BLK ioctl arguments Alexander Graf
2012-01-31 21:49 ` [Qemu-devel] [PATCH 4/4] linux-user: add BLKSSZGET ioctl wrapper Alexander Graf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).