Commit a59b5e35 authored by Alexander Graf's avatar Alexander Graf Committed by Riku Voipio
Browse files

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.

This patch fixes running parted for me.

Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
Signed-off-by: default avatarRiku Voipio <riku.voipio@linaro.org>
parent 40645c7b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -78,7 +78,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
+53 −0
Original line number Diff line number Diff line
@@ -3696,6 +3696,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)
{
+1 −1
Original line number Diff line number Diff line
@@ -252,4 +252,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 */