110 lines
3.5 KiB
Diff
110 lines
3.5 KiB
Diff
|
From 4b0131e7b071bb06802a99fcf9a3717215b2362b Mon Sep 17 00:00:00 2001
|
||
|
From: Alexander Graf <agraf@suse.de>
|
||
|
Date: Fri, 22 Aug 2014 12:22:28 +0200
|
||
|
Subject: [PATCH] linux-user: Convert blkpg to use a special subop handler
|
||
|
|
||
|
The blkpg ioctl can take different payloads depending on the opcode in
|
||
|
its payload structure. Create a new special ioctl handler that can only
|
||
|
deal with partition style ones for now.
|
||
|
|
||
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||
|
|
||
|
---
|
||
|
|
||
|
Andreas, if you like feel free to squash this into your patch and submit
|
||
|
it upstream.
|
||
|
---
|
||
|
linux-user/ioctls.h | 3 ++-
|
||
|
linux-user/syscall.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
linux-user/syscall_types.h | 2 +-
|
||
|
3 files changed, 56 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
|
||
|
index 9b6cacb..8eb4446 100644
|
||
|
--- a/linux-user/ioctls.h
|
||
|
+++ b/linux-user/ioctls.h
|
||
|
@@ -96,7 +96,8 @@
|
||
|
IOCTL(BLKRAGET, IOC_R, MK_PTR(TYPE_LONG))
|
||
|
IOCTL(BLKSSZGET, IOC_R, MK_PTR(TYPE_LONG))
|
||
|
IOCTL(BLKBSZGET, IOC_R, MK_PTR(TYPE_INT))
|
||
|
- IOCTL(BLKPG, IOC_W, MK_PTR(MK_STRUCT(STRUCT_blkpg_ioctl_arg)))
|
||
|
+ IOCTL_SPECIAL(BLKPG, IOC_W, do_ioctl_blkpg,
|
||
|
+ MK_PTR(MK_STRUCT(STRUCT_blkpg_ioctl_arg)))
|
||
|
#ifdef FIBMAP
|
||
|
IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG))
|
||
|
#endif
|
||
|
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
|
||
|
index 660095b..04b5119 100644
|
||
|
--- a/linux-user/syscall.c
|
||
|
+++ b/linux-user/syscall.c
|
||
|
@@ -3657,6 +3657,59 @@ out:
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
+static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
|
||
|
+ abi_long cmd, abi_long arg)
|
||
|
+{
|
||
|
+ void *argptr;
|
||
|
+ int target_size;
|
||
|
+ const argtype *arg_type = ie->arg_type;
|
||
|
+ const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
|
||
|
+ abi_long ret;
|
||
|
+
|
||
|
+ struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
|
||
|
+ struct blkpg_partition host_part;
|
||
|
+
|
||
|
+ /* Read and convert blkpg */
|
||
|
+ 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);
|
||
|
+
|
||
|
+ switch (host_blkpg->op) {
|
||
|
+ case BLKPG_ADD_PARTITION:
|
||
|
+ case BLKPG_DEL_PARTITION:
|
||
|
+ /* payload is struct blkpg_partition */
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ /* Unknown opcode */
|
||
|
+ ret = -TARGET_EINVAL;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Read and convert blkpg->data */
|
||
|
+ arg = (abi_long)(uintptr_t)host_blkpg->data;
|
||
|
+ target_size = thunk_type_size(part_arg_type, 0);
|
||
|
+ argptr = lock_user(VERIFY_READ, arg, target_size, 1);
|
||
|
+ if (!argptr) {
|
||
|
+ ret = -TARGET_EFAULT;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
|
||
|
+ unlock_user(argptr, arg, 0);
|
||
|
+
|
||
|
+ /* Swizzle the data pointer to our local copy and call! */
|
||
|
+ host_blkpg->data = &host_part;
|
||
|
+ ret = get_errno(ioctl(fd, ie->host_cmd, host_blkpg));
|
||
|
+
|
||
|
+out:
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||
|
int fd, abi_long cmd, abi_long arg)
|
||
|
{
|
||
|
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
|
||
|
index 56e344c..a730c87 100644
|
||
|
--- a/linux-user/syscall_types.h
|
||
|
+++ b/linux-user/syscall_types.h
|
||
|
@@ -260,4 +260,4 @@ STRUCT(blkpg_ioctl_arg,
|
||
|
TYPE_INT, /* op */
|
||
|
TYPE_INT, /* flags */
|
||
|
TYPE_INT, /* datalen */
|
||
|
- MK_PTR(MK_STRUCT(STRUCT_blkpg_partition))) /* data */
|
||
|
+ TYPE_PTRVOID) /* data */
|