Add statx

Fix netlink with IFLA_BR_MULTI_BOOLOPT
 Fix mips (EXCP_FPE, struct flock)
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAl0bcq4SHGxhdXJlbnRA
 dml2aWVyLmV1AAoJEPMMOL0/L748w5cP/0XQefv2ryHm2qXgXR457cRkdPYdjwus
 ybdM3jMZyWJwzMzdEw67inYcDzdyomKaf4NWpFa7mPv13+Gtn8aNpSmOf9+TXlLx
 VQIfM98BSnWW8rI+zTtNOzeUbfMC/19ZVHEfOi24InoomvdaBatiw93daU/2dfdR
 vaq/KNjjwMQxca5pRI12nFUxhsuDhy4A/Mhdhpg3tLcq664LRGY+LmFRWGbsKG6Q
 BAG/wXA4PhMMfubIKobzPgENV/xl3Xiwnc20iH9Or2d6SXGKGfvuEA8GAghNjrhi
 6KZN+0quCAByWcLH7ZjlVFKS5F4ahg59EZPyWi95bTl2yJUi50CBLFrQ4z/lhXp/
 0rWaWseB0sLQCy4TXDBEJLfXTGySWywjvg+pGJ3mO01j0zCW7lBO8w3PmBKTYSgb
 Uwzem3HOOxbeC3zT/TF72iWxieNXIVMYZMJUEhjdW9+rDDB1ornPFkVTS4h1LwKO
 zYL+haKW7EZRnf6Xvpi2QEMziQQ9Zit7yCPn/w7qWNmRZYxOrFgx6KyrJlw+vLBx
 7iFFJVTxDyqYOmEntd/QopYXFdsI1ftvWMQmzT3lN1EyBvl+3weWdUYG4nV9inof
 qieSv9kN5BavMwV1fhotvxoivYZ4dmftmT6a4MmA515hQVrdlORIC42mQdkNAGSX
 Ty3u1u/M0pNP
 =NG1X
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-4.1-pull-request' into staging

Add statx
Fix netlink with IFLA_BR_MULTI_BOOLOPT
Fix mips (EXCP_FPE, struct flock)

# gpg: Signature made Tue 02 Jul 2019 16:05:18 BST
# gpg:                using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg:                issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F  5173 F30C 38BD 3F2F BE3C

* remotes/vivier2/tags/linux-user-for-4.1-pull-request:
  linux-user: move QEMU_IFLA_BR_MULTI_BOOLOPT to the good function
  linux-user: Handle EXCP_FPE properly for MIPS
  linux-user: Introduce TARGET_HAVE_ARCH_STRUCT_FLOCK
  linux-user: Fix target_flock structure for MIPS O64 ABI
  linux-user: Add support for strace for statx() syscall
  linux-user: Add support for translation of statx() syscall

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-07-03 17:22:06 +01:00
commit 2b40d231ae
8 changed files with 283 additions and 12 deletions

View File

@ -483,6 +483,12 @@ static abi_long host_to_target_data_bridge_nlattr(struct nlattr *nlattr,
case QEMU_IFLA_BR_ROOT_ID:
case QEMU_IFLA_BR_BRIDGE_ID:
break;
/* br_boolopt_multi { uint32_t, uint32_t } */
case QEMU_IFLA_BR_MULTI_BOOLOPT:
u32 = NLA_DATA(nlattr);
u32[0] = tswap32(u32[0]); /* optval */
u32[1] = tswap32(u32[1]); /* optmask */
break;
default:
gemu_log("Unknown QEMU_IFLA_BR type %d\n", nlattr->nla_type);
break;
@ -546,12 +552,6 @@ static abi_long host_to_target_slave_data_bridge_nlattr(struct nlattr *nlattr,
case QEMU_IFLA_BRPORT_ROOT_ID:
case QEMU_IFLA_BRPORT_BRIDGE_ID:
break;
/* br_boolopt_multi { uint32_t, uint32_t } */
case QEMU_IFLA_BR_MULTI_BOOLOPT:
u32 = NLA_DATA(nlattr);
u32[0] = tswap32(u32[0]); /* optval */
u32[1] = tswap32(u32[1]); /* optmask */
break;
default:
gemu_log("Unknown QEMU_IFLA_BRPORT type %d\n", nlattr->nla_type);
break;

View File

@ -120,6 +120,7 @@ struct target_f_owner_ex {
#define TARGET_F_SHLCK 8
#endif
#ifndef TARGET_HAVE_ARCH_STRUCT_FLOCK
#ifndef TARGET_ARCH_FLOCK_PAD
#define TARGET_ARCH_FLOCK_PAD
#endif
@ -129,13 +130,12 @@ struct target_flock {
short l_whence;
abi_long l_start;
abi_long l_len;
#if defined(TARGET_MIPS)
abi_long l_sysid;
#endif
int l_pid;
TARGET_ARCH_FLOCK_PAD
};
#endif
#ifndef TARGET_HAVE_ARCH_STRUCT_FLOCK64
#ifndef TARGET_ARCH_FLOCK64_PAD
#define TARGET_ARCH_FLOCK64_PAD
#endif
@ -149,3 +149,5 @@ struct target_flock64 {
TARGET_ARCH_FLOCK64_PAD
};
#endif
#endif

View File

@ -540,6 +540,23 @@ done_syscall:
info.si_code = TARGET_ILL_ILLOPC;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case EXCP_FPE:
info.si_signo = TARGET_SIGFPE;
info.si_errno = 0;
info.si_code = TARGET_FPE_FLTUNK;
if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) {
info.si_code = TARGET_FPE_FLTINV;
} else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_DIV0) {
info.si_code = TARGET_FPE_FLTDIV;
} else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_OVERFLOW) {
info.si_code = TARGET_FPE_FLTOVF;
} else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_UNDERFLOW) {
info.si_code = TARGET_FPE_FLTUND;
} else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INEXACT) {
info.si_code = TARGET_FPE_FLTRES;
}
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
/* The code below was inspired by the MIPS Linux kernel trap
* handling code in arch/mips/kernel/traps.c.
*/

View File

@ -27,8 +27,21 @@
#define TARGET_F_SETOWN 24 /* for sockets. */
#define TARGET_F_GETOWN 23 /* for sockets. */
#define TARGET_ARCH_FLOCK_PAD abi_long pad[4];
#define TARGET_ARCH_FLOCK64_PAD
#if (TARGET_ABI_BITS == 32)
struct target_flock {
short l_type;
short l_whence;
abi_long l_start;
abi_long l_len;
abi_long l_sysid;
int l_pid;
abi_long pad[4];
};
#define TARGET_HAVE_ARCH_STRUCT_FLOCK
#endif
#define TARGET_F_GETLK64 33 /* using 'struct flock64' */
#define TARGET_F_SETLK64 34

View File

@ -976,6 +976,76 @@ UNUSED static struct flags msg_flags[] = {
FLAG_END,
};
UNUSED static struct flags statx_flags[] = {
#ifdef AT_EMPTY_PATH
FLAG_GENERIC(AT_EMPTY_PATH),
#endif
#ifdef AT_NO_AUTOMOUNT
FLAG_GENERIC(AT_NO_AUTOMOUNT),
#endif
#ifdef AT_SYMLINK_NOFOLLOW
FLAG_GENERIC(AT_SYMLINK_NOFOLLOW),
#endif
#ifdef AT_STATX_SYNC_AS_STAT
FLAG_GENERIC(AT_STATX_SYNC_AS_STAT),
#endif
#ifdef AT_STATX_FORCE_SYNC
FLAG_GENERIC(AT_STATX_FORCE_SYNC),
#endif
#ifdef AT_STATX_DONT_SYNC
FLAG_GENERIC(AT_STATX_DONT_SYNC),
#endif
FLAG_END,
};
UNUSED static struct flags statx_mask[] = {
/* This must come first, because it includes everything. */
#ifdef STATX_ALL
FLAG_GENERIC(STATX_ALL),
#endif
/* This must come second; it includes everything except STATX_BTIME. */
#ifdef STATX_BASIC_STATS
FLAG_GENERIC(STATX_BASIC_STATS),
#endif
#ifdef STATX_TYPE
FLAG_GENERIC(STATX_TYPE),
#endif
#ifdef STATX_MODE
FLAG_GENERIC(STATX_MODE),
#endif
#ifdef STATX_NLINK
FLAG_GENERIC(STATX_NLINK),
#endif
#ifdef STATX_UID
FLAG_GENERIC(STATX_UID),
#endif
#ifdef STATX_GID
FLAG_GENERIC(STATX_GID),
#endif
#ifdef STATX_ATIME
FLAG_GENERIC(STATX_ATIME),
#endif
#ifdef STATX_MTIME
FLAG_GENERIC(STATX_MTIME),
#endif
#ifdef STATX_CTIME
FLAG_GENERIC(STATX_CTIME),
#endif
#ifdef STATX_INO
FLAG_GENERIC(STATX_INO),
#endif
#ifdef STATX_SIZE
FLAG_GENERIC(STATX_SIZE),
#endif
#ifdef STATX_BLOCKS
FLAG_GENERIC(STATX_BLOCKS),
#endif
#ifdef STATX_BTIME
FLAG_GENERIC(STATX_BTIME),
#endif
FLAG_END,
};
/*
* print_xxx utility functions. These are used to print syscall
* parameters in certain format. All of these have parameter
@ -2611,6 +2681,22 @@ print_tgkill(const struct syscallname *name,
}
#endif
#ifdef TARGET_NR_statx
static void
print_statx(const struct syscallname *name,
abi_long arg0, abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5)
{
print_syscall_prologue(name);
print_at_dirfd(arg0, 0);
print_string(arg1, 0);
print_flags(statx_flags, arg2, 0);
print_flags(statx_mask, arg3, 0);
print_pointer(arg4, 1);
print_syscall_epilogue(name);
}
#endif
/*
* An array of all of the syscalls we know about
*/

View File

@ -1650,3 +1650,6 @@
#ifdef TARGET_NR_atomic_barrier
{ TARGET_NR_atomic_barrier, "atomic_barrier", NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_statx
{ TARGET_NR_statx, "statx", NULL, print_statx, NULL },
#endif

View File

@ -238,6 +238,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
#define __NR_sys_inotify_init __NR_inotify_init
#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
#define __NR_sys_statx __NR_statx
#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__)
#define __NR__llseek __NR_lseek
@ -316,6 +317,14 @@ _syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
unsigned long, idx1, unsigned long, idx2)
#endif
/*
* It is assumed that struct statx is architecture independent.
*/
#if defined(TARGET_NR_statx) && defined(__NR_statx)
_syscall5(int, sys_statx, int, dirfd, const char *, pathname, int, flags,
unsigned int, mask, struct target_statx *, statxbuf)
#endif
static bitmask_transtbl fcntl_flags_tbl[] = {
{ TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
{ TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
@ -6516,6 +6525,48 @@ static inline abi_long host_to_target_stat64(void *cpu_env,
}
#endif
#if defined(TARGET_NR_statx) && defined(__NR_statx)
static inline abi_long host_to_target_statx(struct target_statx *host_stx,
abi_ulong target_addr)
{
struct target_statx *target_stx;
if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr, 0)) {
return -TARGET_EFAULT;
}
memset(target_stx, 0, sizeof(*target_stx));
__put_user(host_stx->stx_mask, &target_stx->stx_mask);
__put_user(host_stx->stx_blksize, &target_stx->stx_blksize);
__put_user(host_stx->stx_attributes, &target_stx->stx_attributes);
__put_user(host_stx->stx_nlink, &target_stx->stx_nlink);
__put_user(host_stx->stx_uid, &target_stx->stx_uid);
__put_user(host_stx->stx_gid, &target_stx->stx_gid);
__put_user(host_stx->stx_mode, &target_stx->stx_mode);
__put_user(host_stx->stx_ino, &target_stx->stx_ino);
__put_user(host_stx->stx_size, &target_stx->stx_size);
__put_user(host_stx->stx_blocks, &target_stx->stx_blocks);
__put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask);
__put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec);
__put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec);
__put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_atime.tv_sec);
__put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_atime.tv_nsec);
__put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_atime.tv_sec);
__put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_atime.tv_nsec);
__put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_atime.tv_sec);
__put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_atime.tv_nsec);
__put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major);
__put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor);
__put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major);
__put_user(host_stx->stx_dev_minor, &target_stx->stx_dev_minor);
unlock_user_struct(target_stx, target_addr, 1);
return 0;
}
#endif
/* ??? Using host futex calls even when target atomic operations
are not really atomic probably breaks things. However implementing
futexes locally would make futexes shared between multiple processes
@ -7094,7 +7145,8 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
abi_long ret;
#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
|| defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
|| defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64)
|| defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \
|| defined(TARGET_NR_statx)
struct stat st;
#endif
#if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
@ -10172,6 +10224,67 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
ret = host_to_target_stat64(cpu_env, arg3, &st);
return ret;
#endif
#if defined(TARGET_NR_statx)
case TARGET_NR_statx:
{
struct target_statx *target_stx;
int dirfd = arg1;
int flags = arg3;
p = lock_user_string(arg2);
if (p == NULL) {
return -TARGET_EFAULT;
}
#if defined(__NR_statx)
{
/*
* It is assumed that struct statx is architecture independent.
*/
struct target_statx host_stx;
int mask = arg4;
ret = get_errno(sys_statx(dirfd, p, flags, mask, &host_stx));
if (!is_error(ret)) {
if (host_to_target_statx(&host_stx, arg5) != 0) {
unlock_user(p, arg2, 0);
return -TARGET_EFAULT;
}
}
if (ret != -TARGET_ENOSYS) {
unlock_user(p, arg2, 0);
return ret;
}
}
#endif
ret = get_errno(fstatat(dirfd, path(p), &st, flags));
unlock_user(p, arg2, 0);
if (!is_error(ret)) {
if (!lock_user_struct(VERIFY_WRITE, target_stx, arg5, 0)) {
return -TARGET_EFAULT;
}
memset(target_stx, 0, sizeof(*target_stx));
__put_user(major(st.st_dev), &target_stx->stx_dev_major);
__put_user(minor(st.st_dev), &target_stx->stx_dev_minor);
__put_user(st.st_ino, &target_stx->stx_ino);
__put_user(st.st_mode, &target_stx->stx_mode);
__put_user(st.st_uid, &target_stx->stx_uid);
__put_user(st.st_gid, &target_stx->stx_gid);
__put_user(st.st_nlink, &target_stx->stx_nlink);
__put_user(major(st.st_rdev), &target_stx->stx_rdev_major);
__put_user(minor(st.st_rdev), &target_stx->stx_rdev_minor);
__put_user(st.st_size, &target_stx->stx_size);
__put_user(st.st_blksize, &target_stx->stx_blksize);
__put_user(st.st_blocks, &target_stx->stx_blocks);
__put_user(st.st_atime, &target_stx->stx_atime.tv_sec);
__put_user(st.st_mtime, &target_stx->stx_mtime.tv_sec);
__put_user(st.st_ctime, &target_stx->stx_ctime.tv_sec);
unlock_user_struct(target_stx, arg5, 1);
}
}
return ret;
#endif
#ifdef TARGET_NR_lchown
case TARGET_NR_lchown:
if (!(p = lock_user_string(arg1)))

View File

@ -2537,4 +2537,41 @@ struct target_user_cap_data {
/* Return size of the log buffer */
#define TARGET_SYSLOG_ACTION_SIZE_BUFFER 10
struct target_statx_timestamp {
int64_t tv_sec;
uint32_t tv_nsec;
int32_t __reserved;
};
struct target_statx {
/* 0x00 */
uint32_t stx_mask; /* What results were written [uncond] */
uint32_t stx_blksize; /* Preferred general I/O size [uncond] */
uint64_t stx_attributes; /* Flags conveying information about the file */
/* 0x10 */
uint32_t stx_nlink; /* Number of hard links */
uint32_t stx_uid; /* User ID of owner */
uint32_t stx_gid; /* Group ID of owner */
uint16_t stx_mode; /* File mode */
uint16_t __spare0[1];
/* 0x20 */
uint64_t stx_ino; /* Inode number */
uint64_t stx_size; /* File size */
uint64_t stx_blocks; /* Number of 512-byte blocks allocated */
uint64_t stx_attributes_mask; /* Mask to show what is supported */
/* 0x40 */
struct target_statx_timestamp stx_atime; /* Last access time */
struct target_statx_timestamp stx_btime; /* File creation time */
struct target_statx_timestamp stx_ctime; /* Last attribute change time */
struct target_statx_timestamp stx_mtime; /* Last data modification time */
/* 0x80 */
uint32_t stx_rdev_major; /* Device ID of special file [if bdev/cdev] */
uint32_t stx_rdev_minor;
uint32_t stx_dev_major; /* ID of device containing file [uncond] */
uint32_t stx_dev_minor;
/* 0x90 */
uint64_t __spare2[14]; /* Spare space for future expansion */
/* 0x100 */
};
#endif