[PATCH] linux-user: Protect btrfs ioctl target definitions
Target definitions of btrfs ioctls in 'syscall_defs.h' use the value BTRFS_IOCTL_MAGIC that is defined header 'btrfs.h'. This header is not available in kernel versions before 3.9. For that reason, these target ioctl definitions should be enwrapped in an #ifdef directive to check whether the 'btrfs.h' header is available as to not cause build errors on older Linux systems. Signed-off-by: Filip Bozuta --- linux-user/syscall_defs.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 33a414c50f..731c3d5341 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -1006,6 +1006,7 @@ struct target_rtc_pll_info { #define TARGET_FS_IOC32_SETVERSION TARGET_IOW('v', 2, int) /* btrfs ioctls */ +#ifdef CONFIG_BTRFS #define TARGET_BTRFS_IOC_SNAP_CREATETARGET_IOWU(BTRFS_IOCTL_MAGIC, 1) #define TARGET_BTRFS_IOC_SCAN_DEV TARGET_IOWU(BTRFS_IOCTL_MAGIC, 4) #define TARGET_BTRFS_IOC_FORGET_DEV TARGET_IOWU(BTRFS_IOCTL_MAGIC, 5) @@ -1041,6 +1042,7 @@ struct target_rtc_pll_info { #define TARGET_BTRFS_IOC_GET_SUBVOL_INFOTARGET_IORU(BTRFS_IOCTL_MAGIC, 60) #define TARGET_BTRFS_IOC_GET_SUBVOL_ROOTREF TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 61) #define TARGET_BTRFS_IOC_INO_LOOKUP_USER TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 62) +#endif /* usb ioctls */ #define TARGET_USBDEVFS_CONTROL TARGET_IOWRU('U', 0) -- 2.17.1
Re: [PULL 0/8] Linux user for 5.2 patches
On 1.9.20. 15:06, Peter Maydell wrote: On Mon, 31 Aug 2020 at 12:08, Laurent Vivier wrote: The following changes since commit 39335fab59e11cfda9b7cf63929825db2dd3a3e0: Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.2-pull-= request' into staging (2020-08-28 22:30:11 +0100) are available in the Git repository at: git://github.com/vivier/qemu.git tags/linux-user-for-5.2-pull-request for you to fetch changes up to d6676fc62a52e020df32abf927c2e7183781a2e3: linux-user: Add support for btrfs ioctls used to scrub a filesystem (2020-0= 8-29 10:14:52 +0200) Add btrfs support Fails to build with clang, I'm afraid: In file included from ../../linux-user/syscall.c:4561: ../../linux-user/syscall_types.h:485:33: error: implicit conversion from enumeration type 'enum btrfs_dev_stat_values' to different enumeration type 'argtype' (aka 'enum argtype') [-Werror,-Wenum-conversion] MK_ARRAY(TYPE_ULONGLONG, BTRFS_DEV_STAT_VALUES_MAX), /* values */ ~^~~~ /home/petmay01/linaro/qemu-for-merges/include/exec/user/thunk.h:45:42: note: expanded from macro 'MK_ARRAY' #define MK_ARRAY(type, size) TYPE_ARRAY, size, type ^~~~ ../../linux-user/syscall.c:4559:79: note: expanded from macro 'STRUCT' #define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL }; ~ ^~~ 1 error generated. There seems to be a problem because 'BTRFS_DEV_STAT_VALUES_MAX' is not a predefined value but an enum value from from 'enum btrfs_dev_stat_values': https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/btrfs.h#L668 The build problem arises probably when 'thunk_convert()' tries to convert this enum value to the thunk enum values 'argtype'. I will see about finding a work around for this or maybe use a STRUCT_SPECIAL() for 'struct btrfs_ioctl_get_dev_stats' to define an explicit converting function. Just curious, on what linux distro are you building on? I didn't come accross this build issue on my system. thanks -- PMM
Re: [PATCH] linux-user: fix target_to_host_timespec64()
On 27.8.20. 09:04, Laurent Vivier wrote: in 32 bit mode, drop the padding in tv_nsec. If host is 64bit and target is 32bit, the padding bytes will be copied from the target and as the kernel checks the value, the syscall exits with EINVAL. Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index c82b73e03234..9d7376734ad4 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1253,6 +1253,8 @@ static inline abi_long target_to_host_timespec64(struct timespec *host_ts, } __get_user(host_ts->tv_sec, _ts->tv_sec); __get_user(host_ts->tv_nsec, _ts->tv_nsec); +/* in 32bit mode, this drops the padding */ +host_ts->tv_nsec = (long)(abi_long)host_ts->tv_nsec; I tested this with sh4 and the nsec conversion seems to be working fine now. Just curious, why a double cast is needed '(long)(abi_long)', why not just '(abi_long)'? unlock_user_struct(target_ts, target_addr, 0); return 0; }
[PATCH v2 1/2] linux-user: Modify 'recvmmsg()' implementation
Implementation of syscall 'recvmmsg()' in file 'syscall.c' uses a loop over 'recvmsg()' to receive each individual message from a socket. However, the implementation ignores the timeout argument. This patch changes that by introducing a timeout check after each received message. Implementation notes: Function 'clock_gettime()' is used to check the time before messages start getting received. After each message is received, 'clock_gettime()' is called and used to check whether the timeout is expired. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 45 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 05f03919ff..dc89bfacca 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3197,21 +3197,36 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec, unsigned int vlen, unsigned int flags, -int send) +abi_ulong timeout, int send) { struct target_mmsghdr *mmsgp; +struct timespec ts, end_time, curr_time; abi_long ret = 0; int i; if (vlen > UIO_MAXIOV) { vlen = UIO_MAXIOV; } - mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1); if (!mmsgp) { return -TARGET_EFAULT; } +if (timeout) { +if (target_to_host_timespec(, timeout)) { +return -TARGET_EFAULT; +} +if (ts.tv_sec < 0 || ts.tv_nsec < 0 || ts.tv_nsec > 10) { +return -TARGET_EINVAL; +} +clock_gettime(CLOCK_REALTIME, _time); +end_time.tv_sec = curr_time.tv_sec + ts.tv_sec; +end_time.tv_nsec = curr_time.tv_nsec + ts.tv_nsec; +if (end_time.tv_nsec > 10) { +end_time.tv_nsec -= 10; +end_time.tv_sec++; +} +} for (i = 0; i < vlen; i++) { ret = do_sendrecvmsg_locked(fd, [i].msg_hdr, flags, send); if (is_error(ret)) { @@ -3222,6 +3237,20 @@ static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec, if (flags & MSG_WAITFORONE) { flags |= MSG_DONTWAIT; } +/* + * For recvmmsg() the timeout is checked only after a datagram is + * received.This is an existing bug in the kernel for this syscall: + * https://man7.org/linux/man-pages/man2/recvmmsg.2.html#BUGS + */ +if (timeout) { +clock_gettime(CLOCK_REALTIME, _time); +if (curr_time.tv_sec > end_time.tv_sec || +(curr_time.tv_sec == end_time.tv_sec && +curr_time.tv_nsec >= end_time.tv_nsec)) { +i++; +break; +} +} } unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i); @@ -3477,7 +3506,7 @@ static abi_long do_socketcall(int num, abi_ulong vptr) [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */ [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */ [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */ -[TARGET_SYS_RECVMMSG] = 4,/* fd, msgvec, vlen, flags */ +[TARGET_SYS_RECVMMSG] = 5,/* fd, msgvec, vlen, flags, timeout */ [TARGET_SYS_SENDMMSG] = 4,/* fd, msgvec, vlen, flags */ }; abi_long a[6]; /* max 6 args */ @@ -3536,10 +3565,10 @@ static abi_long do_socketcall(int num, abi_ulong vptr) return do_sendrecvmsg(a[0], a[1], a[2], 0); case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */ return do_accept4(a[0], a[1], a[2], a[3]); -case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */ -return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0); +case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags, timeout */ +return do_sendrecvmmsg(a[0], a[1], a[2], a[3], a[4], 0); case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */ -return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1); +return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0, 1); default: qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num); return -TARGET_EINVAL; @@ -9343,11 +9372,11 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_sendmmsg case TARGET_NR_sendmmsg: -return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1); +return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0, 1); #endif #ifdef TARGET_NR_recvmmsg case TARGET_NR_recvmmsg: -return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0); +return do_sendrecvmmsg(arg1, arg2, arg3, arg4, arg5, 0); #endif #ifdef TARGET_NR_sendto case TARGET_NR_sendto: -- 2.25.1
[PATCH v2 2/2] linux-user: Add support for 'recvmmsg_time64()'
This patch introduces functionality for syscall: *recvmmsg_time64 This syscall is a 2038 safe variant for syscall: int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout) --receive multiple messages on a socket-- man page: https://man7.org/linux/man-pages/man2/recvmmsg.2.html Implementation notes: Function 'do_sendrecvmmsg()' in 'syscall.c' was changed with the addition of a new argument 'time64' which represents a flag by which the function knows what kind of 'struct timespec' converting function to call ('target_to_host_timespec() or 'target_to_host_timespec64()'). It is false in case of 'TARGET_NR_recvmmsg' and true in case of 'TARGET_NR_recvmmsg_time64'. In 'do_socketcall()', the 'TARGET_ABI_BITS' was checked to know what value for 'time64' argument to pass. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 27 +++ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index dc89bfacca..762eea0e5b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3197,7 +3197,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec, unsigned int vlen, unsigned int flags, -abi_ulong timeout, int send) +abi_ulong timeout, bool time64, int send) { struct target_mmsghdr *mmsgp; struct timespec ts, end_time, curr_time; @@ -3212,8 +3212,14 @@ static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec, return -TARGET_EFAULT; } if (timeout) { -if (target_to_host_timespec(, timeout)) { -return -TARGET_EFAULT; +if (time64) { +if (target_to_host_timespec64(, timeout)) { +return -TARGET_EFAULT; +} +} else { +if (target_to_host_timespec(, timeout)) { +return -TARGET_EFAULT; +} } if (ts.tv_sec < 0 || ts.tv_nsec < 0 || ts.tv_nsec > 10) { return -TARGET_EINVAL; @@ -3506,7 +3512,7 @@ static abi_long do_socketcall(int num, abi_ulong vptr) [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */ [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */ [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */ -[TARGET_SYS_RECVMMSG] = 5,/* fd, msgvec, vlen, flags, timeout */ +[TARGET_SYS_RECVMMSG] = 6,/* fd, msgvec, vlen, flags, timeout */ [TARGET_SYS_SENDMMSG] = 4,/* fd, msgvec, vlen, flags */ }; abi_long a[6]; /* max 6 args */ @@ -3566,9 +3572,10 @@ static abi_long do_socketcall(int num, abi_ulong vptr) case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */ return do_accept4(a[0], a[1], a[2], a[3]); case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags, timeout */ -return do_sendrecvmmsg(a[0], a[1], a[2], a[3], a[4], 0); +return do_sendrecvmmsg(a[0], a[1], a[2], a[3], a[4], + TARGET_ABI_BITS == 64, 0); case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */ -return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0, 1); +return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0, false, 1); default: qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num); return -TARGET_EINVAL; @@ -9372,11 +9379,15 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_sendmmsg case TARGET_NR_sendmmsg: -return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0, 1); +return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0, false, 1); #endif #ifdef TARGET_NR_recvmmsg case TARGET_NR_recvmmsg: -return do_sendrecvmmsg(arg1, arg2, arg3, arg4, arg5, 0); +return do_sendrecvmmsg(arg1, arg2, arg3, arg4, arg5, false, 0); +#endif +#ifdef TARGET_NR_recvmmsg_time64 +case TARGET_NR_recvmmsg_time64: +return do_sendrecvmmsg(arg1, arg2, arg3, arg4, arg5, true, 0); #endif #ifdef TARGET_NR_sendto case TARGET_NR_sendto: -- 2.25.1
[PATCH v2 0/2] linux-user: Introducing support for 'recvmmsg_time64()'
This patch introduces functionality for 'recvmmsg_time64()' which is a year 2038 safe variant of 'recvmmsg()'. This new time64 syscall is introduced in series of two patches rather than in one patch because a little modification was needed before the syscall could be introduced properly. The first patch in the series introduces a little fix in the implementation of 'recvmmsg()' that introduces the timeout argument which is of type 'struct timespec' for which the separate time64 variant is added. The second patch in the series introduces the implementation of 'recvmmsg_time64()'. Testing method: The implementation was tested using existing tests from the LTP test suite which was build inside a chroot. Filip Bozuta (2): linux-user: Modify 'recvmmsg()' implementation linux-user: Add support for 'recvmmsg_time64()' linux-user/syscall.c | 56 +--- 1 file changed, 48 insertions(+), 8 deletions(-) -- 2.25.1
[PATCH v2 1/2] linux-user: Add support for ppoll_time64() and pselect6_time64()
This patch introduces functionality for following time64 syscalls: *ppoll_time64 This is a year 2038 safe variant of: int poll(struct pollfd *fds, nfds_t nfds, int timeout) -- wait for some event on a file descriptor -- man page: https://man7.org/linux/man-pages/man2/ppoll.2.html *pselect6_time64 This is a year 2038 safe variant of: int pselect6(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask); -- synchronous I/O multiplexing -- man page: https://man7.org/linux/man-pages/man2/pselect6.2.html Implementation notes: Year 2038 safe syscalls in this patch were implemented with the same code as their regular variants (ppoll() and pselect()). This code was moved to new functions ('do_ppoll()' and 'do_pselect6()') that take a 'bool time64' from which a right 'struct timespec' converting function is called. (target_to_host/host_to_target_timespec() for regular and target_to_host/host_to_target_timespec64() for time64 variants) Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 462 +++ 1 file changed, 251 insertions(+), 211 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1211e759c2..fc6a6e32e4 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -397,7 +397,7 @@ static int sys_getcwd1(char *buf, size_t size) return strlen(buf)+1; } -#ifdef TARGET_NR_utimensat +#if defined(TARGET_NR_utimensat) #if defined(__NR_utimensat) #define __NR_sys_utimensat __NR_utimensat _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, @@ -763,11 +763,11 @@ safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \ int, options, struct rusage *, rusage) safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp) #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \ -defined(TARGET_NR_pselect6) +defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64) safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \ fd_set *, exceptfds, struct timespec *, timeout, void *, sig) #endif -#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_poll) +#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64) safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds, struct timespec *, tsp, const sigset_t *, sigmask, size_t, sigsetsize) @@ -984,7 +984,7 @@ abi_long do_brk(abi_ulong new_brk) } #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \ -defined(TARGET_NR_pselect6) +defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64) static inline abi_long copy_from_user_fdset(fd_set *fds, abi_ulong target_fds_addr, int n) @@ -1252,7 +1252,8 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts, } #endif -#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) +#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \ +defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64) static inline abi_long target_to_host_timespec64(struct timespec *host_ts, abi_ulong target_addr) { @@ -1458,6 +1459,237 @@ static abi_long do_old_select(abi_ulong arg1) #endif #endif +#if defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64) +static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3, +abi_long arg4, abi_long arg5, abi_long arg6, +bool time64) +{ +abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr; +fd_set rfds, wfds, efds; +fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; +struct timespec ts, *ts_ptr; +abi_long ret; + +/* + * The 6th arg is actually two args smashed together, + * so we cannot use the C library. + */ +sigset_t set; +struct { +sigset_t *set; +size_t size; +} sig, *sig_ptr; + +abi_ulong arg_sigset, arg_sigsize, *arg7; +target_sigset_t *target_sigset; + +n = arg1; +rfd_addr = arg2; +wfd_addr = arg3; +efd_addr = arg4; +ts_addr = arg5; + +ret = copy_from_user_fdset_ptr(, _ptr, rfd_addr, n); +if (ret) { +return ret; +} +ret = copy_from_user_fdset_ptr(, _ptr, wfd_addr, n); +if (ret) { +return ret; +} +ret = copy_from_user_fdset_ptr(, _ptr, efd_addr, n); +if (ret) { +return ret; +} + +/* + * This takes a timespec, and not a timeval, so we cannot + * use the do_select() helper ... + */ +if (ts_addr) { +if (time64) { +if (target_to_host_timespec64(, ts_addr)) { +return -TARGET_EFAULT
[PATCH v2 0/2] linux-user: Adding support for a group of 4 time64 syscalls
This two patch series introduces functionality for following Year 2038 safe syscalls: --Introduced in first patch-- *ppoll_time64() *pselect6_time64() --Introduced in second patch-- *utimensat_time64() *semtimedop_time64() Testing notes: The implementations of these time64 syscalls was tested using tests from the LTP test suite which was built inside a chroot. v2: -Moved code of 'ppoll()' and 'pselect6()' to a separate function -Changed 'time64' from 'int' to 'bool' Filip Bozuta (2): linux-user: Add support for ppoll_time64() and pselect6_time64() linux-user: Add support for utimensat_time64() and semtimedop_time64() linux-user/syscall.c | 520 +-- 1 file changed, 300 insertions(+), 220 deletions(-) -- 2.25.1
[PATCH v2 2/2] linux-user: Add support for utimensat_time64() and semtimedop_time64()
This patch introduces functionality for following time64 syscalls: *utimensat_time64() int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags); -- change file timestamps with nanosecond precision -- man page: https://man7.org/linux/man-pages/man2/utimensat.2.html *semtimedop_time64() int semtimedop(int semid, struct sembuf *sops, size_t nsops, const struct timespec *timeout); -- System V semaphore operations -- man page: https://www.man7.org/linux/man-pages/man2/semtimedop.2.html Implementation notes: Syscall 'utimensat_time64()' is implemented in similar way as its regular variants only difference being that time64 converting function is used to convert values of 'struct timespec' between host and target ('target_to_host_timespec64()'). For syscall 'semtimedop_time64()' and additional argument is added in function 'do_semtimedop()' through which the aproppriate 'struct timespec' converting function is called (false for regular target_to_host_timespec() and true for target_to_host_timespec64()). For 'do_ipc()' a check was added as that additional argument: 'TARGET_ABI_BITS == 64'. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/syscall.c | 60 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index fc6a6e32e4..4d460af744 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1253,7 +1253,8 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts, #endif #if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \ -defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64) +defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64) || \ +defined(TARGET_NR_utimensat_time64) || defined(TARGET_NR_semtimedop_time64) static inline abi_long target_to_host_timespec64(struct timespec *host_ts, abi_ulong target_addr) { @@ -4117,7 +4118,7 @@ static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, } #if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \ -defined(TARGET_NR_semtimedop) +defined(TARGET_NR_semtimedop) || defined(TARGET_NR_semtimedop_time64) /* * This macro is required to handle the s390 variants, which passes the @@ -4134,7 +4135,7 @@ static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, static inline abi_long do_semtimedop(int semid, abi_long ptr, unsigned nsops, - abi_long timeout) + abi_long timeout, bool time64) { struct sembuf sops[nsops]; struct timespec ts, *pts = NULL; @@ -4142,8 +4143,14 @@ static inline abi_long do_semtimedop(int semid, if (timeout) { pts = -if (target_to_host_timespec(pts, timeout)) { -return -TARGET_EFAULT; +if (time64) { +if (target_to_host_timespec64(pts, timeout)) { +return -TARGET_EFAULT; +} +} else { +if (target_to_host_timespec(pts, timeout)) { +return -TARGET_EFAULT; +} } } @@ -4657,7 +4664,7 @@ static abi_long do_ipc(CPUArchState *cpu_env, switch (call) { case IPCOP_semop: -ret = do_semtimedop(first, ptr, second, 0); +ret = do_semtimedop(first, ptr, second, 0, false); break; case IPCOP_semtimedop: /* @@ -4667,9 +4674,9 @@ static abi_long do_ipc(CPUArchState *cpu_env, * to a struct timespec where the generic variant uses fifth parameter. */ #if defined(TARGET_S390X) -ret = do_semtimedop(first, ptr, second, third); +ret = do_semtimedop(first, ptr, second, third, TARGET_ABI_BITS == 64); #else -ret = do_semtimedop(first, ptr, second, fifth); +ret = do_semtimedop(first, ptr, second, fifth, TARGET_ABI_BITS == 64); #endif break; @@ -9887,11 +9894,15 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_semop case TARGET_NR_semop: -return do_semtimedop(arg1, arg2, arg3, 0); +return do_semtimedop(arg1, arg2, arg3, 0, false); #endif #ifdef TARGET_NR_semtimedop case TARGET_NR_semtimedop: -return do_semtimedop(arg1, arg2, arg3, arg4); +return do_semtimedop(arg1, arg2, arg3, arg4, false); +#endif +#ifdef TARGET_NR_semtimedop_time64 +case TARGET_NR_semtimedop_time64: +return do_semtimedop(arg1, arg2, arg3, arg4, true); #endif #ifdef TARGET_NR_semctl case TARGET_NR_semctl: @@ -11938,6 +11949,35 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef
[PATCH v3 2/2] linux-user: Add support for 'mq_timedsend_time64()' and 'mq_timedreceive_time64()'
This patch implements functionality for following time64 syscalls: *mq_timedsend_time64() This is a year 2038 safe vairant of syscall: int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout) --send a message to a message queue-- man page: https://www.man7.org/linux/man-pages/man2/mq_timedsend.2.html *mq_timedreceive_time64() This is a year 2038 safe variant of syscall: ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct timespec *abs_timeout) --receive a message from a message queue-- man page: https://man7.org/linux/man-pages/man3/mq_receive.3.html Implementation notes: These syscalls were implemented in similar ways like 'mq_timedsend()' and 'mq_timedreceive' except that functions 'target_to_host_timespec64()' and 'host_to_target_timespec64()' were used to convert values of 'struct timespec' between host and target. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/syscall.c | 58 +--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 4ee1de6e65..3331ec9fea 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -829,11 +829,13 @@ safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz, safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, unsigned, nsops, const struct timespec *, timeout) #endif -#ifdef TARGET_NR_mq_timedsend +#if defined(TARGET_NR_mq_timedsend) || \ +defined(TARGET_NR_mq_timedsend_time64) safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr, size_t, len, unsigned, prio, const struct timespec *, timeout) #endif -#ifdef TARGET_NR_mq_timedreceive +#if defined(TARGET_NR_mq_timedreceive) || \ +defined(TARGET_NR_mq_timedreceive_time64) safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr, size_t, len, unsigned *, prio, const struct timespec *, timeout) #endif @@ -1243,7 +1245,9 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts, } #endif -#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) +#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \ +defined(TARGET_NR_mq_timedsend_time64) || \ +defined(TARGET_NR_mq_timedreceive_time64) static inline abi_long target_to_host_timespec64(struct timespec *host_ts, abi_ulong target_addr) { @@ -11831,6 +11835,27 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_mq_timedsend_time64 +case TARGET_NR_mq_timedsend_time64: +{ +struct timespec ts; + +p = lock_user(VERIFY_READ, arg2, arg3, 1); +if (arg5 != 0) { +if (target_to_host_timespec64(, arg5)) { +return -TARGET_EFAULT; +} +ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, )); +if (!is_error(ret) && host_to_target_timespec64(arg5, )) { +return -TARGET_EFAULT; +} +} else { +ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL)); +} +unlock_user(p, arg2, arg3); +} +return ret; +#endif #ifdef TARGET_NR_mq_timedreceive case TARGET_NR_mq_timedreceive: @@ -11858,6 +11883,33 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_mq_timedreceive_time64 +case TARGET_NR_mq_timedreceive_time64: +{ +struct timespec ts; +unsigned int prio; + +p = lock_user(VERIFY_READ, arg2, arg3, 1); +if (arg5 != 0) { +if (target_to_host_timespec64(, arg5)) { +return -TARGET_EFAULT; +} +ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, + , )); +if (!is_error(ret) && host_to_target_timespec64(arg5, )) { +return -TARGET_EFAULT; +} +} else { +ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, + , NULL)); +} +unlock_user(p, arg2, arg3); +if (arg4 != 0) { +put_user_u32(prio, arg4); +} +} +return ret; +#endif /* Not implemented for now... */ /* case TARGET_NR_mq_notify: */ -- 2.25.1
[PATCH v3 1/2] linux-user: Fix 'mq_timedsend()' and 'mq_timedreceive()'
Implementations of syscalls 'mq_timedsend()' and 'mq_timedreceive()' in 'syscall.c' use functions 'target_to_host_timespec()' and 'host_to_target_timespec()' to transfer the value of 'struct timespec' between target and host. However, the implementations don't check whether this conversion succeeds and thus can cause an unaproppriate error instead of the 'EFAULT (Bad address)' which is supposed to be set if the conversion from target to host fails. This was confirmed with the modified LTP test suite where test cases with a bad adress for 'timespec' were added. This modified test suite can be found at: https://github.com/bozutaf/ltp Without the changes from this patch the bad adress testcase for 'mq_timedsend()' succeds unexpectedly, while the test returns errno 'ETIMEOUT' for 'mq_timedreceive()': mq_timedsend01.c:190: FAIL: mq_timedsend() returned 0, expected -1: SUCCESS (0) mq_timedreceive01.c:178: FAIL: mq_timedreceive() failed unexpectedly, expected EFAULT: ETIMEDOUT (110) After the changes from this patch, testcases for both syscalls fail with EFAULT as expected, which is the same test result that is received with native execution: mq_timedsend01.c:187: PASS: mq_timedsend() failed expectedly: EFAULT (14) mq_timedreceive01.c:180: PASS: mq_timedreceive() failed expectedly: EFAULT (14) (Patch with this new test case will be sent to LTP mailing list soon) Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 16 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 05f03919ff..4ee1de6e65 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -11817,9 +11817,13 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, p = lock_user (VERIFY_READ, arg2, arg3, 1); if (arg5 != 0) { -target_to_host_timespec(, arg5); +if (target_to_host_timespec(, arg5)) { +return -TARGET_EFAULT; +} ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, )); -host_to_target_timespec(arg5, ); +if (!is_error(ret) && host_to_target_timespec(arg5, )) { +return -TARGET_EFAULT; +} } else { ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL)); } @@ -11836,10 +11840,14 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, p = lock_user (VERIFY_READ, arg2, arg3, 1); if (arg5 != 0) { -target_to_host_timespec(, arg5); +if (target_to_host_timespec(, arg5)) { +return -TARGET_EFAULT; +} ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, , )); -host_to_target_timespec(arg5, ); +if (!is_error(ret) && host_to_target_timespec(arg5, )) { +return -TARGET_EFAULT; +} } else { ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, , NULL)); -- 2.25.1
[PATCH v3 0/2] linux-user: Introducing functionality for two time64 syscalls
This two patch series introduces functionality for two year 2038 safe syscalls. The first patch introduces a little correction for already implemented normal (32-bit) variants of implemented syscalls. The second patch introduces the implementation of the syscalls. Testing method: The implementation of the implemented syscalls was tested using recently added time64 test in the LTP test suite. v3: -Added an error check before converting back the value of 'struct timespec/timespec64' from host to target Filip Bozuta (2): linux-user: Fix 'mq_timedsend()' and 'mq_timedreceive()' linux-user: Add support for 'mq_timedsend_time64()' and 'mq_timedreceive_time64()' linux-user/syscall.c | 74 +++- 1 file changed, 67 insertions(+), 7 deletions(-) -- 2.25.1
[PATCH v3 0/2] Introducing functionality for a group of 4 time64 syscalls
This two patch series introduces functionality for a group of 4 2038 safe syscalls. The list of implemented syscalls and implementation details can be found in the patch commit messages. Testing method: The implementation of the implemented syscalls was tested using already existing tests from LTP test suite which was built inside chroot. *v2: -Added check for 'clock_nanosleep_time64()' which returns '-TARGET_EFAULT' if conversion of 'struct timespec64' between host and target -Removed unnecesary special errno handling for 'PPC' *v3: -Removed unnecesary pointer to timex structure 'phtx' Filip Bozuta (2): linux-user: Add support for 'clock_nanosleep_time64()' and 'clock_adjtime64()' linux-user: Add support for 'rt_sigtimedwait_time64()' and 'sched_rr_get_interval_time64()' linux-user/syscall.c | 190 +- linux-user/syscall_defs.h | 31 +++ 2 files changed, 219 insertions(+), 2 deletions(-) -- 2.25.1
[PATCH v3 1/2] linux-user: Add support for 'clock_nanosleep_time64()' and 'clock_adjtime64()'
This patch implements functionality for following time64 syscall: *clock_nanosleep_time64() This is a year 2038 safe vairant of syscall: int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *request, struct timespec *remain) --high-resolution sleep with specifiable clock-- man page: https://man7.org/linux/man-pages/man2/clock_nanosleep.2.html *clock_adjtime64() This is a year 2038 safe variant of syscall: int clock_adjtime(clockid_t clk_id, struct timex *buf) --tune kernel clock-- man page: https://man7.org/linux/man-pages/man2/clock_adjtime.2.html Implementation notes: Syscall 'clock_nanosleep_time64()' was implemented similarly to syscall 'clock_nanosleep()' except that 'host_to_target_timespec64()' and 'target_to_host_timespec64()' were used instead of the regular 'host_to_target_timespec()' and 'target_to_host_timespec()'. For 'clock_adjtime64()' a 64-bit target kernel version of 'struct timex' was defined in 'syscall_defs.h': 'struct target__kernel_timex'. This type was used to convert the values of 64-bit timex type between host and target. For this purpose a 64-bit timex converting functions 'target_to_host_timex64()' and 'host_to_target_timex64()'. An existing function 'copy_to_user_timeval64()' was used to convert the field 'time' which if of type 'struct timeval' from host to target. Function 'copy_from_user_timveal64()' was added in this patch and used to convert the 'time' field from target to host. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 137 +- linux-user/syscall_defs.h | 31 + 2 files changed, 166 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 05f03919ff..a359bd8620 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -809,7 +809,8 @@ safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len, safe_syscall2(int, nanosleep, const struct timespec *, req, struct timespec *, rem) #endif -#ifdef TARGET_NR_clock_nanosleep +#if defined(TARGET_NR_clock_nanosleep) || \ +defined(TARGET_NR_clock_nanosleep_time64) safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags, const struct timespec *, req, struct timespec *, rem) #endif @@ -1205,8 +1206,25 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr, return 0; } +static inline abi_long copy_from_user_timeval64(struct timeval *tv, +abi_ulong target_tv_addr) +{ +struct target__kernel_sock_timeval *target_tv; + +if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) { +return -TARGET_EFAULT; +} + +__get_user(tv->tv_sec, _tv->tv_sec); +__get_user(tv->tv_usec, _tv->tv_usec); + +unlock_user_struct(target_tv, target_tv_addr, 0); + +return 0; +} + static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr, - const struct timeval *tv) + const struct timeval *tv) { struct target__kernel_sock_timeval *target_tv; @@ -6771,6 +6789,87 @@ static inline abi_long host_to_target_timex(abi_long target_addr, } #endif + +#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME) +static inline abi_long target_to_host_timex64(struct timex *host_tx, + abi_long target_addr) +{ +struct target__kernel_timex *target_tx; + +if (copy_from_user_timeval64(_tx->time, target_addr + + offsetof(struct target__kernel_timex, + time))) { +return -TARGET_EFAULT; +} + +if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) { +return -TARGET_EFAULT; +} + +__get_user(host_tx->modes, _tx->modes); +__get_user(host_tx->offset, _tx->offset); +__get_user(host_tx->freq, _tx->freq); +__get_user(host_tx->maxerror, _tx->maxerror); +__get_user(host_tx->esterror, _tx->esterror); +__get_user(host_tx->status, _tx->status); +__get_user(host_tx->constant, _tx->constant); +__get_user(host_tx->precision, _tx->precision); +__get_user(host_tx->tolerance, _tx->tolerance); +__get_user(host_tx->tick, _tx->tick); +__get_user(host_tx->ppsfreq, _tx->ppsfreq); +__get_user(host_tx->jitter, _tx->jitter); +__get_user(host_tx->shift, _tx->shift); +__get_user(host_tx->stabil, _tx->stabil); +__get_user(host_tx->jitcnt, _tx->jitcnt); +__get_user(host_tx->calcnt, _tx->calcnt); +__get_user(host_tx->errcnt, _tx->errcnt); +__get_user(host_tx->stbcnt, _tx->stbcnt); +__
[PATCH v3 2/2] linux-user: Add support for 'rt_sigtimedwait_time64()' and 'sched_rr_get_interval_time64()'
This patch implements functionality for following time64 syscalls: *rt_sigtimedwait_time64() This is a year 2038 safe variant of syscall: int rt_sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout, size_t sigsetsize) --synchronously wait for queued signals-- man page: https://man7.org/linux/man-pages/man2/rt_sigtimedwait.2.html *sched_rr_get_interval_time64() This is a year 2038 safe variant of syscall: int sched_rr_get_interval(pid_t pid, struct timespec *tp) --get the SCHED_RR interval for the named process-- man page: https://man7.org/linux/man-pages/man2/sched_rr_get_interval.2.html Implementation notes: These syscalls were implemented in similar ways like 'rt_sigtimedwait()' and 'sched_rr_get_interval()' except that functions 'target_to_host_timespec64()' and 'host_to_target_timespec64()' were used to convert values of 'struct timespec' between host and target. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/syscall.c | 53 1 file changed, 53 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index a359bd8620..0533a5a5bb 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8831,6 +8831,48 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } } return ret; +#endif +#ifdef TARGET_NR_rt_sigtimedwait_time64 +case TARGET_NR_rt_sigtimedwait_time64: +{ +sigset_t set; +struct timespec uts, *puts; +siginfo_t uinfo; + +if (arg4 != sizeof(target_sigset_t)) { +return -TARGET_EINVAL; +} + +p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1); +if (!p) { +return -TARGET_EFAULT; +} +target_to_host_sigset(, p); +unlock_user(p, arg1, 0); +if (arg3) { +puts = +if (target_to_host_timespec64(puts, arg3)) { +return -TARGET_EFAULT; +} +} else { +puts = NULL; +} +ret = get_errno(safe_rt_sigtimedwait(, , puts, + SIGSET_T_SIZE)); +if (!is_error(ret)) { +if (arg2) { +p = lock_user(VERIFY_WRITE, arg2, + sizeof(target_siginfo_t), 0); +if (!p) { +return -TARGET_EFAULT; +} +host_to_target_siginfo(p, ); +unlock_user(p, arg2, sizeof(target_siginfo_t)); +} +ret = host_to_target_signal(ret); +} +} +return ret; #endif case TARGET_NR_rt_sigqueueinfo: { @@ -10351,6 +10393,17 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_sched_rr_get_interval_time64 +case TARGET_NR_sched_rr_get_interval_time64: +{ +struct timespec ts; +ret = get_errno(sched_rr_get_interval(arg1, )); +if (!is_error(ret)) { +ret = host_to_target_timespec64(arg2, ); +} +} +return ret; +#endif #if defined(TARGET_NR_nanosleep) case TARGET_NR_nanosleep: { -- 2.25.1
[PATCH v3 0/8] linux-user: Adding support for a group of btrfs ioctls
This series covers support for following btrfs ioctls *BTRFS_SUBVOL_CREATE *BTRFS_IOC_ADD_DEV *BTRFS_SUBVOL_SETFLAGS *BTRFS_IOC_RM_DEV *BTRFS_SUBVOL_GETFLAGS *BTRFS_IOC_DEV_INFO *BTRFS_GET_SUBVOL_INFO *BTRFS_IOC_GET_DEV_STATS *BTRFS_IOC_SNAP_CREATE *BTRFS_IOC_GET_FEATURES *BTRFS_IOC_SNAP_DESTROY*BTRFS_IOC_SET_FEATURES *BTRFS_IOC_SCAN_DEV*BTRFS_IOC_GET_SUPPORTED_FEATURES *BTRFS_IOC_DEFAULT_SUBVOL *BTRFS_IOC_QUOTA_RESCAN *BTRFS_IOC_GET_SUBVOL_ROOTREF *BTRFS_IOC_QUOTA_RESCAN_WAIT *BTRFS_IOC_QUOTA_CTL *BTRFS_IOC_SCRUB *BTRFS_IOC_QGROUP_CREATE *BTRFS_IOC_SCRUB_CANCEL *BTRFS_IOC_QGROUP_ASSIGN *BTRFS_IOC_SCRUB_PROGRESS *BTRFS_IOC_INO_PATHS *BTRFS_IOC_QGROUP_LIMIT *BTRFS_IOC_LOGICAL_INO *BTRFS_IOC_QUOTA_RESCAN_STATUS *BTRFS_IOC_LOGICAL_INO_V2 *BTRFS_IOC_INO_LOOKUP_USER *BTRFS_IOC_INO_LOOKUP The functionalities of individual ioctls were described in this series patch commit messages. Since all of these ioctls are added in kernel version 3.9, their definitions in file 'linux-user/ioctls.h' are enwrapped in an #ifdef directive. Testing method: Mini test programs were written for these ioctls. These test programs can be found on a repositort which is located on the link: https://github.com/bozutaf/btrfs-tests These test programs were compiled (sometimes using cross compilers) for following architectures: * Intel 64-bit (little endian) * Power pc 32-bit (big endian) * Power pc 64-bit (big endian) The corresponding native programs were executed without using QEMU on an intel x86_64 host. All applicable compiled programs were in turn executed through QEMU and the results obtained were the same ones gotten for native execution. v2: * Merged two series in one 8 patch series * Changed target ioctl definitions from IOR/IOW/IOWR to IORU/IOWU/IOWRU * Fixed some thunk struct definitions v3: * Added some checks in fine 'syscall_types.h' to see whether the ioctls that use the defined thunk types are present. This is done to support systems that have older versions of 'btrfs.h' file or if the file is not present at all. This is neccesary as to not cause build errors as some structures depend on values which are defined in 'btrfs.h'. Filip Bozuta (8): linux-user: Add support for a group of btrfs ioctls used for subvolumes linux-user: Add support for a group of btrfs ioctls used for snapshots linux-user: Add support for btrfs ioctls used to manipulate with devices linux-user: Add support for btrfs ioctls used to get/set features linux-user: Add support for a group of btrfs inode ioctls linux-user: Add support for two btrfs ioctls used for subvolume linux-user: Add support for btrfs ioctls used to manage quota linux-user: Add support for btrfs ioctls used to scrub a filesystem configure | 9 ++ linux-user/ioctls.h| 124 linux-user/syscall.c | 3 + linux-user/syscall_defs.h | 37 + linux-user/syscall_types.h | 163 + 5 files changed, 336 insertions(+) -- 2.25.1
[PATCH] linux-user: Add support for a group of '_V2' btrfs ioctls
This patch introduces functionality for following btrfs ioctls: BTRFS_IOC_SUBVOL_CREATE_V2 - Adding a new btrfs subvolume Create a new btrfs subvolume (same as with BTRFS_IOC_SUBVOL_CREATE). The third ioctl's argument is a pointer to a following type: struct btrfs_ioctl_vol_args_v2 { __s64 fd; __u64 transid; __u64 flags; union { struct { __u64 size; struct btrfs_qgroup_inherit __user *qgroup_inherit; }; __u64 unused[4]; }; union { char name[BTRFS_SUBVOL_NAME_MAX + 1]; __u64 devid; __u64 subvolid; /* added in kernel version 5.8 */ }; }; When calling this ioctl, the 'name' field should be filled with the aproppriate value that contains the name of the subvolume that is to be created. The flags field can take values that are 'BTRFS_SUBVOL_RDONLY' or 'BTRFS_SUBVOL_QGROUP_INHERIT'. If the latter is specified, the field 'qgroup_inherit' should be filled with aproppriate values of the quota group in which the newly created subvolume is to be added. The definition of 'struct btrfs_qgroup_inherit' can be found at: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/btrfs.h#L90 BTRFS_IOC_SNAP_CREATE_V2 - Adding a btrfs snapshot for a subvolume Create a new btrfs snapshot for a specified subvolume (same as with BTRFS_IOC_SNAP_CREATE). The ioctl's third argument is a pointer to the above mentioned 'struct btrfs_ioctl_vol_args_v2'. Before calling this ioctl, field 'fd' should be filled with the aproppriate file descriptor value for the btrfs subvolume for which the snapshot is to be created. Also, the 'name' field should be filled with the aproppriate value that represents the name of the snapshot that is to be created. The 'flags' field takes the same values as in case of 'BTRFS_IOC_SUBVOL_CREATE_V2' and represents the same functionality. BTRFS_IOC_RM_DEV_V2 - Removing a btrfs device Delete a btrfs device (same as with BTRFS_IOC_RM_DEV). The ioctl's third argument is a pointer to the above mentioned 'struct btrfs_ioctl_vol_args_v2'. Before calling this ioctl, either the 'name' or the 'devid' field should be filled with the name or id of the device that is to be removed. Also, the flags field should be filled either with 0 or 'BTRFS_DEVICE_SPEC_BY_ID' depending on if the device is gonna be specified via name or id. BTRFS_IOC_SNAP_DESTROY_V2 - Removing a btrfs snapshot Remove a btrfs snapshot (same as with BTRFS_IOC_SNAP_DESTROY). The ioctl's third argument is a pointer to the above mentioned 'struct btrfs_ioctl_vol_args_v2'. Before calling this ioctl, either the 'name' or the 'subvolid' field should be filled with the name or id of the snapshot that is to be removed. Also, the flags field should be filled either with 0 or 'BTRFS_SUBVOL_SPEC_BY_ID' depending on if the snapshot is gonna be specified via name or id. Implementation notes: Since the third argument of the implemented ioctl's is a structure that contains unions, a special converting function 'target_to_host_btrfs_ioctl_vol_args_v2' was defined in 'syscall.c'. This function is called instead of 'thunk_convert()' to convert the values of the third argument from target to host. All of the ioctls in this patch are of type 'IOW' which is why a converting function from host to target is not required. Also, a separate printing function was defined in file 'strace.c' that is called instead of 'thunk_print()' to print the contents of the third argument. Signed-off-by: Filip Bozuta Based-on: <20200811164553.27713-2-filip.boz...@syrmia.com> Based-on: <20200723210233.349690-4-filip.boz...@syrmia.com> --- linux-user/ioctls.h| 16 +++ linux-user/qemu.h | 5 ++ linux-user/strace.c| 95 ++ linux-user/syscall.c | 77 ++ linux-user/syscall_defs.h | 28 +++ linux-user/syscall_types.h | 5 ++ thunk.c| 2 +- 7 files changed, 227 insertions(+), 1 deletion(-) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index e3bfe78774..a29ce6b69d 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -209,6 +209,14 @@ #ifdef BTRFS_IOC_DEFAULT_SUBVOL IOCTL(BTRFS_IOC_DEFAULT_SUBVOL, IOC_W, MK_PTR(TYPE_ULONGLONG)) #endif +#ifdef BTRFS_IOC_SNAP_CREATE_V2 + IOCTL(BTRFS_IOC_SNAP_CREATE_V2, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args_v2))) +#endif +#ifdef BTRFS_IOC_SUBVOL_CREATE_V2 + IOCTL(BTRFS_IOC_SUBVOL_CREATE_V2, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args_v2))) +#endif #ifdef BTRFS_IOC_SUBVOL_GETFLAGS IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG)) #endif @@ -2
[PATCH v3 8/8] linux-user: Add support for btrfs ioctls used to scrub a filesystem
This patch implements functionality for following ioctls: BTRFS_IOC_SCRUB - Starting a btrfs filesystem scrub Start a btrfs filesystem scrub. The third ioctls argument is a pointer to a following type: struct btrfs_ioctl_scrub_args { __u64 devid;/* in */ __u64 start;/* in */ __u64 end; /* in */ __u64 flags;/* in */ struct btrfs_scrub_progress progress; /* out */ /* pad to 1k */ __u64 unused[(1024-32-sizeof(struct btrfs_scrub_progress))/8]; }; Before calling this ioctl, field 'devid' should be filled with value that represents the device id of the btrfs filesystem for which the scrub is to be started. BTRFS_IOC_SCRUB_CANCEL - Canceling scrub of a btrfs filesystem Cancel a btrfs filesystem scrub if it is running. The third ioctls argument is ignored. BTRFS_IOC_SCRUB_PROGRESS - Getting status of a running scrub Read the status of a running btrfs filesystem scrub. The third ioctls argument is a pointer to the above mentioned 'struct btrfs_ioctl_scrub_args'. Similarly as with 'BTRFS_IOC_SCRUB', the 'devid' field should be filled with value that represents the id of the btrfs device for which the scrub has started. The status of a running scrub is returned in the field 'progress' which is of type 'struct btrfs_scrub_progress' and its definition can be found at: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/btrfs.h#L150 Implementation nots: Ioctls in this patch use type 'struct btrfs_ioctl_scrub_args' as their third argument. That is the reason why an aproppriate thunk type definition is added in file 'syscall_types.h'. Signed-off-by: Filip Bozuta --- linux-user/ioctls.h| 11 +++ linux-user/syscall_defs.h | 3 +++ linux-user/syscall_types.h | 29 + 3 files changed, 43 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 882bfb3e88..e3bfe78774 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -215,6 +215,17 @@ #ifdef BTRFS_IOC_SUBVOL_SETFLAGS IOCTL(BTRFS_IOC_SUBVOL_SETFLAGS, IOC_W, MK_PTR(TYPE_ULONGLONG)) #endif +#ifdef BTRFS_IOC_SCRUB + IOCTL(BTRFS_IOC_SCRUB, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_scrub_args))) +#endif +#ifdef BTRFS_IOC_SCRUB_CANCEL + IOCTL(BTRFS_IOC_SCRUB_CANCEL, 0, TYPE_NULL) +#endif +#ifdef BTRFS_IOC_SCRUB_PROGRESS + IOCTL(BTRFS_IOC_SCRUB_PROGRESS, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_scrub_args))) +#endif #ifdef BTRFS_IOC_DEV_INFO IOCTL(BTRFS_IOC_DEV_INFO, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_dev_info_args))) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 10a7f91016..969377d622 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -982,6 +982,9 @@ struct target_rtc_pll_info { abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_SETFLAGSTARGET_IOW(BTRFS_IOCTL_MAGIC, 26,\ abi_ullong) +#define TARGET_BTRFS_IOC_SCRUB TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 27) +#define TARGET_BTRFS_IOC_SCRUB_CANCEL TARGET_IO(BTRFS_IOCTL_MAGIC, 28) +#define TARGET_BTRFS_IOC_SCRUB_PROGRESS TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 29) #define TARGET_BTRFS_IOC_DEV_INFO TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 30) #define TARGET_BTRFS_IOC_INO_PATHS TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 35) #define TARGET_BTRFS_IOC_LOGICAL_INO TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 36) diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index d9b7106a69..789723cfb9 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -421,6 +421,35 @@ STRUCT(btrfs_ioctl_ino_lookup_user_args, MK_ARRAY(TYPE_CHAR, BTRFS_INO_LOOKUP_USER_PATH_MAX)) /* path */ #endif +#if defined(BTRFS_IOC_SCRUB) || defined(BTRFS_IOC_SCRUB_PROGRESS) +STRUCT(btrfs_scrub_progress, + TYPE_ULONGLONG, /* data_extents_scrubbed */ + TYPE_ULONGLONG, /* tree_extents_scrubbed */ + TYPE_ULONGLONG, /* data_bytes_scrubbed */ + TYPE_ULONGLONG, /* tree_bytes_scrubbed */ + TYPE_ULONGLONG, /* read_errors */ + TYPE_ULONGLONG, /* csum_errors */ + TYPE_ULONGLONG, /* verify_errors */ + TYPE_ULONGLONG, /* no_csum */ + TYPE_ULONGLONG, /* csum_discards */ + TYPE_ULONGLONG, /* super_errors */ + TYPE_ULONGLONG, /* malloc_errors */ + TYPE_ULONGLONG, /* uncorrectable_errors */ + TYPE_ULONGLONG, /* corrected_er */ + TYPE_ULONGLONG, /* last_physical */ + TYPE_ULONGLONG) /* unverified_errors */ + +STRUCT(btrfs_ioctl_scrub_args, + TYPE_ULONGLONG, /* devid */ + TYPE_ULONGLONG, /* start
[PATCH v3 4/8] linux-user: Add support for btrfs ioctls used to get/set features
This patch implements functionality for following ioctls: BTRFS_IOC_GET_FEATURES - Getting feature flags Read feature flags for a btrfs filesystem. The feature flags are returned inside the ioctl's third argument which represents a pointer to a following structure type: struct btrfs_ioctl_feature_flags { __u64 compat_flags; __u64 compat_ro_flags; __u64 incompat_flags; }; All of the structure field represent bit masks that can be composed of values which can be found on: https://elixir.bootlin.com/linux/latest/source/fs/btrfs/ctree.h#L282 BTRFS_IOC_SET_FEATURES - Setting feature flags Set and clear feature flags for a btrfs filesystem. The feature flags are set using the ioctl's third argument which represents a 'struct btrfs_ioctl_feature_flags[2]' array. The first element of the array represent flags which are to be cleared and the second element of the array represent flags which are to be set. The second element has the priority over the first, which means that if there are matching flags in the elements, they will be set in the filesystem. If the flag values in the third argument aren't correctly set to be composed of the available predefined flag values, errno ENOPERM ("Operation not permitted") is returned. BTRFS_IOC_GET_SUPPORTED_FEATURES - Getting supported feature flags Read supported feature flags for a btrfs filesystem. The supported feature flags are read using the ioctl's third argument which represents a 'struct btrfs_ioctl_feature_flags[3]' array. The first element of this array represents all of the supported flags in the btrfs filesystem. The second element represents flags that can be safely set and third element represent flags that can be safely clearead. Implementation notes: All of the implemented ioctls use 'struct btrfs_ioctl_feature_flags' as third argument. That is the reason why a corresponding defintion was added in file 'linux-user/syscall_types.h'. Signed-off-by: Filip Bozuta --- linux-user/ioctls.h| 12 linux-user/syscall_defs.h | 3 +++ linux-user/syscall_types.h | 5 + 3 files changed, 20 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 55a6cbeca5..50fae1e33b 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -216,6 +216,18 @@ IOCTL(BTRFS_IOC_GET_DEV_STATS, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_dev_stats))) #endif +#ifdef BTRFS_IOC_GET_FEATURES + IOCTL(BTRFS_IOC_GET_FEATURES, IOC_R, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_feature_flags))) +#endif +#ifdef BTRFS_IOC_SET_FEATURES + IOCTL(BTRFS_IOC_SET_FEATURES, IOC_W, + MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_btrfs_ioctl_feature_flags), 2))) +#endif +#ifdef BTRFS_IOC_GET_SUPPORTED_FEATURES + IOCTL(BTRFS_IOC_GET_SUPPORTED_FEATURES, IOC_R, + MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_btrfs_ioctl_feature_flags), 3))) +#endif #ifdef BTRFS_IOC_GET_SUBVOL_INFO IOCTL(BTRFS_IOC_GET_SUBVOL_INFO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_subvol_info_args))) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 4c7bfa0391..44811fdcbb 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -981,6 +981,9 @@ struct target_rtc_pll_info { abi_ullong) #define TARGET_BTRFS_IOC_DEV_INFO TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 30) #define TARGET_BTRFS_IOC_GET_DEV_STATS TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 52) +#define TARGET_BTRFS_IOC_GET_FEATURES TARGET_IORU(BTRFS_IOCTL_MAGIC, 57) +#define TARGET_BTRFS_IOC_SET_FEATURES TARGET_IOWU(BTRFS_IOCTL_MAGIC, 57) +#define TARGET_BTRFS_IOC_GET_SUPPORTED_FEATURES TARGET_IORU(BTRFS_IOCTL_MAGIC, 57) #define TARGET_BTRFS_IOC_GET_SUBVOL_INFOTARGET_IORU(BTRFS_IOCTL_MAGIC, 60) /* usb ioctls */ diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index ea6898979b..925054cfd4 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -409,6 +409,11 @@ STRUCT(btrfs_ioctl_get_dev_stats, 128 - 2 - BTRFS_DEV_STAT_VALUES_MAX)) /* unused */ #endif +STRUCT(btrfs_ioctl_feature_flags, + TYPE_ULONGLONG, /* compat_flags */ + TYPE_ULONGLONG, /* compat_ro_flags */ + TYPE_ULONGLONG) /* incompat_flags */ + STRUCT(rtc_time, TYPE_INT, /* tm_sec */ TYPE_INT, /* tm_min */ -- 2.25.1
[PATCH v3 7/8] linux-user: Add support for btrfs ioctls used to manage quota
This patch implements functionality for following ioctls: BTRFS_IOC_QUOTA_CTL - Enabling/Disabling quota support Enable or disable quota support for a btrfs filesystem. Quota support is enabled or disabled using the ioctls third argument which represents a pointer to a following type: struct btrfs_ioctl_quota_ctl_args { __u64 cmd; __u64 status; }; Before calling this ioctl, the 'cmd' field should be filled with one of the values 'BTRFS_QUOTA_CTL_ENABLE' (enabling quota) 'BTRFS_QUOTA_CTL_DISABLE' (disabling quota). BTRFS_IOC_QGROUP_CREATE - Creating/Removing a subvolume quota group Create or remove a subvolume quota group. The subvolume quota group is created or removed using the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_qgroup_create_args { __u64 create; __u64 qgroupid; }; Before calling this ioctl, the 'create' field should be filled with the aproppriate value depending on if the user wants to create or remove a quota group (0 for removing, everything else for creating). Also, the 'qgroupid' field should be filled with the value for the quota group id that is to be created. BTRFS_IOC_QGROUP_ASSIGN - Asigning or removing a quota group as child group Asign or remove a quota group as child quota group of another group in the btrfs filesystem. The asignment is done using the ioctl's third argument which represents a pointert to a following type: struct btrfs_ioctl_qgroup_assign_args { __u64 assign; __u64 src; __u64 dst; }; Before calling this ioctl, the 'assign' field should be filled with the aproppriate value depending on if the user wants to asign or remove a quota group as a child quota group of another group (0 for removing, everythin else for asigning). Also, the 'src' and 'dst' fields should be filled with the aproppriate quota group id values depending on which quota group needs to asigned or removed as child quota group of another group ('src' gets asigned or removed as child group of 'dst'). BTRFS_IOC_QGROUP_LIMIT - Limiting the size of a quota group Limit the size of a quota group. The size of the quota group is limited with the ioctls third argument which represents a pointer to a following type: struct btrfs_ioctl_qgroup_limit_args { __u64 qgroupid; struct btrfs_qgroup_limit lim; }; Before calling this ioctl, the 'qgroup' id field should be filled with aproppriate value of the quota group id for which the size is to be limited. The second field is of following type: struct btrfs_qgroup_limit { __u64 flags; __u64 max_rfer; __u64 max_excl; __u64 rsv_rfer; __u64 rsv_excl; }; The 'max_rfer' field should be filled with the size to which the quota group should be limited. The 'flags' field can be used for passing additional options and can have values which can be found on: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/btrfs.h#L67 BTRFS_IOC_QUOTA_RESCAN_STATUS - Checking status of running rescan operation Check status of a running rescan operation. The status is checked using the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_quota_rescan_args { __u64 flags; __u64 progress; __u64 reserved[6]; }; If there is a rescan operation running, 'flags' field is set to 1, and 'progress' field is set to aproppriate value which represents the progress of the operation. BTRFS_IOC_QUOTA_RESCAN - Starting a rescan operation Start ar rescan operation to Trash all quota groups and scan the metadata again with the current config. Before calling this ioctl, BTRFS_IOC_QUOTA_RESCAN_STATUS sould be run to check if there is already a rescan operation runing. After that ioctl call, the received 'struct btrfs_ioctl_quota_rescan_args' should be than passed as this ioctls third argument. BTRFS_IOC_QUOTA_RESCAN_WAIT - Waiting for a rescan operation to finish Wait until a rescan operation is finished (if there is a rescan operation running). The third ioctls argument is ignored. Implementation notes: Almost all of the ioctls in this patch use structure types as third arguments. That is the reason why aproppriate thunk definitions were added in file 'syscall_types.h'. Signed-off-by: Filip Bozuta --- linux-user/ioctls.h| 27 +++ linux-user/syscall_defs.h | 7 +++ linux-user/syscall_types.h | 29 + 3 files changed, 63 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 728880b9f3..882bfb3e88 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -227,6 +227,33 @@ IOCTL(BTRFS_IOC_LOGICAL_INO
[PATCH v3 2/8] linux-user: Add support for a group of btrfs ioctls used for snapshots
This patch implements functionality for following ioctls: BTRFS_IOC_SNAP_CREATE - Creating a subvolume snapshot Create a snapshot of a btrfs subvolume. The snapshot is created using the ioctl's third argument that is a pointer to a 'struct btrfs_ioctl_vol_args' (which was mentioned in the previous patch). Before calling this ioctl, the fields of the structure should be filled with aproppriate values for the file descriptor and path of the subvolume for which the snapshot is to be created. BTRFS_IOC_SNAP_DESTROY - Removing a subvolume snapshot Delete a snapshot of a btrfs subvolume. The snapshot is deleted using the ioctl's third argument that is a pointer to a 'struct btrfs_ioctl_vol_args' (which was mentioned in the previous patch). Before calling this ioctl, the fields of the structure should be filled with aproppriate values for the file descriptor and path of the subvolume for which the snapshot is to be deleted. Implementation notes: Since the thunk type 'struct btrfs_ioctl_vol_args' is defined in the previous patch, the implementation for these ioctls was straightforward. Signed-off-by: Filip Bozuta --- linux-user/ioctls.h| 8 linux-user/syscall_defs.h | 2 ++ linux-user/syscall_types.h | 3 ++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 12d1444224..f33a99f8b6 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -174,10 +174,18 @@ IOCTL(FS_IOC32_GETVERSION, IOC_R, MK_PTR(TYPE_INT)) IOCTL(FS_IOC32_SETVERSION, IOC_W, MK_PTR(TYPE_INT)) +#ifdef BTRFS_IOC_SNAP_CREATE + IOCTL(BTRFS_IOC_SNAP_CREATE, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) +#endif #ifdef BTRFS_IOC_SUBVOL_CREATE IOCTL(BTRFS_IOC_SUBVOL_CREATE, IOC_W, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) #endif +#ifdef BTRFS_IOC_SNAP_DESTROY + IOCTL(BTRFS_IOC_SNAP_DESTROY, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) +#endif #ifdef BTRFS_IOC_SUBVOL_GETFLAGS IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG)) #endif diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 2757956dfa..a945e12547 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -968,7 +968,9 @@ struct target_rtc_pll_info { #define TARGET_FS_IOC32_SETVERSION TARGET_IOW('v', 2, int) /* btrfs ioctls */ +#define TARGET_BTRFS_IOC_SNAP_CREATETARGET_IOWU(BTRFS_IOCTL_MAGIC, 1) #define TARGET_BTRFS_IOC_SUBVOL_CREATE TARGET_IOWU(BTRFS_IOCTL_MAGIC, 14) +#define TARGET_BTRFS_IOC_SNAP_DESTROY TARGET_IOWU(BTRFS_IOCTL_MAGIC, 15) #define TARGET_BTRFS_IOC_SUBVOL_GETFLAGSTARGET_IOR(BTRFS_IOCTL_MAGIC, 25,\ abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_SETFLAGSTARGET_IOW(BTRFS_IOCTL_MAGIC, 26,\ diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index db61dbc1b3..038cd7869b 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -354,7 +354,8 @@ STRUCT(blkpg_partition, MK_ARRAY(TYPE_CHAR, BLKPG_DEVNAMELTH), /* devname */ MK_ARRAY(TYPE_CHAR, BLKPG_VOLNAMELTH)) /* volname */ -#ifdef BTRFS_IOC_SUBVOL_CREATE +#if defined(BTRFS_IOC_SUBVOL_CREATE) || defined(BTRFS_IOC_SNAP_CREATE) || \ +defined(BTRFS_IOC_SNAP_DESTROY) STRUCT(btrfs_ioctl_vol_args, TYPE_LONGLONG, /* fd */ MK_ARRAY(TYPE_CHAR, BTRFS_PATH_NAME_MAX + 1)) /* name */ -- 2.25.1
[PATCH v3 3/8] linux-user: Add support for btrfs ioctls used to manipulate with devices
This patch implements functionality for following ioctls: BTRFS_IOC_SCAN_DEV - Scanning device for a btrfs filesystem Scan a device for a btrfs filesystem. The device that is to be scanned is passed in the ioctl's third argument which represents a pointer to a 'struct ioc_vol_args' (which was mentioned in a previous patch). Before calling this ioctl, the name field of this structure should be filled with the aproppriate name value which represents a path for the device. If the device contains a btrfs filesystem, the ioctl returns 0, otherwise a negative value is returned. BTRFS_IOC_ADD_DEV - Adding a device to a btrfs filesystem Add a device to a btrfs filesystem. The device that is to be added is passed in the ioctl's third argument which represents a pointer to a 'struct ioc_vol_args' (which was mentioned in a previous patch). Before calling this ioctl, the name field of this structure should be filled with the aproppriate name value which represents a path for the device. BTRFS_IOC_RM_DEV - Removing a device from a btrfs filesystem Remove a device from a btrfs filesystem. The device that is to be removed is passed in the ioctl's third argument which represents a pointer to a 'struct ioc_vol_args' (which was mentioned in a previous patch). Before calling this ioctl, the name field of this structure should be filled with the aproppriate name value which represents a path for the device. BTRFS_IOC_DEV_INFO - Getting information about a device Obtain information for device in a btrfs filesystem. The information is gathered in the ioctl's third argument which represents a pointer to a following structure type: struct btrfs_ioctl_dev_info_args { __u64 devid;/* in/out */ __u8 uuid[BTRFS_UUID_SIZE]; /* in/out */ __u64 bytes_used; /* out */ __u64 total_bytes; /* out */ __u64 unused[379]; /* pad to 4k */ __u8 path[BTRFS_DEVICE_PATH_NAME_MAX]; /* out */ }; Before calling this ioctl, field "devid" should be set with the id value for the device for which the information is to be obtained. If this field is not aproppriately set, the errno ENODEV ("No such device") is returned. BTRFS_IOC_GET_DEV_STATS - Getting device statistics Obtain stats informatin for device in a btrfs filesystem. The information is gathered in the ioctl's third argument which represents a pointer to a following structure type: struct btrfs_ioctl_get_dev_stats { __u64 devid;/* in */ __u64 nr_items; /* in/out */ __u64 flags;/* in/out */ /* out values: */ __u64 values[BTRFS_DEV_STAT_VALUES_MAX]; /* * This pads the struct to 1032 bytes. It was originally meant to pad to * 1024 bytes, but when adding the flags field, the padding calculation * was not adjusted. */ __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; }; Before calling this ioctl, field "devid" should be set with the id value for the device for which the information is to be obtained. If this field is not aproppriately set, the errno ENODEV ("No such device") is returned. BTRFS_IOC_FORGET_DEV - Remove unmounted devices Search and remove all stale devices (devices which are not mounted). The third ioctl argument is a pointer to a 'struct btrfs_ioctl_vol_args'. The ioctl call will release all unmounted devices which match the path which is specified in the "name" field of the structure. If an empty path ("") is specified, all unmounted devices will be released. Implementation notes: Ioctls BTRFS_IOC_DEV_INFO and BTRFS_IOC_GET_DEV_STATS use types 'struct btrfs_ioctl_dev_info_args' and ' struct btrfs_ioctl_get_dev_stats' as third argument types. That is the reason why corresponding structure definitions were added in file 'linux-user/syscall_types.h'. Since the thunk type for 'struct ioc_vol_args' was already added in a previous patch, the rest of the implementation was straightforward. Signed-off-by: Filip Bozuta --- linux-user/ioctls.h| 24 linux-user/syscall_defs.h | 6 ++ linux-user/syscall_types.h | 24 +++- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index f33a99f8b6..55a6cbeca5 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -178,6 +178,22 @@ IOCTL(BTRFS_IOC_SNAP_CREATE, IOC_W, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) #endif +#ifdef BTRFS_IOC_SCAN_DEV + IOCTL(BTRFS_IOC_SCAN_DEV, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_
[PATCH v3 5/8] linux-user: Add support for a group of btrfs inode ioctls
This patch implements functionality of following ioctls: BTRFS_IOC_INO_LOOKUP - Reading tree root id and path Read tree root id and path for a given file or directory. The name and tree root id are returned in an ioctl's third argument that represents a pointer to a following type: struct btrfs_ioctl_ino_lookup_args { __u64 treeid; __u64 objectid; char name[BTRFS_INO_LOOKUP_PATH_MAX]; }; Before calling this ioctl, field 'objectid' should be filled with the object id value for which the tree id and path are to be read. Value 'BTRFS_FIRST_FREE_OBJECTID' represents the object id for the first available btrfs object (directory or file). BTRFS_IOC_INO_PATHS - Reading paths to all files Read path to all files with a certain inode number. The paths are returned in the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_ino_path_args { __u64 inum; /* in */ __u64 size; /* in */ __u64 reserved[4]; /* struct btrfs_data_container *fspath; out */ __u64 fspath; /* out */ }; Before calling this ioctl, the 'inum' and 'size' field should be filled with the aproppriate inode number and size of the directory where file paths should be looked for. For now, the paths are returned in an '__u64' (unsigned long long) value 'fspath'. BTRFS_IOC_LOGICAL_INO - Reading inode numbers Read inode numbers for files on a certain logical adress. The inode numbers are returned in the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_logical_ino_args { __u64 logical;/* in */ __u64 size; /* in */ __u64 reserved[3];/* must be 0 for now */ __u64 flags; /* in, v2 only */ /* struct btrfs_data_container *inodes;out */ __u64 inodes; }; Before calling this ioctl, the 'logical' and 'size' field should be filled with the aproppriate logical adress and size of where the inode numbers of files should be looked for. For now, the inode numbers are returned in an '__u64' (unsigned long long) value 'inodes'. BTRFS_IOC_LOGICAL_INO_V2 - Reading inode numbers Same as the above mentioned ioctl except that it allows passing a flags 'BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET'. BTRFS_IOC_INO_LOOKUP_USER - Reading subvolume name and path Read name and path of a subvolume. The tree root id and path are read in an ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_ino_lookup_user_args { /* in, inode number containing the subvolume of 'subvolid' */ __u64 dirid; /* in */ __u64 treeid; /* out, name of the subvolume of 'treeid' */ char name[BTRFS_VOL_NAME_MAX + 1]; /* * out, constructed path from the directory with which the ioctl is * called to dirid */ char path[BTRFS_INO_LOOKUP_USER_PATH_MAX]; }; Before calling this ioctl, the 'dirid' and 'treeid' field should be filled with aproppriate values which represent the inode number of the directory that contains the subvolume and treeid of the subvolume. Implementation notes: All of the ioctls in this patch use structure types as third arguments. That is the reason why aproppriate thunk definitions were added in file 'syscall_types.h'. Signed-off-by: Filip Bozuta --- linux-user/ioctls.h| 20 linux-user/syscall_defs.h | 5 + linux-user/syscall_types.h | 32 3 files changed, 57 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 50fae1e33b..169f98f7a3 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -202,6 +202,10 @@ IOCTL(BTRFS_IOC_SNAP_DESTROY, IOC_W, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) #endif +#ifdef BTRFS_IOC_INO_LOOKUP + IOCTL(BTRFS_IOC_INO_LOOKUP, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_args))) +#endif #ifdef BTRFS_IOC_SUBVOL_GETFLAGS IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG)) #endif @@ -212,6 +216,14 @@ IOCTL(BTRFS_IOC_DEV_INFO, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_dev_info_args))) #endif +#ifdef BTRFS_IOC_INO_PATHS + IOCTL(BTRFS_IOC_INO_PATHS, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_path_args))) +#endif +#ifdef BTRFS_IOC_LOGICAL_INO + IOCTL(BTRFS_IOC_LOGICAL_INO, IOC_RW, + MK_PTR(MK_STRUCT
[PATCH v3 6/8] linux-user: Add support for two btrfs ioctls used for subvolume
This patch implements functionality for following ioctl: BTRFS_IOC_DEFAULT_SUBVOL - Setting a default subvolume Set a default subvolume for a btrfs filesystem. The third ioctl's argument is a '__u64' (unsigned long long) which represents the id of a subvolume that is to be set as the default. BTRFS_IOC_GET_SUBVOL_ROOTREF - Getting tree and directory id of subvolumes Read tree and directory id of subvolumes from a btrfs filesystem. The tree and directory id's are returned in the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_get_subvol_rootref_args { /* in/out, minimum id of rootref's treeid to be searched */ __u64 min_treeid; /* out */ struct { __u64 treeid; __u64 dirid; } rootref[BTRFS_MAX_ROOTREF_BUFFER_NUM]; /* out, number of found items */ __u8 num_items; __u8 align[7]; }; Before calling this ioctl, 'min_treeid' field should be filled with value that represent the minimum value for the tree id. Implementation notes: Ioctl BTRFS_IOC_GET_SUBVOL_ROOTREF uses the above mentioned structure type as third argument. That is the reason why a aproppriate thunk structure definition is added in file 'syscall_types.h'. Signed-off-by: Filip Bozuta --- linux-user/ioctls.h| 7 +++ linux-user/syscall_defs.h | 3 +++ linux-user/syscall_types.h | 13 + 3 files changed, 23 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 169f98f7a3..728880b9f3 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -206,6 +206,9 @@ IOCTL(BTRFS_IOC_INO_LOOKUP, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_args))) #endif +#ifdef BTRFS_IOC_DEFAULT_SUBVOL + IOCTL(BTRFS_IOC_DEFAULT_SUBVOL, IOC_W, MK_PTR(TYPE_ULONGLONG)) +#endif #ifdef BTRFS_IOC_SUBVOL_GETFLAGS IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG)) #endif @@ -248,6 +251,10 @@ IOCTL(BTRFS_IOC_GET_SUBVOL_INFO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_subvol_info_args))) #endif +#ifdef BTRFS_IOC_GET_SUBVOL_ROOTREF + IOCTL(BTRFS_IOC_GET_SUBVOL_ROOTREF, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_subvol_rootref_args))) +#endif #ifdef BTRFS_IOC_INO_LOOKUP_USER IOCTL(BTRFS_IOC_INO_LOOKUP_USER, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_user_args))) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index a6a9454b85..1d0bfb5479 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -976,6 +976,8 @@ struct target_rtc_pll_info { #define TARGET_BTRFS_IOC_SUBVOL_CREATE TARGET_IOWU(BTRFS_IOCTL_MAGIC, 14) #define TARGET_BTRFS_IOC_SNAP_DESTROY TARGET_IOWU(BTRFS_IOCTL_MAGIC, 15) #define TARGET_BTRFS_IOC_INO_LOOKUP TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 18) +#define TARGET_BTRFS_IOC_DEFAULT_SUBVOL TARGET_IOW(BTRFS_IOCTL_MAGIC, 19,\ + abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_GETFLAGSTARGET_IOR(BTRFS_IOCTL_MAGIC, 25,\ abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_SETFLAGSTARGET_IOW(BTRFS_IOCTL_MAGIC, 26,\ @@ -989,6 +991,7 @@ struct target_rtc_pll_info { #define TARGET_BTRFS_IOC_GET_SUPPORTED_FEATURES TARGET_IORU(BTRFS_IOCTL_MAGIC, 57) #define TARGET_BTRFS_IOC_LOGICAL_INO_V2 TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 59) #define TARGET_BTRFS_IOC_GET_SUBVOL_INFOTARGET_IORU(BTRFS_IOCTL_MAGIC, 60) +#define TARGET_BTRFS_IOC_GET_SUBVOL_ROOTREF TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 61) #define TARGET_BTRFS_IOC_INO_LOOKUP_USER TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 62) /* usb ioctls */ diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index b84e14235f..5566d101c2 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -431,6 +431,19 @@ STRUCT(btrfs_ioctl_dev_info_args, MK_ARRAY(TYPE_CHAR, BTRFS_DEVICE_PATH_NAME_MAX)) /* path */ #endif +#ifdef BTRFS_IOC_GET_SUBVOL_ROOTREF +STRUCT(rootref, + TYPE_ULONGLONG, /* treeid */ + TYPE_ULONGLONG) /* dirid */ + +STRUCT(btrfs_ioctl_get_subvol_rootref_args, + TYPE_ULONGLONG, /* min_treeid */ + MK_ARRAY(MK_STRUCT(STRUCT_rootref), +BTRFS_MAX_ROOTREF_BUFFER_NUM), /* rootref */ + TYPE_CHAR, /* num_items */ + MK_ARRAY(TYPE_CHAR, 7)) /* align */ +#endif + #ifdef BTRFS_IOC_GET_DEV_STATS STRUCT(btrfs_ioctl_get_dev_stats, TYPE_ULONGLONG, /* devid */ -- 2.25.1
[PATCH v3 1/8] linux-user: Add support for a group of btrfs ioctls used for subvolumes
This patch implements functionality of following ioctls: BTRFS_IOC_SUBVOL_CREATE - Creating a btrfs subvolume Create a btrfs subvolume. The subvolume is created using the ioctl's third argument which represents a pointer to a following structure type: struct btrfs_ioctl_vol_args { __s64 fd; char name[BTRFS_PATH_NAME_MAX + 1]; }; Before calling this ioctl, the fields of this structure should be filled with aproppriate values. The fd field represents the file descriptor value of the subvolume and the name field represents the subvolume path. BTRFS_IOC_SUBVOL_GETFLAGS - Getting subvolume flags Read the flags of the btrfs subvolume. The flags are read using the ioctl's third argument that is a pointer of __u64 (unsigned long). The third argument represents a bit mask that can be composed of following values: BTRFS_SUBVOL_RDONLY (1ULL << 1) BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) BTRFS_DEVICE_SPEC_BY_ID (1ULL << 3) BTRFS_SUBVOL_SPEC_BY_ID (1ULL << 4) BTRFS_IOC_SUBVOL_SETFLAGS - Setting subvolume flags Set the flags of the btrfs subvolume. The flags are set using the ioctl's third argument that is a pointer of __u64 (unsigned long). The third argument represents a bit mask that can be composed of same values as in the case of previous ioctl (BTRFS_IOC_SUBVOL_GETFLAGS). BTRFS_IOC_SUBVOL_GETINFO - Getting subvolume information Read information about the subvolume. The subvolume information is returned in the ioctl's third argument which represents a pointer to a following structure type: struct btrfs_ioctl_get_subvol_info_args { /* Id of this subvolume */ __u64 treeid; /* Name of this subvolume, used to get the real name at mount point */ char name[BTRFS_VOL_NAME_MAX + 1]; /* * Id of the subvolume which contains this subvolume. * Zero for top-level subvolume or a deleted subvolume. */ __u64 parent_id; /* * Inode number of the directory which contains this subvolume. * Zero for top-level subvolume or a deleted subvolume */ __u64 dirid; /* Latest transaction id of this subvolume */ __u64 generation; /* Flags of this subvolume */ __u64 flags; /* UUID of this subvolume */ __u8 uuid[BTRFS_UUID_SIZE]; /* * UUID of the subvolume of which this subvolume is a snapshot. * All zero for a non-snapshot subvolume. */ __u8 parent_uuid[BTRFS_UUID_SIZE]; /* * UUID of the subvolume from which this subvolume was received. * All zero for non-received subvolume. */ __u8 received_uuid[BTRFS_UUID_SIZE]; /* Transaction id indicating when change/create/send/receive happened */ __u64 ctransid; __u64 otransid; __u64 stransid; __u64 rtransid; /* Time corresponding to c/o/s/rtransid */ struct btrfs_ioctl_timespec ctime; struct btrfs_ioctl_timespec otime; struct btrfs_ioctl_timespec stime; struct btrfs_ioctl_timespec rtime; /* Must be zero */ __u64 reserved[8]; }; All of the fields of this structure are filled after the ioctl call. Implementation notes: Ioctls BTRFS_IOC_SUBVOL_CREATE and BTRFS_IOC_SUBVOL_GETINFO have structure types as third arguments. That is the reason why a corresponding definition are added in file 'linux-user/syscall_types.h'. The line '#include ' is added in file 'linux-user/syscall.c' to recognise preprocessor definitions for these ioctls. Since the file "linux/btrfs.h" was added in the kernel version 3.9, it is enwrapped in an #ifdef statement with parameter CONFIG_BTRFS which is defined in 'configure' if the header file is present. Signed-off-by: Filip Bozuta --- configure | 9 + linux-user/ioctls.h| 15 +++ linux-user/syscall.c | 3 +++ linux-user/syscall_defs.h | 8 linux-user/syscall_types.h | 32 5 files changed, 67 insertions(+) diff --git a/configure b/configure index 4e5fe33211..a0747fe3ab 100755 --- a/configure +++ b/configure @@ -4954,6 +4954,12 @@ if check_include sys/kcov.h ; then kcov=yes fi +# check for btrfs filesystem support (kernel must be 3.9+) +btrfs=no +if check_include linux/btrfs.h ; then +btrfs=yes +fi + # If we're making warnings fatal, apply this to Sphinx runs as well sphinx_werror="" if test "$werror" = "yes"; then @@ -6938,6 +6944,9 @@ fi if test "$kcov" = "yes" ; then echo "CONFIG_KCOV=y" >> $config_host_mak fi +if test "$btrfs" = "yes" ; then + echo "CONFIG_BTRFS=y" >> $config_host_mak
Re: [PULL 00/14] Linux user for 5.2 patches
Hello, On 21.8.20. 20:45, Laurent Vivier wrote: Filip, could you have a look to see what's going wrong? Thanks, LAurent Le 21/08/2020 à 18:23, Peter Maydell a écrit : On Thu, 13 Aug 2020 at 07:51, Laurent Vivier wrote: The following changes since commit d0ed6a69d399ae193959225cdeaa9382746c91cc: Update version for v5.1.0 release (2020-08-11 17:07:03 +0100) are available in the Git repository at: git://github.com/vivier/qemu.git tags/linux-user-for-5.2-pull-request for you to fetch changes up to 04275cad60c8f99e0dd7f56aecda68ceac926da8: linux-user: Fix 'utimensat()' implementation (2020-08-12 10:09:58 +0200) Add btrfs ioctls Add clock_getres_time64, timer_gettime64, timer_settime64, timerfd_gettime64, timerfd_settime64 Some fixes (page protection, print_fdset, timerspec, itimerspec) Fails to compile: ../../linux-user/syscall_types.h:407:28: error: ‘BTRFS_INO_LOOKUP_USER_PATH_MAX’ undeclared here (not in a function); did you mean ‘BTRFS_INO_LOOKUP_PATH_MAX’? MK_ARRAY(TYPE_CHAR, BTRFS_INO_LOOKUP_USER_PATH_MAX)) /* path */ ^ ../../linux-user/syscall_types.h:451:17: error: ‘BTRFS_MAX_ROOTREF_BUFFER_NUM’ undeclared here (not in a function) BTRFS_MAX_ROOTREF_BUFFER_NUM), /* rootref */ ^ On PPC, even more errors, relating to not having BTRFS_PATH_NAME_MAX, PTRFS_VOL_NAME_MAX, etc. Not sure if this was a semantic conflict with the meson conversion, or just an assumption of a newer btrfs.h than some systems have. Yes, this is because of asumption that a newer btrfs.h file is present than some systems have. There have been significant changes in btrfs.h from kernel version 3.9 (since it was introduced). For example, BTRFS_INO_LOOKPU_USER_PATH_MAX is used by BTRRS_IOC_INO_LOOKUP_USER which was introduced a little later which is why this error ocurres. I am guessing that this should be fixed by putting an #ifdef around thunk structure definitions in 'syscall_types.h' to check whether the values that are used by these structures are present (or if ioctls that use this structures are defined). I am sorry that I didn't notice this at first. I will try to send a fix as soon as possible. Best regards, Filip thanks -- PMM
[PATCH v3] linux-user: Fix 'semop()' and 'semtimedop()' implementation
The implementations of syscalls 'semop()' and 'semtimedop()' in file 'syscall.c' use function 'target_to_host_sembuf()' to convert values of 'struct sembuf' from host to target. However, before this conversion it should be check whether the number of semaphore operations 'nsops' is not bigger than maximum allowed semaphor operations per syscall: 'SEMOPM'. In these cases, errno 'E2BIG' ("Arg list too long") should be set. But the implementation will set errno 'EFAULT' ("Bad address") in this case since the conversion from target to host in this case fails. This was confirmed with the LTP test for 'semop()' ('ipc/semop/semop02') in test case where 'nsops' is greater than SEMOPM with unaproppriate errno EFAULT: semop02.c:130: FAIL: semop failed unexpectedly; expected: E2BIG: EFAULT (14) This patch changes this by adding a check whether 'nsops' is bigger than 'SEMOPM' before the conversion function 'target_to_host_sembuf()' is called. After the changes from this patch, the test works fine along with the other LTP testcases for 'semop()'): semop02.c:126: PASS: semop failed as expected: E2BIG (7) Implementation notes: A target value ('TARGET_SEMOPM') was added for 'SEMOPM' as to be sure in case the value is not available for some targets. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 13 +++-- linux-user/syscall_defs.h | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1211e759c2..e4d12c29d3 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3904,7 +3904,7 @@ static inline abi_long do_semtimedop(int semid, unsigned nsops, abi_long timeout) { -struct sembuf sops[nsops]; +struct sembuf *sops; struct timespec ts, *pts = NULL; abi_long ret; @@ -3915,8 +3915,16 @@ static inline abi_long do_semtimedop(int semid, } } -if (target_to_host_sembuf(sops, ptr, nsops)) +if (nsops > TARGET_SEMOPM) { +return -TARGET_E2BIG; +} + +sops = g_new(struct sembuf, nsops); + +if (target_to_host_sembuf(sops, ptr, nsops)) { +g_free(sops); return -TARGET_EFAULT; +} ret = -TARGET_ENOSYS; #ifdef __NR_semtimedop @@ -3928,6 +3936,7 @@ static inline abi_long do_semtimedop(int semid, SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts))); } #endif +g_free(sops); return ret; } #endif diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 3c261cff0e..f7f77346be 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -46,6 +46,8 @@ #define IPCOP_shmget 23 #define IPCOP_shmctl 24 +#define TARGET_SEMOPM 500 + /* * The following is for compatibility across the various Linux * platforms. The i386 ioctl numbering scheme doesn't really enforce -- 2.25.1
[PATCH v2] linux-user: Fix 'semop()' and 'semtimedop()' implementation
The implementations of syscalls 'semop()' and 'semtimedop()' in file 'syscall.c' use function 'target_to_host_sembuf()' to convert values of 'struct sembuf' from host to target. However, before this conversion it should be check whether the number of semaphore operations 'nsops' is not bigger than maximum allowed semaphor operations per syscall: 'SEMOPM'. In these cases, errno 'E2BIG' ("Arg list too long") should be set. But the implementation will set errno 'EFAULT' ("Bad address") in this case since the conversion from target to host in this case fails. This was confirmed with the LTP test for 'semop()' ('ipc/semop/semop02') in test case where 'nsops' is greater than SEMOPM with unaproppriate errno EFAULT: semop02.c:130: FAIL: semop failed unexpectedly; expected: E2BIG: EFAULT (14) This patch changes this by adding a check whether 'nsops' is bigger than 'SEMOPM' before the conversion function 'target_to_host_sembuf()' is called. After the changes from this patch, the test works fine along with the other LTP testcases for 'semop()'): semop02.c:126: PASS: semop failed as expected: E2BIG (7) Implementation notes: A target value ('TARGET_SEMOPM') was added for 'SEMOPM' as to be sure in case the value is not available for some targets. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 12 ++-- linux-user/syscall_defs.h | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1211e759c2..70b172740c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3904,7 +3904,7 @@ static inline abi_long do_semtimedop(int semid, unsigned nsops, abi_long timeout) { -struct sembuf sops[nsops]; +struct sembuf *sops = NULL; struct timespec ts, *pts = NULL; abi_long ret; @@ -3915,8 +3915,15 @@ static inline abi_long do_semtimedop(int semid, } } -if (target_to_host_sembuf(sops, ptr, nsops)) +if (nsops > TARGET_SEMOPM) { +return -TARGET_E2BIG; +} + +sops = g_new(struct sembuf, nsops); + +if (target_to_host_sembuf(sops, ptr, nsops)) { return -TARGET_EFAULT; +} ret = -TARGET_ENOSYS; #ifdef __NR_semtimedop @@ -3928,6 +3935,7 @@ static inline abi_long do_semtimedop(int semid, SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts))); } #endif +g_free(sops); return ret; } #endif diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 3c261cff0e..f7f77346be 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -46,6 +46,8 @@ #define IPCOP_shmget 23 #define IPCOP_shmctl 24 +#define TARGET_SEMOPM 500 + /* * The following is for compatibility across the various Linux * platforms. The i386 ioctl numbering scheme doesn't really enforce -- 2.25.1
[PATCH 0/2] linux-user: Adding support for a group of 4 time64 syscalls
This two patch series introduces functionality for following Year 2038 safe syscalls: --Introduced in first patch-- *ppoll_time64() *pselect6_time64() --Introduced in second patch-- *utimensat_time64() *semtimedop_time64() Testing notes: The implementations of these time64 syscalls was tested using tests from the LTP test suite which was built inside a chroot. Filip Bozuta (2): linux-user: Add support for ppoll_time64() and pselect6_time64() linux-user: Add support for utimensat_time64() and semtimedop_time64() linux-user/syscall.c | 154 --- 1 file changed, 131 insertions(+), 23 deletions(-) -- 2.25.1
[PATCH] linux-user: Fix 'semop()' and 'semtimedop()' implementation
The implementations of syscalls 'semop()' and 'semtimedop()' in file 'syscall.c' use function 'target_to_host_sembuf()' to convert values of 'struct sembuf' from host to target. However, before this conversion it should be check whether the number of semaphore operations 'nsops' is not bigger than maximum allowed semaphor operations per syscall: 'SEMOPM'. In these cases, errno 'E2BIG' ("Arg list too long") should be set. But the implementation will set errno 'EFAULT' ("Bad address") in this case since the conversion from target to host fails. This was confirmed with the LTP test for 'semop()' ('ipc/semop/semop02') in test case where 'nsops' is greater than SEMOPM with unaproppriate errno EFAULT: semop02.c:130: FAIL: semop failed unexpectedly; expected: E2BIG: EFAULT (14) This patch changes this by adding a check whether 'nsops' is bigger than 'SEMOPM' before the conversion function 'target_to_host_sembuf()' is called. After the changes from this patch, the test works fine along with the other LTP testcases for 'semop()'): semop02.c:126: PASS: semop failed as expected: E2BIG (7) Implementation notes: A target value ('TARGET_SEMOPM') was added for 'SEMOPM' as to be sure in case the value is not available for some targets. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1211e759c2..4743a5bef2 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3899,6 +3899,8 @@ static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, (__nsops), 0, (__sops), (__timeout) #endif +#define TARGET_SEMOPM 500 + static inline abi_long do_semtimedop(int semid, abi_long ptr, unsigned nsops, @@ -3915,8 +3917,13 @@ static inline abi_long do_semtimedop(int semid, } } -if (target_to_host_sembuf(sops, ptr, nsops)) +if (nsops > TARGET_SEMOPM) { +return -TARGET_E2BIG; +} + +if (target_to_host_sembuf(sops, ptr, nsops)) { return -TARGET_EFAULT; +} ret = -TARGET_ENOSYS; #ifdef __NR_semtimedop -- 2.25.1
[PATCH 2/2] linux-user: Add support for 'utimensat_time64()' and 'semtimedop_time64()'
This patch introduces functionality for following time64 syscalls: *utimensat_time64() int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags); -- change file timestamps with nanosecond precision -- man page: https://man7.org/linux/man-pages/man2/utimensat.2.html *semtimedop_time64() int semtimedop(int semid, struct sembuf *sops, size_t nsops, const struct timespec *timeout); -- System V semaphore operations -- man page: https://www.man7.org/linux/man-pages/man2/semtimedop.2.html Implementation notes: Syscall 'utimensat_time64()' is implemented in similar way as its regular variants only difference being that time64 converting function is used to convert values of 'struct timespec' between host and target ('target_to_host_timespec64()'). For syscall 'semtimedop_time64()' and additional argument is added in function 'do_semtimedop()' through which the aproppriate 'struct timespec' converting function is called (0 for regular target_to_host_timespec() and anything else for target_to_host_timespec64()). For 'do_ipc()' an check was added as that additional argument: 'TARGET_ABI_BITS == 64'. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 55 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 8f63a46f58..44a13c5ec2 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1253,7 +1253,8 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts, #endif #if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \ -defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64) +defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64) || \ +defined(TARGET_NR_utimensat_time64) || defined(TARGET_NR_semtimedop_time64) static inline abi_long target_to_host_timespec64(struct timespec *host_ts, abi_ulong target_addr) { @@ -3886,7 +3887,7 @@ static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, } #if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \ -defined(TARGET_NR_semtimedop) +defined(TARGET_NR_semtimedop) || defined(TARGET_NR_semtimedop_time64) /* * This macro is required to handle the s390 variants, which passes the @@ -3903,7 +3904,7 @@ static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, static inline abi_long do_semtimedop(int semid, abi_long ptr, unsigned nsops, - abi_long timeout) + abi_long timeout, int time64) { struct sembuf sops[nsops]; struct timespec ts, *pts = NULL; @@ -3911,7 +3912,10 @@ static inline abi_long do_semtimedop(int semid, if (timeout) { pts = -if (target_to_host_timespec(pts, timeout)) { +if (!time64 && target_to_host_timespec(pts, timeout)) { +return -TARGET_EFAULT; +} +if (time64 && target_to_host_timespec64(pts, timeout)) { return -TARGET_EFAULT; } } @@ -4426,7 +4430,7 @@ static abi_long do_ipc(CPUArchState *cpu_env, switch (call) { case IPCOP_semop: -ret = do_semtimedop(first, ptr, second, 0); +ret = do_semtimedop(first, ptr, second, 0, 0); break; case IPCOP_semtimedop: /* @@ -4436,9 +4440,9 @@ static abi_long do_ipc(CPUArchState *cpu_env, * to a struct timespec where the generic variant uses fifth parameter. */ #if defined(TARGET_S390X) -ret = do_semtimedop(first, ptr, second, third); +ret = do_semtimedop(first, ptr, second, third, TARGET_ABI_BITS == 64); #else -ret = do_semtimedop(first, ptr, second, fifth); +ret = do_semtimedop(first, ptr, second, fifth, TARGET_ABI_BITS == 64); #endif break; @@ -9783,11 +9787,15 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_semop case TARGET_NR_semop: -return do_semtimedop(arg1, arg2, arg3, 0); +return do_semtimedop(arg1, arg2, arg3, 0, 0); #endif #ifdef TARGET_NR_semtimedop case TARGET_NR_semtimedop: -return do_semtimedop(arg1, arg2, arg3, arg4); +return do_semtimedop(arg1, arg2, arg3, arg4, 0); +#endif +#ifdef TARGET_NR_semtimedop_time64 +case TARGET_NR_semtimedop_time64: +return do_semtimedop(arg1, arg2, arg3, arg4, 1); #endif #ifdef TARGET_NR_semctl case TARGET_NR_semctl: @@ -11969,6 +11977,35 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_utimensat_time64 +case TARGET_NR_utimensat_time64: +{ +struct timespec *tsp, ts[2]; +
[PATCH 1/2] linux-user: Add support for 'ppoll_time64()' and 'pselect6_time64()'
This patch introduces functionality for following time64 syscalls: *ppoll_time64 This is a year 2038 safe variant of: int poll(struct pollfd *fds, nfds_t nfds, int timeout) -- wait for some event on a file descriptor -- man page: https://man7.org/linux/man-pages/man2/ppoll.2.html *pselect6_time64 This is a year 2038 safe variant of: int pselect6(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask); -- synchronous I/O multiplexing -- man page: https://man7.org/linux/man-pages/man2/pselect6.2.html Implementation notes: Year 2038 safe syscalls in this patch were implemented with the same code as their regular variants (ppoll() and pselect()). A switch/case statement was used to call an apropriate converting function for 'struct timespec' between target and host. (target_to_host/host_to_target_timespec() for regular and target_to_host/host_to_target_timespec64() for time64 variants) Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 101 --- 1 file changed, 86 insertions(+), 15 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1211e759c2..8f63a46f58 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -397,7 +397,7 @@ static int sys_getcwd1(char *buf, size_t size) return strlen(buf)+1; } -#ifdef TARGET_NR_utimensat +#if defined(TARGET_NR_utimensat) #if defined(__NR_utimensat) #define __NR_sys_utimensat __NR_utimensat _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, @@ -763,11 +763,11 @@ safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \ int, options, struct rusage *, rusage) safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp) #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \ -defined(TARGET_NR_pselect6) +defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64) safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \ fd_set *, exceptfds, struct timespec *, timeout, void *, sig) #endif -#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_poll) +#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64) safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds, struct timespec *, tsp, const sigset_t *, sigmask, size_t, sigsetsize) @@ -984,7 +984,7 @@ abi_long do_brk(abi_ulong new_brk) } #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \ -defined(TARGET_NR_pselect6) +defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64) static inline abi_long copy_from_user_fdset(fd_set *fds, abi_ulong target_fds_addr, int n) @@ -1252,7 +1252,8 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts, } #endif -#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) +#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \ +defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64) static inline abi_long target_to_host_timespec64(struct timespec *host_ts, abi_ulong target_addr) { @@ -9043,8 +9044,13 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #endif return ret; #endif +#if defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64) #ifdef TARGET_NR_pselect6 case TARGET_NR_pselect6: +#endif +#ifdef TARGET_NR_pselect6_time64 +case TARGET_NR_pselect6_time64: +#endif { abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr; fd_set rfds, wfds, efds; @@ -9088,8 +9094,21 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, * use the do_select() helper ... */ if (ts_addr) { -if (target_to_host_timespec(, ts_addr)) { -return -TARGET_EFAULT; +switch (num) { +#ifdef TARGET_NR_pselect6 +case TARGET_NR_pselect6: +if (target_to_host_timespec(, ts_addr)) { +return -TARGET_EFAULT; +} +break; +#endif +#ifdef TARGET_NR_pselect6_time64 +case TARGET_NR_pselect6_time64: +if (target_to_host_timespec64(, ts_addr)) { +return -TARGET_EFAULT; +} +break; +#endif } ts_ptr = } else { @@ -9140,8 +9159,22 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, if (efd_addr && copy_to_user_fdset(efd_addr, , n)) return -TARGE
[PATCH v4 1/5] linux-user: Make cpu_env accessible in strace.c
Variable "cpu_env" is used in file "syscall.c" to store the information about the cpu environment. This variable is used because values of some syscalls can vary between cpu architectures. This patch makes the "cpu_env" accessible in "strace.c" so it can enable aproppriate "-strace" argument printing for these syscalls. This will be a useful addition for future "-strace" implementation in QEMU. Implementation notes: Functions "print_syscall()" and "print_syscall_ret()" which are stated and defined in "qemu.h" and "strace.c" respectively are used to print syscall arguments before and after syscall execution. These functions were changed with addition of a new argument "void *cpu_env". Strucute "struct syscallname" in "strace.c" is used to store the information about syscalls. Fields "call" and "result" represent pointers to functions which are used to print syscall arguments before and after execution. These fields were also changed with addition of a new "void *" argumetn. Also, all defined "print_*" and "print_syscall_ret*" functions in "strace.c" were changed to have the new "void *cpu_env". This was done to not cause build errors (even though none of these functions use this argument). Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/qemu.h| 4 +- linux-user/strace.c | 479 ++- linux-user/syscall.c | 5 +- 3 files changed, 247 insertions(+), 241 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 5c964389c1..63ddfe86fd 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -400,10 +400,10 @@ extern long safe_syscall_base(int *pending, long number, ...); int host_to_target_waitstatus(int status); /* strace.c */ -void print_syscall(int num, +void print_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6); -void print_syscall_ret(int num, abi_long ret, +void print_syscall_ret(void *cpu_env, int num, abi_long ret, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6); /** diff --git a/linux-user/strace.c b/linux-user/strace.c index 13981341b3..f0624b6206 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -16,10 +16,10 @@ struct syscallname { int nr; const char *name; const char *format; -void (*call)(const struct syscallname *, +void (*call)(void *, const struct syscallname *, abi_long, abi_long, abi_long, abi_long, abi_long, abi_long); -void (*result)(const struct syscallname *, abi_long, +void (*result)(void *, const struct syscallname *, abi_long, abi_long, abi_long, abi_long, abi_long, abi_long, abi_long); }; @@ -634,7 +634,7 @@ print_clockid(int clockid, int last) /* select */ #ifdef TARGET_NR__newselect static void -print_newselect(const struct syscallname *name, +print_newselect(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -652,7 +652,7 @@ print_newselect(const struct syscallname *name, #ifdef TARGET_NR_semctl static void -print_semctl(const struct syscallname *name, +print_semctl(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -664,7 +664,7 @@ print_semctl(const struct syscallname *name, #endif static void -print_execve(const struct syscallname *name, +print_execve(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -697,7 +697,7 @@ print_execve(const struct syscallname *name, #ifdef TARGET_NR_ipc static void -print_ipc(const struct syscallname *name, +print_ipc(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -741,9 +741,10 @@ print_syscall_err(abi_long ret) } static void -print_syscall_ret_addr(const struct syscallname *name, abi_long ret, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_syscall_ret_addr(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) { if (!p
[PATCH v4 3/5] linux-user: Add strace support for printing arguments of syscalls used to lock and unlock memory
This patch implements strace argument printing functionality for following syscalls: * mlock, munlock, mlockall, munlockall - lock and unlock memory int mlock(const void *addr, size_t len) int munlock(const void *addr, size_t len) int mlockall(int flags) int munlockall(void) man page: https://man7.org/linux/man-pages/man2/mlock.2.html Implementation notes: Syscall mlockall() takes an argument that is composed of predefined values which represent flags that determine the type of locking operation that is to be performed. For that reason, a printing function "print_mlockall" was stated in file "strace.list". This printing function uses an already existing function "print_flags()" to print the "flags" argument. These flags are stated inside an array "mlockall_flags" that contains values of type "struct flags". These values are instantiated using an existing macro "FLAG_TARGET()" that crates aproppriate target flag values based on those defined in files '/target_syscall.h'. These target flag values were changed from "TARGET_MLOCKALL_MCL*" to "TARGET_MCL_*" so that they can be aproppriately set and recognised in "strace.c" with "FLAG_TARGET()". Value for "MCL_ONFAULT" was added in this patch. This value was also added in "syscall.c" in function "target_to_host_mlockall_arg()". Because this flag value was added in kernel version 4.4, it is enwrapped in an #ifdef directive (both in "syscall.c" and in "strace.c") as to support older kernel versions. The other syscalls have only primitive argument types, so the rest of the implementation was handled by stating an appropriate printing format in file "strace.list". Syscall mlock2() is not implemented in "syscall.c" and thus it's argument printing is not implemented in this patch. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/aarch64/target_syscall.h| 5 +++-- linux-user/alpha/target_syscall.h | 5 +++-- linux-user/arm/target_syscall.h| 6 -- linux-user/cris/target_syscall.h | 5 +++-- linux-user/hppa/target_syscall.h | 5 +++-- linux-user/i386/target_syscall.h | 5 +++-- linux-user/m68k/target_syscall.h | 6 +++--- linux-user/microblaze/target_syscall.h | 5 +++-- linux-user/mips/target_syscall.h | 5 +++-- linux-user/mips64/target_syscall.h | 5 +++-- linux-user/nios2/target_syscall.h | 5 +++-- linux-user/openrisc/target_syscall.h | 5 +++-- linux-user/ppc/target_syscall.h| 5 +++-- linux-user/riscv/target_syscall.h | 5 +++-- linux-user/s390x/target_syscall.h | 5 +++-- linux-user/sh4/target_syscall.h| 5 +++-- linux-user/sparc/target_syscall.h | 5 +++-- linux-user/sparc64/target_syscall.h| 5 +++-- linux-user/strace.c| 21 + linux-user/strace.list | 8 linux-user/syscall.c | 10 -- linux-user/tilegx/target_syscall.h | 5 +++-- linux-user/x86_64/target_syscall.h | 5 +++-- linux-user/xtensa/target_syscall.h | 5 +++-- 24 files changed, 97 insertions(+), 49 deletions(-) diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h index 995e475c73..3194e6b009 100644 --- a/linux-user/aarch64/target_syscall.h +++ b/linux-user/aarch64/target_syscall.h @@ -16,8 +16,9 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "3.8.0" #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #define TARGET_PR_SVE_SET_VL 50 #define TARGET_PR_SVE_GET_VL 51 diff --git a/linux-user/alpha/target_syscall.h b/linux-user/alpha/target_syscall.h index 3426cc5b4e..fd389422e3 100644 --- a/linux-user/alpha/target_syscall.h +++ b/linux-user/alpha/target_syscall.h @@ -258,7 +258,8 @@ struct target_pt_regs { #define TARGET_UAC_NOFIX 2 #define TARGET_UAC_SIGBUS 4 #define TARGET_MINSIGSTKSZ 4096 -#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 -#define TARGET_MLOCKALL_MCL_FUTURE 0x4000 +#define TARGET_MCL_CURRENT 0x2000 +#define TARGET_MCL_FUTURE 0x4000 +#define TARGET_MCL_ONFAULT 0x8000 #endif /* ALPHA_TARGET_SYSCALL_H */ diff --git a/linux-user/arm/target_syscall.h b/linux-user/arm/target_syscall.h index f85cbdaf56..e870ed7a54 100644 --- a/linux-user/arm/target_syscall.h +++ b/linux-user/arm/target_syscall.h @@ -28,8 +28,10 @@ struct target_pt_regs { #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_M
[PATCH v4 5/5] linux-user: Add strace support for printing arguments of some clock and time functions
This patch implements strace argument printing functionality for following syscalls: * clock_getres, clock_gettime, clock_settime - clock and time functions int clock_getres(clockid_t clockid, struct timespec *res) int clock_gettime(clockid_t clockid, struct timespec *tp) int clock_settime(clockid_t clockid, const struct timespec *tp) man page: https://man7.org/linux/man-pages/man2/clock_getres.2.html * gettimeofday - get time int gettimeofday(struct timeval *tv, struct timezone *tz) man page: https://man7.org/linux/man-pages/man2/gettimeofday.2.html * getitimer, setitimer - get or set value of an interval timer int getitimer(int which, struct itimerval *curr_value) int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value) man page: https://man7.org/linux/man-pages/man2/getitimer.2.html Implementation notes: All of the syscalls have some structue types as argument types and thus a separate printing function was stated in file "strace.list" for each of them. All of these functions use existing functions for their appropriate structure types ("print_timeval()" and "print_timezone()"). Functions "print_timespec()" and "print_itimerval()" were added in this patch so that they can be used to print types "struct timespec" and "struct itimerval" used by some of the syscalls. Function "print_itimerval()" uses the existing function "print_timeval()" to print fields of the structure "struct itimerval" that are of type "struct timeval". Function "print_enums()", which was introduced in the previous patch, is used to print the interval timer type which is the first argument of "getitimer()" and "setitimer()". Also, this function is used to print the clock id which is the first argument of "clock_getres()" and "clock_gettime()". For that reason, the existing function "print_clockid()" was removed in this patch. Existing function "print_clock_adjtime()" was also changed for this reason to use "print_enums()". The existing function "print_timeval()" was changed a little so that it prints the field names beside the values. Syscalls "clock_getres()" and "clock_gettime()" have the same number and types of arguments and thus their print functions "print_clock_getres" and "print_clock_gettime" share a common definition in file "strace.c". Signed-off-by: Filip Bozuta --- linux-user/strace.c| 287 +++-- linux-user/strace.list | 17 ++- 2 files changed, 232 insertions(+), 72 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index def92c4d73..1a5c4c820a 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -78,7 +78,9 @@ UNUSED static void print_string(abi_long, int); UNUSED static void print_buf(abi_long addr, abi_long len, int last); UNUSED static void print_raw_param(const char *, abi_long, int); UNUSED static void print_timeval(abi_ulong, int); +UNUSED static void print_timespec(abi_ulong, int); UNUSED static void print_timezone(abi_ulong, int); +UNUSED static void print_itimerval(abi_ulong, int); UNUSED static void print_number(abi_long, int); UNUSED static void print_signal(abi_ulong, int); UNUSED static void print_sockaddr(abi_ulong, abi_long, int); @@ -578,69 +580,6 @@ print_fdset(int n, abi_ulong target_fds_addr) } #endif -#ifdef TARGET_NR_clock_adjtime -/* IDs of the various system clocks */ -#define TARGET_CLOCK_REALTIME 0 -#define TARGET_CLOCK_MONOTONIC 1 -#define TARGET_CLOCK_PROCESS_CPUTIME_ID2 -#define TARGET_CLOCK_THREAD_CPUTIME_ID 3 -#define TARGET_CLOCK_MONOTONIC_RAW 4 -#define TARGET_CLOCK_REALTIME_COARSE 5 -#define TARGET_CLOCK_MONOTONIC_COARSE 6 -#define TARGET_CLOCK_BOOTTIME 7 -#define TARGET_CLOCK_REALTIME_ALARM8 -#define TARGET_CLOCK_BOOTTIME_ALARM9 -#define TARGET_CLOCK_SGI_CYCLE 10 -#define TARGET_CLOCK_TAI 11 - -static void -print_clockid(int clockid, int last) -{ -switch (clockid) { -case TARGET_CLOCK_REALTIME: -qemu_log("CLOCK_REALTIME"); -break; -case TARGET_CLOCK_MONOTONIC: -qemu_log("CLOCK_MONOTONIC"); -break; -case TARGET_CLOCK_PROCESS_CPUTIME_ID: -qemu_log("CLOCK_PROCESS_CPUTIME_ID"); -break; -case TARGET_CLOCK_THREAD_CPUTIME_ID: -qemu_log("CLOCK_THREAD_CPUTIME_ID"); -break; -case TARGET_CLOCK_MONOTONIC_RAW: -qemu_log("CLOCK_MONOTONIC_RAW"); -break; -case TARGET_CLOCK_RE
[PATCH v4 4/5] linux-user: Add an api to print enumareted argument values with strace
This patch introduces a type 'struct enums' and function 'print_enums()' that can be used to print enumerated argument values of some syscalls in strace. This can be used in future strace implementations. Also, macros 'ENUM_GENERIC()', 'ENUM_TARGET()' and 'ENUM_END', are introduced to enable automatic generation of aproppriate enumarated values and their repsective string representations (these macros are exactly the same as 'FLAG_GENERIC()', 'FLAG_TARGET()' and 'FLAG_END'). Future patches are planned to modify all existing print functions in 'strace.c' that print arguments of syscalls with enumerated values to use this new api. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/strace.c | 31 +++ 1 file changed, 31 insertions(+) diff --git a/linux-user/strace.c b/linux-user/strace.c index 40f863c6e2..def92c4d73 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -52,9 +52,23 @@ struct flags { /* end of flags array */ #define FLAG_END { 0, NULL } +/* Structure used to translate enumerated values into strings */ +struct enums { +abi_longe_value; /* enum value */ +const char *e_string; /* stringified enum */ +}; + +/* common enums for all architectures */ +#define ENUM_GENERIC(name) { name, #name } +/* target specific enums */ +#define ENUM_TARGET(name) { TARGET_ ## name, #name } +/* end of enums array */ +#define ENUM_END { 0, NULL } + UNUSED static const char *get_comma(int); UNUSED static void print_pointer(abi_long, int); UNUSED static void print_flags(const struct flags *, abi_long, int); +UNUSED static void print_enums(const struct enums *, abi_long, int); UNUSED static void print_at_dirfd(abi_long, int); UNUSED static void print_file_mode(abi_long, int); UNUSED static void print_open_flags(abi_long, int); @@ -1248,6 +1262,23 @@ print_flags(const struct flags *f, abi_long flags, int last) } } +static void +print_enums(const struct enums *e, abi_long enum_arg, int last) +{ +for (; e->e_string != NULL; e++) { +if (e->e_value == enum_arg) { +qemu_log("%s", e->e_string); +break; +} +} + +if (e->e_string == NULL) { +qemu_log("%#x", (unsigned int)enum_arg); +} + +qemu_log("%s", get_comma(last)); +} + static void print_at_dirfd(abi_long dirfd, int last) { -- 2.25.1
[PATCH v4 0/5] Add strace support for printing arguments for a group of selected syscalls
This series covers strace support for following syscalls: *truncate() *munlock() *clock_gettimeofday() *ftruncate()*munlockall() *clock_getitimer() *getsid() *clock_getres() *clock_setitimer() *mlock()*clock_gettime() *mlockall() *clock_settime() Testing method: Mini test programs were written that run these syscalls for different arguments. Those programs were compiled (sometimes using cross-compilers) for the following architectures: * Intel 64-bit (little endian) (gcc) * Power pc 32-bit (big endian) (powerpc-linux-gnu-gcc) * Power pc 64-bit (big endian) (powerpc64-linux-gnu-gcc) The corresponding native programs were executed with strace, without using QEMU, on intel (x86_64) host. All applicable compiled programs were in turn executed with "-strace" through QEMU and the strace printing results obtained were the same ones gotten for native execution. v2: * added patch that enables 'cpu_env' to be accessible from "strace.c" * cut and pasted "regpairs_aligned" from 'syscall.c' to 'qemu.h' so that it can be used for "print_truncate64" and "print_ftruncate64" * changed flag names from 'TARGET_MLOCKALL_MCL_*' to 'TARGET_MCL_*' * added target flag value 'TARGET_MCL_ONFAULT' for 'MCL_ONFAULT' * added 'print_syscall_ret_setitimer' for old value of the interval timer * added a function 'print_itimer_type' that prints the interval timer type v3: * added patch that introduces an api that prints enumarted values with strace * used this new introduced api to print certain arguments of syscalls in patch 4 * rebased the series to use the new 'print_syscall_err()' v4: * modified 'print_itimerval()' function in 'syscall.c' Filip Bozuta (5): linux-user: Make cpu_env accessible in strace.c linux-user: Add strace support for printing arguments of truncate()/ftruncate() and getsid() linux-user: Add strace support for printing arguments of syscalls used to lock and unlock memory linux-user: Add an api to print enumareted argument values with strace linux-user: Add strace support for printing arguments of some clock and time functions linux-user/aarch64/target_syscall.h| 5 +- linux-user/alpha/target_syscall.h | 5 +- linux-user/arm/target_syscall.h| 6 +- linux-user/cris/target_syscall.h | 5 +- linux-user/hppa/target_syscall.h | 5 +- linux-user/i386/target_syscall.h | 5 +- linux-user/m68k/target_syscall.h | 6 +- linux-user/microblaze/target_syscall.h | 5 +- linux-user/mips/target_syscall.h | 5 +- linux-user/mips64/target_syscall.h | 5 +- linux-user/nios2/target_syscall.h | 5 +- linux-user/openrisc/target_syscall.h | 5 +- linux-user/ppc/target_syscall.h| 5 +- linux-user/qemu.h | 39 +- linux-user/riscv/target_syscall.h | 5 +- linux-user/s390x/target_syscall.h | 5 +- linux-user/sh4/target_syscall.h| 5 +- linux-user/sparc/target_syscall.h | 5 +- linux-user/sparc64/target_syscall.h| 5 +- linux-user/strace.c| 865 - linux-user/strace.list | 35 +- linux-user/syscall.c | 47 +- linux-user/tilegx/target_syscall.h | 5 +- linux-user/x86_64/target_syscall.h | 5 +- linux-user/xtensa/target_syscall.h | 5 +- 25 files changed, 694 insertions(+), 399 deletions(-) -- 2.25.1
[PATCH v4 2/5] linux-user: Add strace support for printing arguments of truncate()/ftruncate() and getsid()
This patch implements strace argument printing functionality for following syscalls: * truncate, ftruncate - truncate a file to a specified length int truncate/truncate64(const char *path, off_t length) int ftruncate/ftruncate64(int fd, off_t length) man page: https://man7.org/linux/man-pages/man2/truncate.2.html * getsid - get session ID pid_t getsid(pid_t pid) man page: https://man7.org/linux/man-pages/man2/getsid.2.html Implementation notes: Syscalls truncate/truncate64 take string argument types and thus a separate print function "print_truncate/print_truncate64" is stated in file "strace.list". This function is defined and implemented in "strace.c" by using an existing function used to print string arguments: "print_string()". For syscall ftruncate64, a separate printing function was also stated in "strace.c" as it requires a special kind of handling. The other syscalls have only primitive argument types, so the rest of the implementation was handled by stating an appropriate printing format in file "strace.list". Function "regpairs_aligned()" was cut & pasted from "syscall.c" to "qemu.h" as it is used by functions "print_truncate64()" and "print_ftruncate64()" to print the offset arguments of "truncate64()" and "ftruncate64()". Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/qemu.h | 35 +++ linux-user/strace.c| 47 ++ linux-user/strace.list | 10 - linux-user/syscall.c | 32 4 files changed, 87 insertions(+), 37 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 63ddfe86fd..f431805e57 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -706,6 +706,41 @@ static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) } #endif /* TARGET_ABI_BITS != 32 */ + +/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ +#ifdef TARGET_ARM +static inline int regpairs_aligned(void *cpu_env, int num) +{ +return CPUARMState *)cpu_env)->eabi) == 1) ; +} +#elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32) +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#elif defined(TARGET_PPC) && !defined(TARGET_PPC64) +/* + * SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs + * of registers which translates to the same as ARM/MIPS, because we start with + * r3 as arg1 + */ +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#elif defined(TARGET_SH4) +/* SH4 doesn't align register pairs, except for p{read,write}64 */ +static inline int regpairs_aligned(void *cpu_env, int num) +{ +switch (num) { +case TARGET_NR_pread64: +case TARGET_NR_pwrite64: +return 1; + +default: +return 0; +} +} +#elif defined(TARGET_XTENSA) +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#else +static inline int regpairs_aligned(void *cpu_env, int num) { return 0; } +#endif + /** * preexit_cleanup: housekeeping before the guest exits * diff --git a/linux-user/strace.c b/linux-user/strace.c index f0624b6206..7dc239b9f1 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1958,6 +1958,53 @@ print_lseek(void *cpu_env, const struct syscallname *name, } #endif +#ifdef TARGET_NR_truncate +static void +print_truncate(void *cpu_env, 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_string(arg0, 0); +print_raw_param(TARGET_ABI_FMT_ld, arg1, 1); +print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_truncate64 +static void +print_truncate64(void *cpu_env, 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_string(arg0, 0); +if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) { +arg1 = arg2; +arg2 = arg3; +} +print_raw_param("%" PRIu64, target_offset64(arg1, arg2), 1); +print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_ftruncate64 +static void +print_ftruncate64(void *cpu_env, 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_raw_param("%d", arg0, 0); +if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) { +arg1 = arg2; +arg2 = arg3; +} +print_raw_param("%" PRIu64, target_
[PATCH] linux-user: Fix 'utimensat()' implementation
Implementation of syscall 'utimensat()' in 'syscall.c' uses functions target_to_host/host_to_target_timespec() to convert values of 'struct timespec' between host and target. However, the implementation doesn't check whether the conversion succeeds and thus can cause an inappropriate error or succeed unappropriately instead of setting errno EFAULT ('Bad address') which is supposed to be set in these cases. This was confirmed with the LTP test for utimensat ('testcases/utimensat') which fails for test cases when the errno EFAULT is expected. After changes from this patch, the test passes for all test cases. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 05f03919ff..920656191b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -11722,8 +11722,13 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, if (!arg3) { tsp = NULL; } else { -target_to_host_timespec(ts, arg3); -target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec)); +if (target_to_host_timespec(ts, arg3)) { +return -TARGET_EFAULT; +} +if (target_to_host_timespec(ts + 1, arg3 + +sizeof(struct target_timespec))) { +return -TARGET_EFAULT; +} tsp = ts; } if (!arg2) -- 2.25.1
[PATCH v2 0/8] linux-user: Adding support for a group of btrfs ioctls
This series covers support for following btrfs ioctls *BTRFS_SUBVOL_CREATE *BTRFS_IOC_ADD_DEV *BTRFS_SUBVOL_SETFLAGS *BTRFS_IOC_RM_DEV *BTRFS_SUBVOL_GETFLAGS *BTRFS_IOC_DEV_INFO *BTRFS_GET_SUBVOL_INFO *BTRFS_IOC_GET_DEV_STATS *BTRFS_IOC_SNAP_CREATE *BTRFS_IOC_GET_FEATURES *BTRFS_IOC_SNAP_DESTROY*BTRFS_IOC_SET_FEATURES *BTRFS_IOC_SCAN_DEV*BTRFS_IOC_GET_SUPPORTED_FEATURES *BTRFS_IOC_DEFAULT_SUBVOL *BTRFS_IOC_QUOTA_RESCAN *BTRFS_IOC_GET_SUBVOL_ROOTREF *BTRFS_IOC_QUOTA_RESCAN_WAIT *BTRFS_IOC_QUOTA_CTL *BTRFS_IOC_SCRUB *BTRFS_IOC_QGROUP_CREATE *BTRFS_IOC_SCRUB_CANCEL *BTRFS_IOC_QGROUP_ASSIGN *BTRFS_IOC_SCRUB_PROGRESS *BTRFS_IOC_INO_PATHS *BTRFS_IOC_QGROUP_LIMIT *BTRFS_IOC_LOGICAL_INO *BTRFS_IOC_QUOTA_RESCAN_STATUS *BTRFS_IOC_LOGICAL_INO_V2 *BTRFS_IOC_INO_LOOKUP_USER *BTRFS_IOC_INO_LOOKUP The functionalities of individual ioctls were described in this series patch commit messages. Since all of these ioctls are added in kernel version 3.9, their definitions in file 'linux-user/ioctls.h' are enwrapped in an #ifdef directive. Testing method: Mini test programs were written for these ioctls. These test programs can be found on a repositort which is located on the link: https://github.com/bozutaf/btrfs-tests These test programs were compiled (sometimes using cross compilers) for following architectures: * Intel 64-bit (little endian) * Power pc 32-bit (big endian) * Power pc 64-bit (big endian) The corresponding native programs were executed without using QEMU on an intel x86_64 host. All applicable compiled programs were in turn executed through QEMU and the results obtained were the same ones gotten for native execution. v2: * Merged two series in one 8 patch series * Changed target ioctl definitions from IOR/IOW/IOWR to IORU/IOWU/IOWRU * Fixed some thunk struct definitions Filip Bozuta (8): linux-user: Add support for a group of btrfs ioctls used for subvolumes linux-user: Add support for a group of btrfs ioctls used for snapshots linux-user: Add support for btrfs ioctls used to manipulate with devices linux-user: Add support for btrfs ioctls used to get/set features linux-user: Add support for a group of btrfs inode ioctls linux-user: Add support for two btrfs ioctls used for subvolume linux-user: Add support for btrfs ioctls used to manage quota linux-user: Add support for btrfs ioctls used to scrub a filesystem configure | 9 +++ linux-user/ioctls.h| 124 linux-user/syscall.c | 3 + linux-user/syscall_defs.h | 37 ++ linux-user/syscall_types.h | 140 + 5 files changed, 313 insertions(+) -- 2.25.1
[PATCH v2 7/8] linux-user: Add support for btrfs ioctls used to manage quota
This patch implements functionality for following ioctls: BTRFS_IOC_QUOTA_CTL - Enabling/Disabling quota support Enable or disable quota support for a btrfs filesystem. Quota support is enabled or disabled using the ioctls third argument which represents a pointer to a following type: struct btrfs_ioctl_quota_ctl_args { __u64 cmd; __u64 status; }; Before calling this ioctl, the 'cmd' field should be filled with one of the values 'BTRFS_QUOTA_CTL_ENABLE' (enabling quota) 'BTRFS_QUOTA_CTL_DISABLE' (disabling quota). BTRFS_IOC_QGROUP_CREATE - Creating/Removing a subvolume quota group Create or remove a subvolume quota group. The subvolume quota group is created or removed using the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_qgroup_create_args { __u64 create; __u64 qgroupid; }; Before calling this ioctl, the 'create' field should be filled with the aproppriate value depending on if the user wants to create or remove a quota group (0 for removing, everything else for creating). Also, the 'qgroupid' field should be filled with the value for the quota group id that is to be created. BTRFS_IOC_QGROUP_ASSIGN - Asigning or removing a quota group as child group Asign or remove a quota group as child quota group of another group in the btrfs filesystem. The asignment is done using the ioctl's third argument which represents a pointert to a following type: struct btrfs_ioctl_qgroup_assign_args { __u64 assign; __u64 src; __u64 dst; }; Before calling this ioctl, the 'assign' field should be filled with the aproppriate value depending on if the user wants to asign or remove a quota group as a child quota group of another group (0 for removing, everythin else for asigning). Also, the 'src' and 'dst' fields should be filled with the aproppriate quota group id values depending on which quota group needs to asigned or removed as child quota group of another group ('src' gets asigned or removed as child group of 'dst'). BTRFS_IOC_QGROUP_LIMIT - Limiting the size of a quota group Limit the size of a quota group. The size of the quota group is limited with the ioctls third argument which represents a pointer to a following type: struct btrfs_ioctl_qgroup_limit_args { __u64 qgroupid; struct btrfs_qgroup_limit lim; }; Before calling this ioctl, the 'qgroup' id field should be filled with aproppriate value of the quota group id for which the size is to be limited. The second field is of following type: struct btrfs_qgroup_limit { __u64 flags; __u64 max_rfer; __u64 max_excl; __u64 rsv_rfer; __u64 rsv_excl; }; The 'max_rfer' field should be filled with the size to which the quota group should be limited. The 'flags' field can be used for passing additional options and can have values which can be found on: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/btrfs.h#L67 BTRFS_IOC_QUOTA_RESCAN_STATUS - Checking status of running rescan operation Check status of a running rescan operation. The status is checked using the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_quota_rescan_args { __u64 flags; __u64 progress; __u64 reserved[6]; }; If there is a rescan operation running, 'flags' field is set to 1, and 'progress' field is set to aproppriate value which represents the progress of the operation. BTRFS_IOC_QUOTA_RESCAN - Starting a rescan operation Start ar rescan operation to Trash all quota groups and scan the metadata again with the current config. Before calling this ioctl, BTRFS_IOC_QUOTA_RESCAN_STATUS sould be run to check if there is already a rescan operation runing. After that ioctl call, the received 'struct btrfs_ioctl_quota_rescan_args' should be than passed as this ioctls third argument. BTRFS_IOC_QUOTA_RESCAN_WAIT - Waiting for a rescan operation to finish Wait until a rescan operation is finished (if there is a rescan operation running). The third ioctls argument is ignored. Implementation notes: Almost all of the ioctls in this patch use structure types as third arguments. That is the reason why aproppriate thunk definitions were added in file 'syscall_types.h'. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/ioctls.h| 27 +++ linux-user/syscall_defs.h | 7 +++ linux-user/syscall_types.h | 29 + 3 files changed, 63 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 2c553103e6..8665f504bf 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -227,6 +227,33 @@ IOCTL
[PATCH v2 6/8] linux-user: Add support for two btrfs ioctls used for subvolume
This patch implements functionality for following ioctl: BTRFS_IOC_DEFAULT_SUBVOL - Setting a default subvolume Set a default subvolume for a btrfs filesystem. The third ioctl's argument is a '__u64' (unsigned long long) which represents the id of a subvolume that is to be set as the default. BTRFS_IOC_GET_SUBVOL_ROOTREF - Getting tree and directory id of subvolumes Read tree and directory id of subvolumes from a btrfs filesystem. The tree and directory id's are returned in the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_get_subvol_rootref_args { /* in/out, minimum id of rootref's treeid to be searched */ __u64 min_treeid; /* out */ struct { __u64 treeid; __u64 dirid; } rootref[BTRFS_MAX_ROOTREF_BUFFER_NUM]; /* out, number of found items */ __u8 num_items; __u8 align[7]; }; Before calling this ioctl, 'min_treeid' field should be filled with value that represent the minimum value for the tree id. Implementation notes: Ioctl BTRFS_IOC_GET_SUBVOL_ROOTREF uses the above mentioned structure type as third argument. That is the reason why a aproppriate thunk structure definition is added in file 'syscall_types.h'. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/ioctls.h| 7 +++ linux-user/syscall_defs.h | 3 +++ linux-user/syscall_types.h | 11 +++ 3 files changed, 21 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index a7f5664487..2c553103e6 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -206,6 +206,9 @@ IOCTL(BTRFS_IOC_INO_LOOKUP, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_args))) #endif +#ifdef BTRFS_IOC_DEFAULT_SUBVOL + IOCTL(BTRFS_IOC_DEFAULT_SUBVOL, IOC_W, MK_PTR(TYPE_ULONGLONG)) +#endif #ifdef BTRFS_IOC_SUBVOL_GETFLAGS IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG)) #endif @@ -248,6 +251,10 @@ IOCTL(BTRFS_IOC_GET_SUBVOL_INFO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_subvol_info_args))) #endif +#ifdef BTRFS_IOC_GET_SUBVOL_ROOTREF + IOCTL(BTRFS_IOC_GET_SUBVOL_ROOTREF, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_subvol_rootref_args))) +#endif #ifdef BTRFS_IOC_INO_LOOKUP_USER IOCTL(BTRFS_IOC_INO_LOOKUP_USER, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_user_args))) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 538b884b8f..f1718ac521 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -976,6 +976,8 @@ struct target_rtc_pll_info { #define TARGET_BTRFS_IOC_SUBVOL_CREATE TARGET_IOWU(BTRFS_IOCTL_MAGIC, 14) #define TARGET_BTRFS_IOC_SNAP_DESTROY TARGET_IOWU(BTRFS_IOCTL_MAGIC, 15) #define TARGET_BTRFS_IOC_INO_LOOKUP TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 18) +#define TARGET_BTRFS_IOC_DEFAULT_SUBVOL TARGET_IOW(BTRFS_IOCTL_MAGIC, 19,\ + abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_GETFLAGSTARGET_IOR(BTRFS_IOCTL_MAGIC, 25,\ abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_SETFLAGSTARGET_IOW(BTRFS_IOCTL_MAGIC, 26,\ @@ -989,6 +991,7 @@ struct target_rtc_pll_info { #define TARGET_BTRFS_IOC_GET_SUPPORTED_FEATURES TARGET_IORU(BTRFS_IOCTL_MAGIC, 57) #define TARGET_BTRFS_IOC_LOGICAL_INO_V2 TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 59) #define TARGET_BTRFS_IOC_GET_SUBVOL_INFOTARGET_IORU(BTRFS_IOCTL_MAGIC, 60) +#define TARGET_BTRFS_IOC_GET_SUBVOL_ROOTREF TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 61) #define TARGET_BTRFS_IOC_INO_LOOKUP_USER TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 62) /* usb ioctls */ diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index 978f2d682c..6bac8f46bb 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -381,6 +381,17 @@ STRUCT(btrfs_ioctl_dev_info_args, MK_ARRAY(TYPE_ULONGLONG, 379), /* unused */ MK_ARRAY(TYPE_CHAR, BTRFS_DEVICE_PATH_NAME_MAX)) /* path */ +STRUCT(rootref, + TYPE_ULONGLONG, /* treeid */ + TYPE_ULONGLONG) /* dirid */ + +STRUCT(btrfs_ioctl_get_subvol_rootref_args, + TYPE_ULONGLONG, /* min_treeid */ + MK_ARRAY(MK_STRUCT(STRUCT_rootref), +BTRFS_MAX_ROOTREF_BUFFER_NUM), /* rootref */ + TYPE_CHAR, /* num_items */ + MK_ARRAY(TYPE_CHAR, 7)) /* align */ + STRUCT(btrfs_ioctl_get_dev_stats, TYPE_ULONGLONG, /* devid */ TYPE_ULONGLONG, /* nr_items */ -- 2.25.1
[PATCH v2 4/8] linux-user: Add support for btrfs ioctls used to get/set features
This patch implements functionality for following ioctls: BTRFS_IOC_GET_FEATURES - Getting feature flags Read feature flags for a btrfs filesystem. The feature flags are returned inside the ioctl's third argument which represents a pointer to a following structure type: struct btrfs_ioctl_feature_flags { __u64 compat_flags; __u64 compat_ro_flags; __u64 incompat_flags; }; All of the structure field represent bit masks that can be composed of values which can be found on: https://elixir.bootlin.com/linux/latest/source/fs/btrfs/ctree.h#L282 BTRFS_IOC_SET_FEATURES - Setting feature flags Set and clear feature flags for a btrfs filesystem. The feature flags are set using the ioctl's third argument which represents a 'struct btrfs_ioctl_feature_flags[2]' array. The first element of the array represent flags which are to be cleared and the second element of the array represent flags which are to be set. The second element has the priority over the first, which means that if there are matching flags in the elements, they will be set in the filesystem. If the flag values in the third argument aren't correctly set to be composed of the available predefined flag values, errno ENOPERM ("Operation not permitted") is returned. BTRFS_IOC_GET_SUPPORTED_FEATURES - Getting supported feature flags Read supported feature flags for a btrfs filesystem. The supported feature flags are read using the ioctl's third argument which represents a 'struct btrfs_ioctl_feature_flags[3]' array. The first element of this array represents all of the supported flags in the btrfs filesystem. The second element represents flags that can be safely set and third element represent flags that can be safely clearead. Implementation notes: All of the implemented ioctls use 'struct btrfs_ioctl_feature_flags' as third argument. That is the reason why a corresponding defintion was added in file 'linux-user/syscall_types.h'. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/ioctls.h| 12 linux-user/syscall_defs.h | 3 +++ linux-user/syscall_types.h | 5 + 3 files changed, 20 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index c20bd97736..c6303a0406 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -216,6 +216,18 @@ IOCTL(BTRFS_IOC_GET_DEV_STATS, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_dev_stats))) #endif +#ifdef BTRFS_IOC_GET_FEATURES + IOCTL(BTRFS_IOC_GET_FEATURES, IOC_R, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_feature_flags))) +#endif +#ifdef BTRFS_IOC_SET_FEATURES + IOCTL(BTRFS_IOC_SET_FEATURES, IOC_W, + MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_btrfs_ioctl_feature_flags), 2))) +#endif +#ifdef BTRFS_IOC_GET_SUPPORTED_FEATURES + IOCTL(BTRFS_IOC_GET_SUPPORTED_FEATURES, IOC_R, + MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_btrfs_ioctl_feature_flags), 3))) +#endif #ifdef BTRFS_IOC_GET_SUBVOL_INFO IOCTL(BTRFS_IOC_GET_SUBVOL_INFO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_subvol_info_args))) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 23f966d552..13a444356b 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -981,6 +981,9 @@ struct target_rtc_pll_info { abi_ullong) #define TARGET_BTRFS_IOC_DEV_INFO TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 30) #define TARGET_BTRFS_IOC_GET_DEV_STATS TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 52) +#define TARGET_BTRFS_IOC_GET_FEATURES TARGET_IORU(BTRFS_IOCTL_MAGIC, 57) +#define TARGET_BTRFS_IOC_SET_FEATURES TARGET_IOWU(BTRFS_IOCTL_MAGIC, 57) +#define TARGET_BTRFS_IOC_GET_SUPPORTED_FEATURES TARGET_IORU(BTRFS_IOCTL_MAGIC, 57) #define TARGET_BTRFS_IOC_GET_SUBVOL_INFOTARGET_IORU(BTRFS_IOCTL_MAGIC, 60) /* usb ioctls */ diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index b5718231e5..e26ab01e8f 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -365,6 +365,11 @@ STRUCT(btrfs_ioctl_get_dev_stats, MK_ARRAY(TYPE_ULONGLONG, 128 - 2 - BTRFS_DEV_STAT_VALUES_MAX)) /* unused */ +STRUCT(btrfs_ioctl_feature_flags, + TYPE_ULONGLONG, /* compat_flags */ + TYPE_ULONGLONG, /* compat_ro_flags */ + TYPE_ULONGLONG) /* incompat_flags */ + STRUCT(rtc_time, TYPE_INT, /* tm_sec */ TYPE_INT, /* tm_min */ -- 2.25.1
[PATCH v2 8/8] linux-user: Add support for btrfs ioctls used to scrub a filesystem
This patch implements functionality for following ioctls: BTRFS_IOC_SCRUB - Starting a btrfs filesystem scrub Start a btrfs filesystem scrub. The third ioctls argument is a pointer to a following type: struct btrfs_ioctl_scrub_args { __u64 devid;/* in */ __u64 start;/* in */ __u64 end; /* in */ __u64 flags;/* in */ struct btrfs_scrub_progress progress; /* out */ /* pad to 1k */ __u64 unused[(1024-32-sizeof(struct btrfs_scrub_progress))/8]; }; Before calling this ioctl, field 'devid' should be filled with value that represents the device id of the btrfs filesystem for which the scrub is to be started. BTRFS_IOC_SCRUB_CANCEL - Canceling scrub of a btrfs filesystem Cancel a btrfs filesystem scrub if it is running. The third ioctls argument is ignored. BTRFS_IOC_SCRUB_PROGRESS - Getting status of a running scrub Read the status of a running btrfs filesystem scrub. The third ioctls argument is a pointer to the above mentioned 'struct btrfs_ioctl_scrub_args'. Similarly as with 'BTRFS_IOC_SCRUB', the 'devid' field should be filled with value that represents the id of the btrfs device for which the scrub has started. The status of a running scrub is returned in the field 'progress' which is of type 'struct btrfs_scrub_progress' and its definition can be found at: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/btrfs.h#L150 Implementation nots: Ioctls in this patch use type 'struct btrfs_ioctl_scrub_args' as their third argument. That is the reason why an aproppriate thunk type definition is added in file 'syscall_types.h'. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/ioctls.h| 11 +++ linux-user/syscall_defs.h | 3 +++ linux-user/syscall_types.h | 27 +++ 3 files changed, 41 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 8665f504bf..bf80615438 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -215,6 +215,17 @@ #ifdef BTRFS_IOC_SUBVOL_SETFLAGS IOCTL(BTRFS_IOC_SUBVOL_SETFLAGS, IOC_W, MK_PTR(TYPE_ULONGLONG)) #endif +#ifdef BTRFS_IOC_SCRUB + IOCTL(BTRFS_IOC_SCRUB, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_scrub_args))) +#endif +#ifdef BTRFS_IOC_SCRUB_CANCEL + IOCTL(BTRFS_IOC_SCRUB_CANCEL, 0, TYPE_NULL) +#endif +#ifdef BTRFS_IOC_SCRUB_PROGRESS + IOCTL(BTRFS_IOC_SCRUB_PROGRESS, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_scrub_args))) +#endif #ifdef BTRFS_IOC_DEV_INFO IOCTL(BTRFS_IOC_DEV_INFO, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_dev_info_args))) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 1b1b2c2d96..83c291f2d3 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -982,6 +982,9 @@ struct target_rtc_pll_info { abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_SETFLAGSTARGET_IOW(BTRFS_IOCTL_MAGIC, 26,\ abi_ullong) +#define TARGET_BTRFS_IOC_SCRUB TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 27) +#define TARGET_BTRFS_IOC_SCRUB_CANCEL TARGET_IO(BTRFS_IOCTL_MAGIC, 28) +#define TARGET_BTRFS_IOC_SCRUB_PROGRESS TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 29) #define TARGET_BTRFS_IOC_DEV_INFO TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 30) #define TARGET_BTRFS_IOC_INO_PATHS TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 35) #define TARGET_BTRFS_IOC_LOGICAL_INO TARGET_IOWRU(BTRFS_IOCTL_MAGIC, 36) diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index 2f5bad808e..fd6a91a309 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -373,6 +373,33 @@ STRUCT(btrfs_ioctl_ino_lookup_user_args, MK_ARRAY(TYPE_CHAR, BTRFS_VOL_NAME_MAX + 1), /* name */ MK_ARRAY(TYPE_CHAR, BTRFS_INO_LOOKUP_USER_PATH_MAX)) /* path */ +STRUCT(btrfs_scrub_progress, + TYPE_ULONGLONG, /* data_extents_scrubbed */ + TYPE_ULONGLONG, /* tree_extents_scrubbed */ + TYPE_ULONGLONG, /* data_bytes_scrubbed */ + TYPE_ULONGLONG, /* tree_bytes_scrubbed */ + TYPE_ULONGLONG, /* read_errors */ + TYPE_ULONGLONG, /* csum_errors */ + TYPE_ULONGLONG, /* verify_errors */ + TYPE_ULONGLONG, /* no_csum */ + TYPE_ULONGLONG, /* csum_discards */ + TYPE_ULONGLONG, /* super_errors */ + TYPE_ULONGLONG, /* malloc_errors */ + TYPE_ULONGLONG, /* uncorrectable_errors */ + TYPE_ULONGLONG, /* corrected_er */ + TYPE_ULONGLONG, /* last_physical */ + TYPE_ULONGLONG) /* unverified_errors */ + +STRUCT(btrfs_ioctl_scrub_args, + TYPE_ULONGLONG, /* devid */ + TYPE_ULONGLONG, /* start
[PATCH v2 5/8] linux-user: Add support for a group of btrfs inode ioctls
This patch implements functionality of following ioctls: BTRFS_IOC_INO_LOOKUP - Reading tree root id and path Read tree root id and path for a given file or directory. The name and tree root id are returned in an ioctl's third argument that represents a pointer to a following type: struct btrfs_ioctl_ino_lookup_args { __u64 treeid; __u64 objectid; char name[BTRFS_INO_LOOKUP_PATH_MAX]; }; Before calling this ioctl, field 'objectid' should be filled with the object id value for which the tree id and path are to be read. Value 'BTRFS_FIRST_FREE_OBJECTID' represents the object id for the first available btrfs object (directory or file). BTRFS_IOC_INO_PATHS - Reading paths to all files Read path to all files with a certain inode number. The paths are returned in the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_ino_path_args { __u64 inum; /* in */ __u64 size; /* in */ __u64 reserved[4]; /* struct btrfs_data_container *fspath; out */ __u64 fspath; /* out */ }; Before calling this ioctl, the 'inum' and 'size' field should be filled with the aproppriate inode number and size of the directory where file paths should be looked for. For now, the paths are returned in an '__u64' (unsigned long long) value 'fspath'. BTRFS_IOC_LOGICAL_INO - Reading inode numbers Read inode numbers for files on a certain logical adress. The inode numbers are returned in the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_logical_ino_args { __u64 logical;/* in */ __u64 size; /* in */ __u64 reserved[3];/* must be 0 for now */ __u64 flags; /* in, v2 only */ /* struct btrfs_data_container *inodes;out */ __u64 inodes; }; Before calling this ioctl, the 'logical' and 'size' field should be filled with the aproppriate logical adress and size of where the inode numbers of files should be looked for. For now, the inode numbers are returned in an '__u64' (unsigned long long) value 'inodes'. BTRFS_IOC_LOGICAL_INO_V2 - Reading inode numbers Same as the above mentioned ioctl except that it allows passing a flags 'BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET'. BTRFS_IOC_INO_LOOKUP_USER - Reading subvolume name and path Read name and path of a subvolume. The tree root id and path are read in an ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_ino_lookup_user_args { /* in, inode number containing the subvolume of 'subvolid' */ __u64 dirid; /* in */ __u64 treeid; /* out, name of the subvolume of 'treeid' */ char name[BTRFS_VOL_NAME_MAX + 1]; /* * out, constructed path from the directory with which the ioctl is * called to dirid */ char path[BTRFS_INO_LOOKUP_USER_PATH_MAX]; }; Before calling this ioctl, the 'dirid' and 'treeid' field should be filled with aproppriate values which represent the inode number of the directory that contains the subvolume and treeid of the subvolume. Implementation notes: All of the ioctls in this patch use structure types as third arguments. That is the reason why aproppriate thunk definitions were added in file 'syscall_types.h'. Signed-off-by: Filip Bozuta --- linux-user/ioctls.h| 20 linux-user/syscall_defs.h | 5 + linux-user/syscall_types.h | 24 3 files changed, 49 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index c6303a0406..a7f5664487 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -202,6 +202,10 @@ IOCTL(BTRFS_IOC_SNAP_DESTROY, IOC_W, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) #endif +#ifdef BTRFS_IOC_INO_LOOKUP + IOCTL(BTRFS_IOC_INO_LOOKUP, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_args))) +#endif #ifdef BTRFS_IOC_SUBVOL_GETFLAGS IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG)) #endif @@ -212,6 +216,14 @@ IOCTL(BTRFS_IOC_DEV_INFO, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_dev_info_args))) #endif +#ifdef BTRFS_IOC_INO_PATHS + IOCTL(BTRFS_IOC_INO_PATHS, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_path_args))) +#endif +#ifdef BTRFS_IOC_LOGICAL_INO + IOCTL(BTRFS_IOC_LOGICAL_INO, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_logical_ino_args
[PATCH v2 1/8] linux-user: Add support for a group of btrfs ioctls used for subvolumes
This patch implements functionality of following ioctls: BTRFS_IOC_SUBVOL_CREATE - Creating a btrfs subvolume Create a btrfs subvolume. The subvolume is created using the ioctl's third argument which represents a pointer to a following structure type: struct btrfs_ioctl_vol_args { __s64 fd; char name[BTRFS_PATH_NAME_MAX + 1]; }; Before calling this ioctl, the fields of this structure should be filled with aproppriate values. The fd field represents the file descriptor value of the subvolume and the name field represents the subvolume path. BTRFS_IOC_SUBVOL_GETFLAGS - Getting subvolume flags Read the flags of the btrfs subvolume. The flags are read using the ioctl's third argument that is a pointer of __u64 (unsigned long). The third argument represents a bit mask that can be composed of following values: BTRFS_SUBVOL_RDONLY (1ULL << 1) BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) BTRFS_DEVICE_SPEC_BY_ID (1ULL << 3) BTRFS_SUBVOL_SPEC_BY_ID (1ULL << 4) BTRFS_IOC_SUBVOL_SETFLAGS - Setting subvolume flags Set the flags of the btrfs subvolume. The flags are set using the ioctl's third argument that is a pointer of __u64 (unsigned long). The third argument represents a bit mask that can be composed of same values as in the case of previous ioctl (BTRFS_IOC_SUBVOL_GETFLAGS). BTRFS_IOC_SUBVOL_GETINFO - Getting subvolume information Read information about the subvolume. The subvolume information is returned in the ioctl's third argument which represents a pointer to a following structure type: struct btrfs_ioctl_get_subvol_info_args { /* Id of this subvolume */ __u64 treeid; /* Name of this subvolume, used to get the real name at mount point */ char name[BTRFS_VOL_NAME_MAX + 1]; /* * Id of the subvolume which contains this subvolume. * Zero for top-level subvolume or a deleted subvolume. */ __u64 parent_id; /* * Inode number of the directory which contains this subvolume. * Zero for top-level subvolume or a deleted subvolume */ __u64 dirid; /* Latest transaction id of this subvolume */ __u64 generation; /* Flags of this subvolume */ __u64 flags; /* UUID of this subvolume */ __u8 uuid[BTRFS_UUID_SIZE]; /* * UUID of the subvolume of which this subvolume is a snapshot. * All zero for a non-snapshot subvolume. */ __u8 parent_uuid[BTRFS_UUID_SIZE]; /* * UUID of the subvolume from which this subvolume was received. * All zero for non-received subvolume. */ __u8 received_uuid[BTRFS_UUID_SIZE]; /* Transaction id indicating when change/create/send/receive happened */ __u64 ctransid; __u64 otransid; __u64 stransid; __u64 rtransid; /* Time corresponding to c/o/s/rtransid */ struct btrfs_ioctl_timespec ctime; struct btrfs_ioctl_timespec otime; struct btrfs_ioctl_timespec stime; struct btrfs_ioctl_timespec rtime; /* Must be zero */ __u64 reserved[8]; }; All of the fields of this structure are filled after the ioctl call. Implementation notes: Ioctls BTRFS_IOC_SUBVOL_CREATE and BTRFS_IOC_SUBVOL_GETINFO have structure types as third arguments. That is the reason why a corresponding definition are added in file 'linux-user/syscall_types.h'. The line '#include ' is added in file 'linux-user/syscall.c' to recognise preprocessor definitions for these ioctls. Since the file "linux/btrfs.h" was added in the kernel version 3.9, it is enwrapped in an #ifdef statement with parameter CONFIG_BTRFS which is defined in 'configure' if the header file is present. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- configure | 9 + linux-user/ioctls.h| 15 +++ linux-user/syscall.c | 3 +++ linux-user/syscall_defs.h | 8 linux-user/syscall_types.h | 28 5 files changed, 63 insertions(+) diff --git a/configure b/configure index b969dee675..8b3b214031 100755 --- a/configure +++ b/configure @@ -4945,6 +4945,12 @@ if check_include sys/kcov.h ; then kcov=yes fi +# check for btrfs filesystem support (kernel must be 3.9+) +btrfs=no +if check_include linux/btrfs.h ; then +btrfs=yes +fi + # If we're making warnings fatal, apply this to Sphinx runs as well sphinx_werror="" if test "$werror" = "yes"; then @@ -7057,6 +7063,9 @@ fi if test "$kcov" = "yes" ; then echo "CONFIG_KCOV=y" >> $config_host_mak fi +if test "$btrfs" = "yes" ; then + echo "CONFIG_BTRFS=y" >
[PATCH v2 3/8] linux-user: Add support for btrfs ioctls used to manipulate with devices
This patch implements functionality for following ioctls: BTRFS_IOC_SCAN_DEV - Scanning device for a btrfs filesystem Scan a device for a btrfs filesystem. The device that is to be scanned is passed in the ioctl's third argument which represents a pointer to a 'struct ioc_vol_args' (which was mentioned in a previous patch). Before calling this ioctl, the name field of this structure should be filled with the aproppriate name value which represents a path for the device. If the device contains a btrfs filesystem, the ioctl returns 0, otherwise a negative value is returned. BTRFS_IOC_ADD_DEV - Adding a device to a btrfs filesystem Add a device to a btrfs filesystem. The device that is to be added is passed in the ioctl's third argument which represents a pointer to a 'struct ioc_vol_args' (which was mentioned in a previous patch). Before calling this ioctl, the name field of this structure should be filled with the aproppriate name value which represents a path for the device. BTRFS_IOC_RM_DEV - Removing a device from a btrfs filesystem Remove a device from a btrfs filesystem. The device that is to be removed is passed in the ioctl's third argument which represents a pointer to a 'struct ioc_vol_args' (which was mentioned in a previous patch). Before calling this ioctl, the name field of this structure should be filled with the aproppriate name value which represents a path for the device. BTRFS_IOC_DEV_INFO - Getting information about a device Obtain information for device in a btrfs filesystem. The information is gathered in the ioctl's third argument which represents a pointer to a following structure type: struct btrfs_ioctl_dev_info_args { __u64 devid;/* in/out */ __u8 uuid[BTRFS_UUID_SIZE]; /* in/out */ __u64 bytes_used; /* out */ __u64 total_bytes; /* out */ __u64 unused[379]; /* pad to 4k */ __u8 path[BTRFS_DEVICE_PATH_NAME_MAX]; /* out */ }; Before calling this ioctl, field "devid" should be set with the id value for the device for which the information is to be obtained. If this field is not aproppriately set, the errno ENODEV ("No such device") is returned. BTRFS_IOC_GET_DEV_STATS - Getting device statistics Obtain stats informatin for device in a btrfs filesystem. The information is gathered in the ioctl's third argument which represents a pointer to a following structure type: struct btrfs_ioctl_get_dev_stats { __u64 devid;/* in */ __u64 nr_items; /* in/out */ __u64 flags;/* in/out */ /* out values: */ __u64 values[BTRFS_DEV_STAT_VALUES_MAX]; /* * This pads the struct to 1032 bytes. It was originally meant to pad to * 1024 bytes, but when adding the flags field, the padding calculation * was not adjusted. */ __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; }; Before calling this ioctl, field "devid" should be set with the id value for the device for which the information is to be obtained. If this field is not aproppriately set, the errno ENODEV ("No such device") is returned. BTRFS_IOC_FORGET_DEV - Remove unmounted devices Search and remove all stale devices (devices which are not mounted). The third ioctl argument is a pointer to a 'struct btrfs_ioctl_vol_args'. The ioctl call will release all unmounted devices which match the path which is specified in the "name" field of the structure. If an empty path ("") is specified, all unmounted devices will be released. Implementation notes: Ioctls BTRFS_IOC_DEV_INFO and BTRFS_IOC_GET_DEV_STATS use types 'struct btrfs_ioctl_dev_info_args' and ' struct btrfs_ioctl_get_dev_stats' as third argument types. That is the reason why corresponding structure definitions were added in file 'linux-user/syscall_types.h'. Since the thunk type for 'struct ioc_vol_args' was already added in a previous patch, the rest of the implementation was straightforward. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/ioctls.h| 24 linux-user/syscall_defs.h | 6 ++ linux-user/syscall_types.h | 16 3 files changed, 46 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 2422675dd0..c20bd97736 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -178,6 +178,22 @@ IOCTL(BTRFS_IOC_SNAP_CREATE, IOC_W, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) #endif +#ifdef BTRFS_IOC_SCAN_DEV + IOCTL(BTRFS_IOC_SCAN_DEV, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_
[PATCH v2 2/8] linux-user: Add support for a group of btrfs ioctls used for snapshots
This patch implements functionality for following ioctls: BTRFS_IOC_SNAP_CREATE - Creating a subvolume snapshot Create a snapshot of a btrfs subvolume. The snapshot is created using the ioctl's third argument that is a pointer to a 'struct btrfs_ioctl_vol_args' (which was mentioned in the previous patch). Before calling this ioctl, the fields of the structure should be filled with aproppriate values for the file descriptor and path of the subvolume for which the snapshot is to be created. BTRFS_IOC_SNAP_DESTROY - Removing a subvolume snapshot Delete a snapshot of a btrfs subvolume. The snapshot is deleted using the ioctl's third argument that is a pointer to a 'struct btrfs_ioctl_vol_args' (which was mentioned in the previous patch). Before calling this ioctl, the fields of the structure should be filled with aproppriate values for the file descriptor and path of the subvolume for which the snapshot is to be deleted. Implementation notes: Since the thunk type 'struct btrfs_ioctl_vol_args' is defined in the previous patch, the implementation for these ioctls was straightforward. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/ioctls.h | 8 linux-user/syscall_defs.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 544184ff95..2422675dd0 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -174,10 +174,18 @@ IOCTL(FS_IOC32_GETVERSION, IOC_R, MK_PTR(TYPE_INT)) IOCTL(FS_IOC32_SETVERSION, IOC_W, MK_PTR(TYPE_INT)) +#ifdef BTRFS_IOC_SNAP_CREATE + IOCTL(BTRFS_IOC_SNAP_CREATE, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) +#endif #ifdef BTRFS_IOC_SUBVOL_CREATE IOCTL(BTRFS_IOC_SUBVOL_CREATE, IOC_W, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) #endif +#ifdef BTRFS_IOC_SNAP_DESTROY + IOCTL(BTRFS_IOC_SNAP_DESTROY, IOC_W, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) +#endif #ifdef BTRFS_IOC_SUBVOL_GETFLAGS IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG)) #endif diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 67a3c110b6..16966c323f 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -968,7 +968,9 @@ struct target_rtc_pll_info { #define TARGET_FS_IOC32_SETVERSION TARGET_IOW('v', 2, int) /* btrfs ioctls */ +#define TARGET_BTRFS_IOC_SNAP_CREATETARGET_IOWU(BTRFS_IOCTL_MAGIC, 1) #define TARGET_BTRFS_IOC_SUBVOL_CREATE TARGET_IOWU(BTRFS_IOCTL_MAGIC, 14) +#define TARGET_BTRFS_IOC_SNAP_DESTROY TARGET_IOWU(BTRFS_IOCTL_MAGIC, 15) #define TARGET_BTRFS_IOC_SUBVOL_GETFLAGSTARGET_IOR(BTRFS_IOCTL_MAGIC, 25,\ abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_SETFLAGSTARGET_IOW(BTRFS_IOCTL_MAGIC, 26,\ -- 2.25.1
[PATCH 2/3] linux-user: Fix 'recvmmsg()' implementation
Syscall 'recvmmsg()' takes an argument which is of type 'struct timespec' that represents a timeout for the receive operation. Before changes from this patch, the timeout argument was ignored. This was probably due to the way 'recvmmsg()' was implemented with looping over 'recvmsg()' which doesn't have the timeout argument. This was changed with the previous patch in this series and which is why the timeout argument should be added accordingly. Implementation notes: Function 'do_sendrecvmmsg()' was changed with the addition of a new argument which represents the timeout. This argument is only passed in case of 'TARGET_NR_recvmmsg' and for 'TARGENT_NR_sendmmsg' 0 is passed. Function 'do_sendrecvmmsg()' was also updated accordingly in 'do_socketcall()' for 'TARGET_SYS_recvmmsg' and 'TARGET_SYS_sendmmsg'. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 22 +++--- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 8cbefdb561..420d7e7334 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3217,10 +3217,11 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec_addr, unsigned int vlen, unsigned int flags, -int send) +abi_long timeout, int send) { struct mmsghdr *host_msgvec; struct target_mmsghdr *target_msgvec; +struct timespec ts; abi_long ret = 0; int num_sentrecv = 0; int num_iovec = 0; @@ -3275,7 +3276,14 @@ static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec_addr, if (send) { ret = get_errno(safe_sendmmsg(fd, host_msgvec, i, flags)); } else { -ret = get_errno(safe_recvmmsg(fd, host_msgvec, i, flags, NULL)); +if (timeout) { +if (target_to_host_timespec(, timeout)) { +return -TARGET_EFAULT; +} +ret = get_errno(safe_recvmmsg(fd, host_msgvec, i, flags, )); +} else { +ret = get_errno(safe_recvmmsg(fd, host_msgvec, i, flags, NULL)); +} } } @@ -3611,10 +3619,10 @@ static abi_long do_socketcall(int num, abi_ulong vptr) return do_sendrecvmsg(a[0], a[1], a[2], 0); case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */ return do_accept4(a[0], a[1], a[2], a[3]); -case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */ -return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0); +case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, timeout, flags */ +return do_sendrecvmmsg(a[0], a[1], a[2], a[3], a[4], 0); case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */ -return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1); +return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0, 1); default: qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num); return -TARGET_EINVAL; @@ -9418,11 +9426,11 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_sendmmsg case TARGET_NR_sendmmsg: -return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1); +return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0, 1); #endif #ifdef TARGET_NR_recvmmsg case TARGET_NR_recvmmsg: -return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0); +return do_sendrecvmmsg(arg1, arg2, arg3, arg4, arg5, 0); #endif #ifdef TARGET_NR_sendto case TARGET_NR_sendto: -- 2.25.1
[PATCH 1/3] linux-user: Modify 'sendmmsg()' and 'recvmmsg()' implementation
Implementations of 'sendmmsg()' and 'recvmmsg()' in 'syscall.c' use a loop over a host command of 'sendmsg()' and 'recvmsg()' respectively to send/receive individual messages from a socket. This patch changes these implementations to use the host commands 'sendmmsg()' and 'recvmmsg()' to send all messages without looping over 'sendmsg()' and 'recvmsg()'. Implementation notes: Parts of code from 'do_sendrecvmsg_locked()', that are used to transfer values of 'struct msghdr' between host and target, were moved to separate functions 'target_to_host_msghdr()' and 'host_to_target_msghdr()'. These functions are used in 'do_sendrecvmmsg()' to transfer the data of each individual 'struct msghdr' from the 'msgvec' argument. Memory allocation for the 'iovec' field is done outside of these functions as to ensure that the memory is freed after the syscall execution. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 243 --- 1 file changed, 159 insertions(+), 84 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 05f03919ff..8cbefdb561 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -798,6 +798,10 @@ safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len, int, flags, struct sockaddr *, addr, socklen_t *, addrlen) safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags) safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags) +safe_syscall4(int, sendmmsg, int, fd, struct mmsghdr *, msgvec, + unsigned int, vlen, int, flags) +safe_syscall5(int, recvmmsg, int, fd, struct mmsghdr *, msgvec, + unsigned int, vlen, int, flags, struct timespec *, timeout) safe_syscall2(int, flock, int, fd, int, operation) #ifdef TARGET_NR_rt_sigtimedwait safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo, @@ -3064,41 +3068,94 @@ static abi_long do_connect(int sockfd, abi_ulong target_addr, return get_errno(safe_connect(sockfd, addr, addrlen)); } -/* do_sendrecvmsg_locked() Must return target values and target errnos. */ -static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, - int flags, int send) +static abi_long target_to_host_msghdr(int fd, struct msghdr *host_msg, + struct target_msghdr *target_msg, + int send) { -abi_long ret, len; -struct msghdr msg; -abi_ulong count; -struct iovec *vec; -abi_ulong target_vec; - -if (msgp->msg_name) { -msg.msg_namelen = tswap32(msgp->msg_namelen); -msg.msg_name = alloca(msg.msg_namelen+1); -ret = target_to_host_sockaddr(fd, msg.msg_name, - tswapal(msgp->msg_name), - msg.msg_namelen); +abi_long ret = 0; +if (target_msg->msg_name) { +host_msg->msg_namelen = tswap32(target_msg->msg_namelen); +host_msg->msg_name = alloca(host_msg->msg_namelen + 1); +ret = target_to_host_sockaddr(fd, host_msg->msg_name, + tswapal(target_msg->msg_name), + host_msg->msg_namelen); if (ret == -TARGET_EFAULT) { -/* For connected sockets msg_name and msg_namelen must +/* + * For connected sockets msg_name and msg_namelen must * be ignored, so returning EFAULT immediately is wrong. * Instead, pass a bad msg_name to the host kernel, and * let it decide whether to return EFAULT or not. */ -msg.msg_name = (void *)-1; +host_msg->msg_name = (void *)-1; +ret = 0; } else if (ret) { -goto out2; +return ret; } } else { -msg.msg_name = NULL; -msg.msg_namelen = 0; +host_msg->msg_name = NULL; +host_msg->msg_namelen = 0; +} +host_msg->msg_controllen = 2 * tswapal(target_msg->msg_controllen); +host_msg->msg_control = alloca(host_msg->msg_controllen); +memset(host_msg->msg_control, 0, host_msg->msg_controllen); +host_msg->msg_flags = tswap32(target_msg->msg_flags); +if (send) { +if (fd_trans_target_to_host_data(fd)) { +void *host_iov_base; + +host_iov_base = g_malloc(host_msg->msg_iov->iov_len); +memcpy(host_iov_base, host_msg->msg_iov->iov_base, + host_msg->msg_iov->iov_len); +ret = fd_trans_target_to_host_data(fd)(host_iov_base, + host_msg->msg_iov->iov_len); +if (ret >= 0) { +host_msg->msg_iov->iov_base = host_iov_base; +ret = 0; +
[PATCH 3/3] linux-user: Add support for 'recvmmsg_time64()'
This patch introduces functionality for syscall: *recvmmsg_time64 This syscall is a 2038 safe variant for syscall: int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout) --receive multiple messages on a socket-- man page: https://man7.org/linux/man-pages/man2/recvmmsg.2.html Implementation notes: Function 'do_sendrecvmmsg()' in 'syscall.c' was changed with the addition of a new argument 'time64' which represents a flag by which the function knows what kind of 'struct timespec' converting function to call ('target_to_host_timespec() or 'target_to_host_timespec64()'). It is 0 in case of 'TARGET_NR_recvmmsg' and 1 in case of 'TARGET_NR_recvmmsg_time64'. In 'do_socketcall()', the 'TARGET_ABI_BITS' was checked to know what value for 'time64' argument to pass (0 if 'TARGET_ABI_BITS == 32' and 1 otherwise). Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 25 ++--- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 420d7e7334..ed9c2cb7ab 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3217,7 +3217,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec_addr, unsigned int vlen, unsigned int flags, -abi_long timeout, int send) +abi_long timeout, int time64, int send) { struct mmsghdr *host_msgvec; struct target_mmsghdr *target_msgvec; @@ -3277,7 +3277,10 @@ static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec_addr, ret = get_errno(safe_sendmmsg(fd, host_msgvec, i, flags)); } else { if (timeout) { -if (target_to_host_timespec(, timeout)) { +if (!time64 && target_to_host_timespec(, timeout)) { +return -TARGET_EFAULT; +} +if (time64 && target_to_host_timespec64(, timeout)) { return -TARGET_EFAULT; } ret = get_errno(safe_recvmmsg(fd, host_msgvec, i, flags, )); @@ -3619,10 +3622,14 @@ static abi_long do_socketcall(int num, abi_ulong vptr) return do_sendrecvmsg(a[0], a[1], a[2], 0); case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */ return do_accept4(a[0], a[1], a[2], a[3]); -case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, timeout, flags */ -return do_sendrecvmmsg(a[0], a[1], a[2], a[3], a[4], 0); +case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags, timeout, */ +#if TARGET_ABI_BITS == 32 +return do_sendrecvmmsg(a[0], a[1], a[2], a[3], a[4], 0, 0); +#else +return do_sendrecvmmsg(a[0], a[1], a[2], a[3], a[4], 1, 0); +#endif case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */ -return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0, 1); +return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0, 0, 1); default: qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num); return -TARGET_EINVAL; @@ -9426,11 +9433,15 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_sendmmsg case TARGET_NR_sendmmsg: -return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0, 1); +return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0, 0, 1); #endif #ifdef TARGET_NR_recvmmsg case TARGET_NR_recvmmsg: -return do_sendrecvmmsg(arg1, arg2, arg3, arg4, arg5, 0); +return do_sendrecvmmsg(arg1, arg2, arg3, arg4, arg5, 0, 0); +#endif +#ifdef TARGET_NR_recvmmsg_time64 +case TARGET_NR_recvmmsg_time64: +return do_sendrecvmmsg(arg1, arg2, arg3, arg4, arg5, 1, 0); #endif #ifdef TARGET_NR_sendto case TARGET_NR_sendto: -- 2.25.1
[PATCH 0/3] linux-user: Introducing support for 'recvmmsg_time64()'
This patch introduces functionality for 'recvmmsg_time64()' which is a year 2038 safe variant of 'recvmmsg()'. This new time64 syscall is introduced in series of three patches rather than in one patch because a little modification was needed before the syscall could be introduced properly. The first patch in the series introduces a little modification for already existing implementations for 'recvmmsg()' and 'sendmmsg()' to use the host syscall result instead of using a loop over 'recvmsg()' and 'sendmsg()'. The second patch in the series introduces a little fix in the implementation of 'recvmmsg()' that introduces the timeout argument which is of type 'struct timespec' for which the separate time64 variant is added. The third patch in the series introduces the implementation of 'recvmmsg_time64()' itself. Testing method: The implementation was tested using a modified LTP test suite where a timeout test case was added for 'recvmmsg()'. This modified test suite can be found at: https://github.com/bozutaf/ltp (A patch with this fix will be sent to LTP mailing list soon) Filip Bozuta (3): linux-user: Modify 'sendmmsg()' and 'recvmmsg()' implementation linux-user: Fix 'recvmmsg()' implementation linux-user: Add support for 'recvmmsg_time64()' linux-user/syscall.c | 274 +-- 1 file changed, 184 insertions(+), 90 deletions(-) -- 2.25.1
Re: [PATCH 1/1] linux-user: Add support for SG_IO and SG_GET_VERSION_NUM raw SCSI ioctls
On 30.7.20. 04:55, Leif N Huhn wrote: This patch implements functionalities of following ioctls: SG_GET_VERSION_NUM - Returns SG driver version number The sg version numbers are of the form "x.y.z" and the single number given by the SG_GET_VERSION_NUM ioctl() is calculated by (x * 1 + y * 100 + z). SG_IO - Permits user applications to send SCSI commands to a device It is logically equivalent to a write followed by a read. Implementation notes: For SG_GET_VERSION_NUM the value is an int and the implementation is straightforward. For SG_IO, the generic thunk mechanism is used, and works correctly when the host and guest architecture have the same pointer size. A special ioctl handler may be needed in other situations and is not covered in this implementation. Signed-off-by: Leif N Huhn --- linux-user/ioctls.h| 2 ++ linux-user/syscall.c | 1 + linux-user/syscall_defs.h | 33 + linux-user/syscall_types.h | 5 + 4 files changed, 41 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 0713ae1311..92e2f65e05 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -333,6 +333,8 @@ IOCTL(CDROM_DRIVE_STATUS, 0, TYPE_NULL) IOCTL(CDROM_DISC_STATUS, 0, TYPE_NULL) IOCTL(CDROMAUDIOBUFSIZ, 0, TYPE_INT) I think there should be a space between ioctls of different groups (in this case CDROM and SG). + IOCTL(SG_GET_VERSION_NUM, 0, TYPE_INT) SG_GET_VERSION_NUM reads the SG driver version number which means it is of type IOC_R. The 0 is used only for ioctl types that don't have the third argument. Also, the third argument is a pointer to a 'TYPE_INT' since it is used for reading. I tried your patch with sg_simple1 and I get the different version number with native and cross execution so I think this needs to be corrected. The IOCTL(...) definition should be: Â Â Â IOCTL(SG_GET_VERSION_NUM, IOC_R, MK_PTR(TYPE_INT)) After this, the 'SG_GET_VERSION_NUM' works fine. + IOCTL(SG_IO, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sg_io_hdr))) #if 0 IOCTL(SNDCTL_COPR_HALT, IOC_RW, MK_PTR(TYPE_INT)) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 945fc25279..d846ef1af2 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -115,6 +115,7 @@ #ifdef HAVE_DRM_H #include #endif +#include #include "linux_loop.h" #include "uname.h" diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 3c261cff0e..0e3004eb31 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2774,4 +2774,37 @@ struct target_statx { /* 0x100 */ }; +/* from kernel's include/scsi/sg.h */ + +#define TARGET_SG_GET_VERSION_NUM 0x2282 /* Example: version 2.1.34 yields 20134 */ +/* synchronous SCSI command ioctl, (only in version 3 interface) */ +#define TARGET_SG_IO 0x2285 /* similar effect as write() followed by read() */ + +struct target_sg_io_hdr +{ +int interface_id; /* [i] 'S' for SCSI generic (required) */ +int dxfer_direction;/* [i] data transfer direction */ +unsigned char cmd_len; /* [i] SCSI command length */ +unsigned char mx_sb_len;/* [i] max length to write to sbp */ +unsigned short iovec_count; /* [i] 0 implies no scatter gather */ +unsigned int dxfer_len; /* [i] byte count of data transfer */ +abi_ulongdxferp; /* [i], [*io] points to data transfer memory + or scatter gather list */ +abi_ulongcmdp; /* [i], [*i] points to command to perform */ +abi_ulongsbp; /* [i], [*o] points to sense_buffer memory */ +unsigned int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ +unsigned int flags; /* [i] 0 -> default, see SG_FLAG... */ +int pack_id;/* [i->o] unused internally (normally) */ +abi_ulong usr_ptr; /* [i->o] unused internally */ +unsigned char status; /* [o] scsi status */ +unsigned char masked_status;/* [o] shifted, masked scsi status */ +unsigned char msg_status; /* [o] messaging level data (optional) */ +unsigned char sb_len_wr;/* [o] byte count actually written to sbp */ +unsigned short host_status; /* [o] errors from host adapter */ +unsigned short driver_status;/* [o] errors from software driver */ +int resid; /* [o] dxfer_len - actual_transferred */ +unsigned int duration; /* [o] time taken by cmd (unit: millisec) */ +unsigned int info; /* [o] auxiliary information */ +}; /* 64 bytes long (on i386) */ + This target structure is defined, but is not used anywhere. It should be used in a special ioctl handling function for SG_IO to convert the values of 'sg_io_hdr' between host and target. #endif diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index
Re: [PATCH 0/1] linux-user: Add support for SG_IO and SG_GET_VERSION_NUM raw SCSI ioctls
Hello Leif, On 30.7.20. 04:55, Leif N Huhn wrote: Hi. This is my first time trying to contribute to qemu. This patch works correctly for architectures with the same bit-width, for example 32bit arm host and i386 user binary. Here is an example with the sg_simple2 executable from https://github.com/hreinecke/sg3_utils 32-bit ARM native: strace -e trace=ioctl ./sg_simple2 /dev/sg0 ioctl(3, SG_GET_VERSION_NUM, [30536]) = 0 ioctl(3, SG_IO, {interface_id='S', dxfer_direction=SG_DXFER_FROM_DEV, cmd_len=6, cmdp="\x12\x00\x00\x00\x60\x00", mx_sb_len=32, iovec_count=0, dxfer_len=96, timeout=2, flags=0, dxferp="\x05\x80\x00\x32\x5b\x00\x00\x00\x48\x4c\x2d\x44\x54\x2d\x53\x54\x42\x44\x2d\x52\x45\x20\x20\x57\x48\x31\x36\x4e\x53\x34\x30\x20"..., status=0, masked_status=0, msg_status=0, sb_len_wr=0, sbp="", host_status=0, driver_status=0, resid=0, duration=3, info=0}) = 0 Some of the INQUIRY command's results: HL-DT-ST BD-RE WH16NS40 1.05 [wide=0 sync=0 cmdque=0 sftre=0] ioctl(3, SG_IO, {interface_id='S', dxfer_direction=SG_DXFER_NONE, cmd_len=6, cmdp="\x00\x00\x00\x00\x00\x00", mx_sb_len=32, iovec_count=0, dxfer_len=0, timeout=2, flags=0, status=0, masked_status=0, msg_status=0, sb_len_wr=0, sbp="", host_status=0, driver_status=0, resid=0, duration=4, info=0}) = 0 Test Unit Ready successful so unit is ready! +++ exited with 0 +++ i386 binary on 32-bit arm host: strace -f -e trace=ioctl qemu/build/i386-linux-user/qemu-i386 sg3_utils/examples/sg_simple2 /dev/sg0 strace: Process 690 attached [pid 689] ioctl(3, SG_GET_VERSION_NUM, [30536]) = 0 [pid 689] ioctl(3, SG_IO, {interface_id='S', dxfer_direction=SG_DXFER_FROM_DEV, cmd_len=6, cmdp="\x12\x00\x00\x00\x60\x00", mx_sb_len=32, iovec_count=0, dxfer_len=96, timeout=2, flags=0, dxferp="\x05\x80\x00\x32\x5b\x00\x00\x00\x48\x4c\x2d\x44\x54\x2d\x53\x54\x42\x44\x2d\x52\x45\x20\x20\x57\x48\x31\x36\x4e\x53\x34\x30\x20"..., status=0, masked_status=0, msg_status=0, sb_len_wr=0, sbp="", host_status=0, driver_status=0, resid=0, duration=3, info=0}) = 0 Some of the INQUIRY command's results: HL-DT-ST BD-RE WH16NS40 1.05 [wide=0 sync=0 cmdque=0 sftre=0] [pid 689] ioctl(3, SG_IO, {interface_id='S', dxfer_direction=SG_DXFER_NONE, cmd_len=6, cmdp="\x00\x00\x00\x00\x00\x00", mx_sb_len=32, iovec_count=0, dxfer_len=0, timeout=2, flags=0, status=0, masked_status=0, msg_status=0, sb_len_wr=0, sbp="", host_status=0, driver_status=0, resid=0, duration=3, info=0}) = 0 Test Unit Ready successful so unit is ready! [pid 690] +++ exited with 0 +++ +++ exited with 0 +++ However when I try i386 guest on x86_64 host, the cmdp bytes in the first SG_IO call are zero, incorrectly. I assume that is because I need to write a special ioctl handler. Is that correct? Should I be calling lock_user(VERIFY_WRITE...) to copy the buffers over? Yes I think you need a special ioctl handler for SG_IO. I also tried your patch by printing the cmdp as pointer in hex format and noticed that it doesn't change after each cross execution through QEMU as it should (which is the case for native execution) so there is definitely a problem there. Check out IOCTL_SPECIAL() in file 'ioctls.h'. It enables defining a special ioctl handling function which is called specifically for that ioctl in cross execution. Also, is the current patch acceptable as is, or does it need to be reworked until the ioctl works with different architecture bit-widths? No, patches are usually not accepted until they work for all targets. There is also a little issue with SG_GET_VERSION_NUM. I will write you a review in your patch so you can see. By the way, I like the form of your patch description. Best regards, Filip Thanks! Leif N Huhn (1): linux-user: Add support for SG_IO and SG_GET_VERSION_NUM raw SCSI ioctls linux-user/ioctls.h| 2 ++ linux-user/syscall.c | 1 + linux-user/syscall_defs.h | 33 + linux-user/syscall_types.h | 5 + 4 files changed, 41 insertions(+)
[PATCH] linux-user: Fix 'clock_nanosleep()' implementation
Implementation of syscall 'clock_nanosleep()' in 'syscall.c' uses functions 'target_to_host_timespec()' and 'host_to_target_timespec()' to transfer the value of 'struct timespec' between target and host. However, the implementation doesn't check whether this conversion succeeds and thus can return an unaproppriate error instead of 'EFAULT' that is expected. This was confirmed with the modified LTP test suite where testcases with bad 'struct timespec' adress for 'clock_nanosleep()' were added. This modified LTP suite can be found at: https://github.com/bozutaf/ltp (Patch with this new test case will be sent to LTP mailing list soon) Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f5c4f6b95d..9f06dde947 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -11828,7 +11828,9 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, case TARGET_NR_clock_nanosleep: { struct timespec ts; -target_to_host_timespec(, arg3); +if (target_to_host_timespec(, arg3)) { +return -TARGET_EFAULT; +} ret = get_errno(safe_clock_nanosleep(arg1, arg2, , arg4 ? : NULL)); /* @@ -11836,8 +11838,9 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, * with error -TARGET_EINTR and if arg4 is not NULL and arg2 is not * TIMER_ABSTIME, it returns the remaining unslept time in arg4. */ -if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME) { -host_to_target_timespec(arg4, ); +if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME && +host_to_target_timespec(arg4, )) { + return -TARGET_EFAULT; } return ret; -- 2.25.1
[PATCH v2 2/2] linux-user: Add support for 'rt_sigtimedwait_time64()' and 'sched_rr_get_interval_time64()'
This patch implements functionality for following time64 syscalls: *rt_sigtimedwait_time64() This is a year 2038 safe variant of syscall: int rt_sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout, size_t sigsetsize) --synchronously wait for queued signals-- man page: https://man7.org/linux/man-pages/man2/rt_sigtimedwait.2.html *sched_rr_get_interval_time64() This is a year 2038 safe variant of syscall: int sched_rr_get_interval(pid_t pid, struct timespec *tp) --get the SCHED_RR interval for the named process-- man page: https://man7.org/linux/man-pages/man2/sched_rr_get_interval.2.html Implementation notes: These syscalls were implemented in similar ways like 'rt_sigtimedwait()' and 'sched_rr_get_interval()' except that functions 'target_to_host_timespec64()' and 'host_to_target_timespec64()' were used to convert values of 'struct timespec' between host and target. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 53 1 file changed, 53 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index c1b36ea698..35f6dded81 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8831,6 +8831,48 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } } return ret; +#endif +#ifdef TARGET_NR_rt_sigtimedwait_time64 +case TARGET_NR_rt_sigtimedwait_time64: +{ +sigset_t set; +struct timespec uts, *puts; +siginfo_t uinfo; + +if (arg4 != sizeof(target_sigset_t)) { +return -TARGET_EINVAL; +} + +p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1); +if (!p) { +return -TARGET_EFAULT; +} +target_to_host_sigset(, p); +unlock_user(p, arg1, 0); +if (arg3) { +puts = +if (target_to_host_timespec64(puts, arg3)) { +return -TARGET_EFAULT; +} +} else { +puts = NULL; +} +ret = get_errno(safe_rt_sigtimedwait(, , puts, + SIGSET_T_SIZE)); +if (!is_error(ret)) { +if (arg2) { +p = lock_user(VERIFY_WRITE, arg2, + sizeof(target_siginfo_t), 0); +if (!p) { +return -TARGET_EFAULT; +} +host_to_target_siginfo(p, ); +unlock_user(p, arg2, sizeof(target_siginfo_t)); +} +ret = host_to_target_signal(ret); +} +} +return ret; #endif case TARGET_NR_rt_sigqueueinfo: { @@ -10353,6 +10395,17 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_sched_rr_get_interval_time64 +case TARGET_NR_sched_rr_get_interval_time64: +{ +struct timespec ts; +ret = get_errno(sched_rr_get_interval(arg1, )); +if (!is_error(ret)) { +ret = host_to_target_timespec64(arg2, ); +} +} +return ret; +#endif #if defined(TARGET_NR_nanosleep) case TARGET_NR_nanosleep: { -- 2.25.1
[PATCH v2 0/2] Introducing functionality for a group of 4 time64 syscalls
This two patch series introduces functionality for a group of 4 2038 safe syscalls. The list of implemented syscalls and implementation details can be found in the patch commit messages. Testing method: The implementation of the implemented syscalls was tested using already existing tests from LTP test suite which was built inside chroot. *v2: -Added check for 'clock_nanosleep_time64()' which returns '-TARGET_EFAULT' if conversion of 'struct timespec64' between host and target fails -Removed unnecesary special errno handling for 'PPC' Filip Bozuta (2): linux-user: Add support for two 'clock_nanosleep_time64()' and 'clock_adjtime64()' linux-user: Add support for 'rt_sigtimedwait_time64()' and 'sched_rr_get_interval_time64()' linux-user/syscall.c | 192 +- linux-user/syscall_defs.h | 31 ++ 2 files changed, 221 insertions(+), 2 deletions(-) -- 2.25.1
[PATCH v2 1/2] linux-user: Add support for two 'clock_nanosleep_time64()' and 'clock_adjtime64()'
This patch implements functionality for following time64 syscall: *clock_nanosleep_time64() This is a year 2038 safe vairant of syscall: int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *request, struct timespec *remain) --high-resolution sleep with specifiable clock-- man page: https://man7.org/linux/man-pages/man2/clock_nanosleep.2.html *clock_adjtime64() This is a year 2038 safe variant of syscall: int clock_adjtime(clockid_t clk_id, struct timex *buf) --tune kernel clock-- man page: https://man7.org/linux/man-pages/man2/clock_adjtime.2.html Implementation notes: Syscall 'clock_nanosleep_time64()' was implemented similarly to syscall 'clock_nanosleep()' except that 'host_to_target_timespec64()' and 'target_to_host_timespec64()' were used instead of the regular 'host_to_target_timespec()' and 'target_to_host_timespec()'. For 'clock_adjtime64()' a 64-bit target kernel version of 'struct timex' was defined in 'syscall_defs.h': 'struct target__kernel_timex'. This type was used to convert the values of 64-bit timex type between host and target. For this purpose a 64-bit timex converting functions 'target_to_host_timex64()' and 'host_to_target_timex64()'. An existing function 'copy_to_user_timeval64()' was used to convert the field 'time' which if of type 'struct timeval' from host to target. Function 'copy_from_user_timveal64()' was added in this patch and used to convert the 'time' field from target to host. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 139 +- linux-user/syscall_defs.h | 31 + 2 files changed, 168 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 05f03919ff..c1b36ea698 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -809,7 +809,8 @@ safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len, safe_syscall2(int, nanosleep, const struct timespec *, req, struct timespec *, rem) #endif -#ifdef TARGET_NR_clock_nanosleep +#if defined(TARGET_NR_clock_nanosleep) || \ +defined(TARGET_NR_clock_nanosleep_time64) safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags, const struct timespec *, req, struct timespec *, rem) #endif @@ -1205,8 +1206,25 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr, return 0; } +static inline abi_long copy_from_user_timeval64(struct timeval *tv, +abi_ulong target_tv_addr) +{ +struct target__kernel_sock_timeval *target_tv; + +if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) { +return -TARGET_EFAULT; +} + +__get_user(tv->tv_sec, _tv->tv_sec); +__get_user(tv->tv_usec, _tv->tv_usec); + +unlock_user_struct(target_tv, target_tv_addr, 0); + +return 0; +} + static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr, - const struct timeval *tv) + const struct timeval *tv) { struct target__kernel_sock_timeval *target_tv; @@ -6771,6 +6789,87 @@ static inline abi_long host_to_target_timex(abi_long target_addr, } #endif + +#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME) +static inline abi_long target_to_host_timex64(struct timex *host_tx, + abi_long target_addr) +{ +struct target__kernel_timex *target_tx; + +if (copy_from_user_timeval64(_tx->time, target_addr + + offsetof(struct target__kernel_timex, + time))) { +return -TARGET_EFAULT; +} + +if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) { +return -TARGET_EFAULT; +} + +__get_user(host_tx->modes, _tx->modes); +__get_user(host_tx->offset, _tx->offset); +__get_user(host_tx->freq, _tx->freq); +__get_user(host_tx->maxerror, _tx->maxerror); +__get_user(host_tx->esterror, _tx->esterror); +__get_user(host_tx->status, _tx->status); +__get_user(host_tx->constant, _tx->constant); +__get_user(host_tx->precision, _tx->precision); +__get_user(host_tx->tolerance, _tx->tolerance); +__get_user(host_tx->tick, _tx->tick); +__get_user(host_tx->ppsfreq, _tx->ppsfreq); +__get_user(host_tx->jitter, _tx->jitter); +__get_user(host_tx->shift, _tx->shift); +__get_user(host_tx->stabil, _tx->stabil); +__get_user(host_tx->jitcnt, _tx->jitcnt); +__get_user(host_tx->calcnt, _tx->calcnt); +__get_user(host_tx->errcnt, _tx->errcnt); +__get_user(host_tx->stbcnt, _tx->stbcnt); +__
[PATCH v2 1/2] linux-user: Fix 'mq_timedsend()' and 'mq_timedreceive()'
Implementations of syscalls 'mq_timedsend()' and 'mq_timedreceive()' in 'syscall.c' use functions 'target_to_host_timespec()' and 'host_to_target_timespec()' to transfer the value of 'struct timespec' between target and host. However, the implementations don't check whether this conversion succeeds and thus can cause an unaproppriate error instead of the 'EFAULT (Bad address)' which is supposed to be set if the conversion from target to host fails. This was confirmed with the modified LTP test suite where test cases with a bad adress for 'timespec' were added. This modified test suite can be found at: https://github.com/bozutaf/ltp Without the changes from this patch the bad adress testcase for 'mq_timedsend()' succeds unexpectedly, while the test returns errno 'ETIMEOUT' for 'mq_timedreceive()': mq_timedsend01.c:190: FAIL: mq_timedsend() returned 0, expected -1: SUCCESS (0) mq_timedreceive01.c:178: FAIL: mq_timedreceive() failed unexpectedly, expected EFAULT: ETIMEDOUT (110) After the changes from this patch, testcases for both syscalls fail with EFAULT as expected, which is the same test result that is received with native execution: mq_timedsend01.c:187: PASS: mq_timedsend() failed expectedly: EFAULT (14) mq_timedreceive01.c:180: PASS: mq_timedreceive() failed expectedly: EFAULT (14) (Patch with this new test case will be sent to LTP mailing list soon) Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 16 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 05f03919ff..1f8d04934a 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -11817,9 +11817,13 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, p = lock_user (VERIFY_READ, arg2, arg3, 1); if (arg5 != 0) { -target_to_host_timespec(, arg5); +if (target_to_host_timespec(, arg5)) { +return -TARGET_EFAULT; +} ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, )); -host_to_target_timespec(arg5, ); +if (host_to_target_timespec(arg5, )) { +return -TARGET_EFAULT; +} } else { ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL)); } @@ -11836,10 +11840,14 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, p = lock_user (VERIFY_READ, arg2, arg3, 1); if (arg5 != 0) { -target_to_host_timespec(, arg5); +if (target_to_host_timespec(, arg5)) { +return -TARGET_EFAULT; +} ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, , )); -host_to_target_timespec(arg5, ); +if (host_to_target_timespec(arg5, )) { +return -TARGET_EFAULT; +} } else { ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, , NULL)); -- 2.25.1
[PATCH v2 2/2] linux-user: Add support for 'mq_timedsend_time64()' and 'mq_timedreceive_time64()'
This patch implements functionality for following time64 syscalls: *mq_timedsend_time64() This is a year 2038 safe vairant of syscall: int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout) --send a message to a message queue-- man page: https://www.man7.org/linux/man-pages/man2/mq_timedsend.2.html *mq_timedreceive_time64() This is a year 2038 safe variant of syscall: ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct timespec *abs_timeout) --receive a message from a message queue-- man page: https://man7.org/linux/man-pages/man3/mq_receive.3.html Implementation notes: These syscalls were implemented in similar ways like 'mq_timedsend()' and 'mq_timedreceive' except that functions 'target_to_host_timespec64()' and 'host_to_target_timespec64()' were used to convert values of 'struct timespec' between host and target. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 58 +--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1f8d04934a..d8cb3c0fd1 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -829,11 +829,13 @@ safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz, safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, unsigned, nsops, const struct timespec *, timeout) #endif -#ifdef TARGET_NR_mq_timedsend +#if defined(TARGET_NR_mq_timedsend) || \ +defined(TARGET_NR_mq_timedsend_time64) safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr, size_t, len, unsigned, prio, const struct timespec *, timeout) #endif -#ifdef TARGET_NR_mq_timedreceive +#if defined(TARGET_NR_mq_timedreceive) || \ +defined(TARGET_NR_mq_timedreceive_time64) safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr, size_t, len, unsigned *, prio, const struct timespec *, timeout) #endif @@ -1243,7 +1245,9 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts, } #endif -#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) +#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \ +defined(TARGET_NR_mq_timedsend_time64) || \ +defined(TARGET_NR_mq_timedreceive_time64) static inline abi_long target_to_host_timespec64(struct timespec *host_ts, abi_ulong target_addr) { @@ -11831,6 +11835,27 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_mq_timedsend_time64 +case TARGET_NR_mq_timedsend_time64: +{ +struct timespec ts; + +p = lock_user(VERIFY_READ, arg2, arg3, 1); +if (arg5 != 0) { +if (target_to_host_timespec64(, arg5)) { +return -TARGET_EFAULT; +} +ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, )); +if (host_to_target_timespec64(arg5, )) { +return -TARGET_EFAULT; +} +} else { +ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL)); +} +unlock_user(p, arg2, arg3); +} +return ret; +#endif #ifdef TARGET_NR_mq_timedreceive case TARGET_NR_mq_timedreceive: @@ -11858,6 +11883,33 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_mq_timedreceive_time64 +case TARGET_NR_mq_timedreceive_time64: +{ +struct timespec ts; +unsigned int prio; + +p = lock_user(VERIFY_READ, arg2, arg3, 1); +if (arg5 != 0) { +if (target_to_host_timespec64(, arg5)) { +return -TARGET_EFAULT; +} +ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, + , )); +if (host_to_target_timespec64(arg5, )) { +return -TARGET_EFAULT; +} +} else { +ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, + , NULL)); +} +unlock_user(p, arg2, arg3); +if (arg4 != 0) { +put_user_u32(prio, arg4); +} +} +return ret; +#endif /* Not implemented for now... */ /* case TARGET_NR_mq_notify: */ -- 2.25.1
[PATCH v2 0/2] linux-user: Introducing functionality for two time64 syscalls
This two patch series introduces functionality for two year 2038 safe syscalls. The first patch introduces a little correction for already implemented normal (32-bit) variants of implemented syscalls. The second patch introduces the implementation of the syscalls. Testing method: The implementation of the implemented syscalls was tested using recently added time64 test in the LTP test suite. Filip Bozuta (2): linux-user: Fix 'mq_timedsend()' and 'mq_timedreceive()' linux-user: Add support for 'mq_timedsend_time64()' and 'mq_timedreceive_time64()' linux-user/syscall.c | 74 +++- 1 file changed, 67 insertions(+), 7 deletions(-) -- 2.25.1
[PATCH] linux-user: Add support for 'mq_timedsend_time64()' and 'mq_timedreceive_time64()'
This patch implements functionality for following time64 syscalls: *mq_timedsend_time64() This is a year 2038 safe vairant of syscall: int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout) --send a message to a message queue-- man page: https://www.man7.org/linux/man-pages/man2/mq_timedsend.2.html *mq_timedreceive_time64() This is a year 2038 safe variant of syscall: ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct timespec *abs_timeout) --receive a message from a message queue-- man page: https://man7.org/linux/man-pages/man3/mq_receive.3.html Implementation notes: These syscalls were implemented in similar ways like 'mq_timedsend()' and 'mq_timedreceive' except that functions 'target_to_host_timespec64()' and 'host_to_target_timespec64()' were used to convert values of 'struct timespec' between host and target. Testing method: The implementation in this patch was tested using recently added LTP time64 test variants for "mq_timedsend()" and "mq_timedsendreceive()". Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 50 +--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 05f03919ff..894e835065 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -829,11 +829,13 @@ safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz, safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, unsigned, nsops, const struct timespec *, timeout) #endif -#ifdef TARGET_NR_mq_timedsend +#if defined(TARGET_NR_mq_timedsend) || \ +defined(TARGET_NR_mq_timedsend_time64) safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr, size_t, len, unsigned, prio, const struct timespec *, timeout) #endif -#ifdef TARGET_NR_mq_timedreceive +#if defined(TARGET_NR_mq_timedreceive) || \ +defined(TARGET_NR_mq_timedreceive_time64) safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr, size_t, len, unsigned *, prio, const struct timespec *, timeout) #endif @@ -1243,7 +1245,9 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts, } #endif -#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) +#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \ +defined(TARGET_NR_mq_timedsend_time64) || \ +defined(TARGET_NR_mq_timedreceive_time64) static inline abi_long target_to_host_timespec64(struct timespec *host_ts, abi_ulong target_addr) { @@ -11827,6 +11831,23 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_mq_timedsend_time64 +case TARGET_NR_mq_timedsend_time64: +{ +struct timespec ts; + +p = lock_user(VERIFY_READ, arg2, arg3, 1); +if (arg5 != 0) { +target_to_host_timespec64(, arg5); +ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, )); +host_to_target_timespec64(arg5, ); +} else { +ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL)); +} +unlock_user(p, arg2, arg3); +} +return ret; +#endif #ifdef TARGET_NR_mq_timedreceive case TARGET_NR_mq_timedreceive: @@ -11850,6 +11871,29 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_mq_timedreceive_time64 +case TARGET_NR_mq_timedreceive_time64: +{ +struct timespec ts; +unsigned int prio; + +p = lock_user(VERIFY_READ, arg2, arg3, 1); +if (arg5 != 0) { +target_to_host_timespec64(, arg5); +ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, + , )); +host_to_target_timespec64(arg5, ); +} else { +ret = get_errno(safe_mq_timedreceive(arg1, p, arg3, + , NULL)); +} +unlock_user(p, arg2, arg3); +if (arg4 != 0) { +put_user_u32(prio, arg4); +} +} +return ret; +#endif /* Not implemented for now... */ /* case TARGET_NR_mq_notify: */ -- 2.25.1
[PATCH 0/2] linux-user: Introducing functionality for a group of 4 time64 syscalls
This two patch series introduces functionality for a group of 4 2038 safe syscalls. The list of implemented syscalls and implementation details can be found in the patch commit messages. Testing method: The implementation of the implemented syscalls was tested using already existing tests from LTP test suite which was built inside chroot. Filip Bozuta (2): linux-user: Add support for two 'clock_nanosleep_time64()' and 'clock_adjtime64()' linux-user: Add support for 'rt_sigtimedwait_time64()' and 'sched_rr_get_interval_time64()' linux-user/syscall.c | 197 +- linux-user/syscall_defs.h | 31 ++ 2 files changed, 226 insertions(+), 2 deletions(-) -- 2.25.1
[PATCH 1/2] linux-user: Add support for 'clock_nanosleep_time64()' and 'clock_adjtime64()'
This patch implements functionality for following time64 syscall: *clock_nanosleep_time64() This is a year 2038 safe vairant of syscall: int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *request, struct timespec *remain) --high-resolution sleep with specifiable clock-- man page: https://man7.org/linux/man-pages/man2/clock_nanosleep.2.html *clock_adjtime64() This is a year 2038 safe variant of syscall: int clock_adjtime(clockid_t clk_id, struct timex *buf) --tune kernel clock-- man page: https://man7.org/linux/man-pages/man2/clock_adjtime.2.html Implementation notes: Syscall 'clock_nanosleep_time64()' was implemented similarly to syscall 'clock_nanosleep()' except that 'host_to_target_timespec64()' and 'target_to_host_timespec64()' were used instead of the regular 'host_to_target_timespec()' and 'target_to_host_timespec()'. For 'clock_adjtime64()' a 64-bit target kernel version of 'struct timex' was defined in 'syscall_defs.h': 'struct target__kernel_timex'. This type was used to convert the values of 64-bit timex type between host and target. For this purpose a 64-bit timex converting functions 'target_to_host_timex64()' and 'host_to_target_timex64()'. An existing function 'copy_to_user_timeval64()' was used to convert the field 'time' which if of type 'struct timeval' from host to target. Function 'copy_from_user_timveal64()' was added in this patch and used to convert the 'time' field from target to host. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 144 +- linux-user/syscall_defs.h | 31 2 files changed, 173 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 05f03919ff..0de11e4245 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -809,7 +809,8 @@ safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len, safe_syscall2(int, nanosleep, const struct timespec *, req, struct timespec *, rem) #endif -#ifdef TARGET_NR_clock_nanosleep +#if defined(TARGET_NR_clock_nanosleep) || \ +defined(TARGET_NR_clock_nanosleep_time64) safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags, const struct timespec *, req, struct timespec *, rem) #endif @@ -1205,8 +1206,25 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr, return 0; } +static inline abi_long copy_from_user_timeval64(struct timeval *tv, +abi_ulong target_tv_addr) +{ +struct target__kernel_sock_timeval *target_tv; + +if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) { +return -TARGET_EFAULT; +} + +__get_user(tv->tv_sec, _tv->tv_sec); +__get_user(tv->tv_usec, _tv->tv_usec); + +unlock_user_struct(target_tv, target_tv_addr, 0); + +return 0; +} + static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr, - const struct timeval *tv) + const struct timeval *tv) { struct target__kernel_sock_timeval *target_tv; @@ -6771,6 +6789,87 @@ static inline abi_long host_to_target_timex(abi_long target_addr, } #endif + +#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME) +static inline abi_long target_to_host_timex64(struct timex *host_tx, + abi_long target_addr) +{ +struct target__kernel_timex *target_tx; + +if (copy_from_user_timeval64(_tx->time, target_addr + + offsetof(struct target__kernel_timex, + time))) { +return -TARGET_EFAULT; +} + +if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) { +return -TARGET_EFAULT; +} + +__get_user(host_tx->modes, _tx->modes); +__get_user(host_tx->offset, _tx->offset); +__get_user(host_tx->freq, _tx->freq); +__get_user(host_tx->maxerror, _tx->maxerror); +__get_user(host_tx->esterror, _tx->esterror); +__get_user(host_tx->status, _tx->status); +__get_user(host_tx->constant, _tx->constant); +__get_user(host_tx->precision, _tx->precision); +__get_user(host_tx->tolerance, _tx->tolerance); +__get_user(host_tx->tick, _tx->tick); +__get_user(host_tx->ppsfreq, _tx->ppsfreq); +__get_user(host_tx->jitter, _tx->jitter); +__get_user(host_tx->shift, _tx->shift); +__get_user(host_tx->stabil, _tx->stabil); +__get_user(host_tx->jitcnt, _tx->jitcnt); +__get_user(host_tx->calcnt, _tx->calcnt); +__get_user(host_tx->errcnt, _tx->errcnt); +__get_user(host_tx->stbcnt, _tx->stbcnt); +__
[PATCH 2/2] linux-user: Add support for 'rt_sigtimedwait_time64()' and 'sched_rr_get_interval_time64()'
This patch implements functionality for following time64 syscalls: *rt_sigtimedwait_time64() This is a year 2038 safe variant of syscall: int rt_sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout, size_t sigsetsize) --synchronously wait for queued signals-- man page: https://man7.org/linux/man-pages/man2/rt_sigtimedwait.2.html *sched_rr_get_interval_time64() This is a year 2038 safe variant of syscall: int sched_rr_get_interval(pid_t pid, struct timespec *tp) --get the SCHED_RR interval for the named process-- man page: https://man7.org/linux/man-pages/man2/sched_rr_get_interval.2.html Implementation notes: These syscalls were implemented in similar ways like 'rt_sigtimedwait()' and 'sched_rr_get_interval()' except that functions 'target_to_host_timespec64()' and 'host_to_target_timespec64()' were used to convert values of 'struct timespec' between host and target. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 53 1 file changed, 53 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 0de11e4245..efd6157350 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8831,6 +8831,48 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } } return ret; +#endif +#ifdef TARGET_NR_rt_sigtimedwait_time64 +case TARGET_NR_rt_sigtimedwait_time64: +{ +sigset_t set; +struct timespec uts, *puts; +siginfo_t uinfo; + +if (arg4 != sizeof(target_sigset_t)) { +return -TARGET_EINVAL; +} + +p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1); +if (!p) { +return -TARGET_EFAULT; +} +target_to_host_sigset(, p); +unlock_user(p, arg1, 0); +if (arg3) { +puts = +if (target_to_host_timespec64(puts, arg3)) { +return -TARGET_EFAULT; +} +} else { +puts = NULL; +} +ret = get_errno(safe_rt_sigtimedwait(, , puts, + SIGSET_T_SIZE)); +if (!is_error(ret)) { +if (arg2) { +p = lock_user(VERIFY_WRITE, arg2, + sizeof(target_siginfo_t), 0); +if (!p) { +return -TARGET_EFAULT; +} +host_to_target_siginfo(p, ); +unlock_user(p, arg2, sizeof(target_siginfo_t)); +} +ret = host_to_target_signal(ret); +} +} +return ret; #endif case TARGET_NR_rt_sigqueueinfo: { @@ -10353,6 +10395,17 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#ifdef TARGET_NR_sched_rr_get_interval_time64 +case TARGET_NR_sched_rr_get_interval_time64: +{ +struct timespec ts; +ret = get_errno(sched_rr_get_interval(arg1, )); +if (!is_error(ret)) { +ret = host_to_target_timespec64(arg2, ); +} +} +return ret; +#endif #if defined(TARGET_NR_nanosleep) case TARGET_NR_nanosleep: { -- 2.25.1
[PATCH] linux-user: Fix syscall rt_sigtimedwait() implementation
Implementation of 'rt_sigtimedwait()' in 'syscall.c' uses the function 'target_to_host_timespec()' to transfer the value of 'struct timespec' from target to host. However, the implementation doesn't check whether this conversion succeeds and thus can cause an unaproppriate error instead of the 'EFAULT (Bad address)' which is supposed to be set if the conversion from target to host fails. This was confirmed with the LTP test for rt_sigtimedwait: "/testcases/kernel/syscalls/rt_sigtimedwait/rt_sigtimedwait01.c" which causes an unapropriate error in test case "test_bad_adress3" which is run with a bad adress for the 'struct timespec' argument: FAIL: test_bad_address3 (349): Unexpected failure: EAGAIN/EWOULDBLOCK (11) The test fails with an unexptected errno 'EAGAIN/EWOULDBLOCK' instead of the expected EFAULT. After the changes from this patch, the test case is executed successfully along with the other LTP test cases for 'rt_sigtimedwait()': PASS: test_bad_address3 (349): Test passed Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1211e759c2..72735682cb 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8868,7 +8868,9 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, unlock_user(p, arg1, 0); if (arg3) { puts = -target_to_host_timespec(puts, arg3); +if (target_to_host_timespec(puts, arg3)) { +return -TARGET_EFAULT; +} } else { puts = NULL; } -- 2.25.1
[PATCH v2 0/3] Adding support for printing contents of 'struct termios' which is used by ioctls of group 'ioctl_tty'
This series introduces strace printing functionality for contents of 'struct termios'. The first patch in the series introduces a generic 'termbits.h' file for some architectures which have same 'struct termios' flag values and 'ioctl_tty' definitions. The second patch introduces some missing types and flag values for 'struct termios' which are needed to print it's contents. The third patch introduces the 'strace' argument printing functionality itself by using existing functions and macros in 'strace.c'. Testing method: The argument printing functionality was tested using mini test program, which were cross compiled for certain architectures ('ppc','ppc64','mips','mips64','mipsel'), in which the ioctls of group 'ioctl_tty' were used. These programs were cross executed with QEMU with "-strace" to check if the contents 'struct termios' are getting correctly printed. Based-on: <20200722200437.312767-1-filip.boz...@syrmia.com> Filip Bozuta (5): linux-user: Add generic 'termbits.h' for some archs linux-user: Add missing termbits types and values definitions linux-user: Add strace support for printing arguments for ioctls used for terminals and serial lines include/exec/user/thunk.h| 1 + linux-user/aarch64/termbits.h| 228 + linux-user/alpha/termbits.h | 1 + linux-user/arm/termbits.h| 223 + linux-user/cris/termbits.h | 18 +- linux-user/generic/termbits.h| 318 +++ linux-user/hppa/termbits.h | 17 +- linux-user/i386/termbits.h | 233 + linux-user/m68k/termbits.h | 234 + linux-user/microblaze/termbits.h | 220 +--- linux-user/mips/termbits.h | 17 +- linux-user/nios2/termbits.h | 228 + linux-user/openrisc/termbits.h | 302 +- linux-user/ppc/termbits.h| 21 +- linux-user/qemu.h| 1 + linux-user/riscv/termbits.h | 228 + linux-user/s390x/termbits.h | 289 + linux-user/sh4/termbits.h| 19 +- linux-user/sparc/termbits.h | 18 +- linux-user/sparc64/termbits.h| 18 +- linux-user/strace.c | 415 ++- linux-user/strace.list | 17 +- linux-user/syscall.c | 35 +-- linux-user/tilegx/termbits.h | 276 +--- linux-user/x86_64/termbits.h | 254 +-- linux-user/xtensa/termbits.h | 53 ++-- thunk.c | 23 +- 27 files changed, 900 insertions(+), 2807 deletions(-) create mode 100644 linux-user/generic/termbits.h -- 2.25.1
[PATCH v2 3/3] linux-user: Add strace support for printing arguments for ioctls used for terminals and serial lines
Functions "print_ioctl()" and "print_syscall_ret_ioctl()" are used to print arguments of "ioctl()" with "-strace". These functions use "thunk_print()", which is defined in "thunk.c", to print the contents of ioctl's third arguments that are not basic types. However, this function doesn't handle ioctls of group ioctl_tty which are used for terminals and serial lines. These ioctls use a type "struct termios" which thunk type is defined in a non standard way using "STRUCT_SPECIAL()". This means that this type is not decoded regularly using "thunk_convert()" and uses special converting functions "target_to_host_termios()" and "host_to_target_termios()", which are defined in "syscall.c" to decode it's values. For simillar reasons, this type is also not printed regularly using "thunk_print()". That is the reason why a separate printing function "print_termios()" is defined in file "strace.c". This function decodes and prints flag values of the "termios" structure. Implementation notes: Function "print_termios()" was implemented in "strace.c" using an existing function "print_flags()" to print flag values of "struct termios" fields. Also, recently implemented function "print_enums()" was also used to print enumareted values which are contained in the fields of 'struct termios'. These flag values were defined using an existing macro "FLAG_TARGET()" that generates aproppriate target flag values and string representations of these flags. Also, the recently defined macro "ENUM_TARGET()" was used to generate aproppriate enumarated values and their respective string representations. Function "print_termios()" was declared in "qemu.h" so that it can be accessed in "syscall.c". Type "StructEntry" defined in "exec/user/thunk.h" contains information that is used to decode structure values. Field "void print(void *arg)" was added in this structure as a special print function. Also, function "thunk_print()" was changed a little so that it uses this special print function in case it is defined. This printing function was instantiated with the defined "print_termios()" in "syscall.c" in "struct_termios_def". Signed-off-by: Filip Bozuta --- include/exec/user/thunk.h | 1 + linux-user/qemu.h | 1 + linux-user/strace.c | 195 ++ linux-user/syscall.c | 1 + thunk.c | 23 +++-- 5 files changed, 212 insertions(+), 9 deletions(-) diff --git a/include/exec/user/thunk.h b/include/exec/user/thunk.h index 7992475c9f..a5bbb2c733 100644 --- a/include/exec/user/thunk.h +++ b/include/exec/user/thunk.h @@ -55,6 +55,7 @@ typedef struct { int *field_offsets[2]; /* special handling */ void (*convert[2])(void *dst, const void *src); +void (*print)(void *arg); int size[2]; int align[2]; const char *name; diff --git a/linux-user/qemu.h b/linux-user/qemu.h index f431805e57..a69a0bd347 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -706,6 +706,7 @@ static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) } #endif /* TARGET_ABI_BITS != 32 */ +void print_termios(void *arg); /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ #ifdef TARGET_ARM diff --git a/linux-user/strace.c b/linux-user/strace.c index 3f16bb2c53..b9ba39ce6e 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1284,6 +1284,140 @@ UNUSED static struct flags falloc_flags[] = { #endif }; +UNUSED static struct flags termios_iflags[] = { +FLAG_TARGET(IGNBRK), +FLAG_TARGET(BRKINT), +FLAG_TARGET(IGNPAR), +FLAG_TARGET(PARMRK), +FLAG_TARGET(INPCK), +FLAG_TARGET(ISTRIP), +FLAG_TARGET(INLCR), +FLAG_TARGET(IGNCR), +FLAG_TARGET(ICRNL), +FLAG_TARGET(IUCLC), +FLAG_TARGET(IXON), +FLAG_TARGET(IXANY), +FLAG_TARGET(IXOFF), +FLAG_TARGET(IMAXBEL), +FLAG_TARGET(IUTF8), +FLAG_END, +}; + +UNUSED static struct flags termios_oflags[] = { +FLAG_TARGET(OPOST), +FLAG_TARGET(OLCUC), +FLAG_TARGET(ONLCR), +FLAG_TARGET(OCRNL), +FLAG_TARGET(ONOCR), +FLAG_TARGET(ONLRET), +FLAG_TARGET(OFILL), +FLAG_TARGET(OFDEL), +FLAG_END, +}; + +UNUSED static struct enums termios_oflags_NLDLY[] = { +ENUM_TARGET(NL0), +ENUM_TARGET(NL1), +ENUM_END, +}; + +UNUSED static struct enums termios_oflags_CRDLY[] = { +ENUM_TARGET(CR0), +ENUM_TARGET(CR1), +ENUM_TARGET(CR2), +ENUM_TARGET(CR3), +ENUM_END, +}; + +UNUSED static struct enums termios_oflags_TABDLY[] = { +ENUM_TARGET(TAB0), +ENUM_TARGET(TAB1), +ENUM_
[PATCH v2 1/3] linux-user: Add generic 'termbits.h' for some archs
This patch introduces a generic 'termbits.h' file for following archs: 'aarch64', 'arm', 'i386, 'm68k', 'microblaze', 'nios2', 'openrisc', 'riscv', 's390x', 'x86_64'. Since all of these archs have the same termios flag values and same ioctl_tty numbers, there is no need for a separate 'termbits.h' file for each one of them. For that reason one generic 'termbits.h' file was added for all of them and an '#include' directive was added for this generic file in every arch 'termbits.h' file. Also, some of the flag values that were missing were added in this generic file so that it matches the generic 'termibts.h' and 'ioctls.h' files from the kernel: 'asm-generic/termbits.h' and 'asm-generic/ioctls.h'. Signed-off-by: Filip Bozuta --- linux-user/aarch64/termbits.h| 228 +- linux-user/arm/termbits.h| 223 +- linux-user/generic/termbits.h| 318 +++ linux-user/i386/termbits.h | 233 +- linux-user/m68k/termbits.h | 234 +-- linux-user/microblaze/termbits.h | 220 + linux-user/nios2/termbits.h | 228 +- linux-user/openrisc/termbits.h | 302 + linux-user/riscv/termbits.h | 228 +- linux-user/s390x/termbits.h | 289 +--- linux-user/tilegx/termbits.h | 276 +-- linux-user/x86_64/termbits.h | 254 +--- 12 files changed, 329 insertions(+), 2704 deletions(-) create mode 100644 linux-user/generic/termbits.h diff --git a/linux-user/aarch64/termbits.h b/linux-user/aarch64/termbits.h index 0ab448d090..b1d4f4fedb 100644 --- a/linux-user/aarch64/termbits.h +++ b/linux-user/aarch64/termbits.h @@ -1,227 +1 @@ -/* from asm/termbits.h */ -/* NOTE: exactly the same as i386 */ - -#ifndef LINUX_USER_AARCH64_TERMBITS_H -#define LINUX_USER_AARCH64_TERMBITS_H - -#define TARGET_NCCS 19 - -struct target_termios { -unsigned int c_iflag; /* input mode flags */ -unsigned int c_oflag; /* output mode flags */ -unsigned int c_cflag; /* control mode flags */ -unsigned int c_lflag; /* local mode flags */ -unsigned char c_line;/* line discipline */ -unsigned char c_cc[TARGET_NCCS];/* control characters */ -}; - -/* c_iflag bits */ -#define TARGET_IGNBRK 001 -#define TARGET_BRKINT 002 -#define TARGET_IGNPAR 004 -#define TARGET_PARMRK 010 -#define TARGET_INPCK 020 -#define TARGET_ISTRIP 040 -#define TARGET_INLCR 100 -#define TARGET_IGNCR 200 -#define TARGET_ICRNL 400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 001 -#define TARGET_IMAXBEL 002 -#define TARGET_IUTF8 004 - -/* c_oflag bits */ -#define TARGET_OPOST 001 -#define TARGET_OLCUC 002 -#define TARGET_ONLCR 004 -#define TARGET_OCRNL 010 -#define TARGET_ONOCR 020 -#define TARGET_ONLRET 040 -#define TARGET_OFILL 100 -#define TARGET_OFDEL 200 -#define TARGET_NLDLY 400 -#define TARGET_NL0 000 -#define TARGET_NL1 400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 001 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 002 -#define TARGET_BS0 000 -#define TARGET_BS1 002 -#define TARGET_VTDLY 004 -#define TARGET_VT0 000 -#define TARGET_VT1 004 -#define TARGET_FFDLY 010 -#define TARGET_FF0 000 -#define TARGET_FF1 010 - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 000 /* hang up */ -#define TARGET_B50001 -#define TARGET_B75002 -#define TARGET_B110 003 -#define TARGET_B134 004 -#define TARGET_B150 005 -#define TARGET_B200 006 -#define TARGET_B300 007 -#define TARGET_B600 010 -#define TARGET_B1200 011 -#define TARGET_B1800 012 -#define TARGET_B2400 013 -#define TARGET_B4800 014 -#define TARGET_B9600 015 -#define TARGET_B19200 016 -#define TARGET_B38400 017 -#define TARGET_EXTA B19200 -#define TARGET_EXTB B38400 -#define TARGET_CSIZE 060 -#define TARGET_CS5 000 -#define TARGET_CS6 020 -#define TARGET_CS7 040 -#define TARGET_CS8 060 -#define TARGET_CSTOPB 100 -#define TARGET_CREAD 200 -#define TARGET_PARENB 400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 -#define TARGET_CBAUDEX 001
[PATCH v2 2/3] linux-user: Add missing termbits types and values definitions
This patch introduces missing target types ('target_flag_t', 'target_cc_t', 'target_speed_t') in a few 'termibts.h' header files. Also, two missing values ('TARGET_IUTF8' and 'TARGET_EXTPROC') were also added. These values were also added in file 'syscall.c' in bitmask tables 'iflag_tbl[]' and 'lflag_tbl[]' which are used to convert values of 'struct termios' between target and host. Signed-off-by: Filip Bozuta --- linux-user/alpha/termbits.h | 1 + linux-user/cris/termbits.h| 18 linux-user/hppa/termbits.h| 17 +++ linux-user/mips/termbits.h| 17 +++ linux-user/ppc/termbits.h | 21 -- linux-user/sh4/termbits.h | 19 + linux-user/sparc/termbits.h | 18 linux-user/sparc64/termbits.h | 18 linux-user/syscall.c | 34 +++--- linux-user/xtensa/termbits.h | 53 ++- 10 files changed, 130 insertions(+), 86 deletions(-) diff --git a/linux-user/alpha/termbits.h b/linux-user/alpha/termbits.h index a71425174a..4a4b1e96f2 100644 --- a/linux-user/alpha/termbits.h +++ b/linux-user/alpha/termbits.h @@ -159,6 +159,7 @@ struct target_termios { #define TARGET_FLUSHO 0x0080 #define TARGET_PENDIN 0x2000 #define TARGET_IEXTEN 0x0400 +#define TARGET_EXTPROC 0x1000 #define TARGET_FIOCLEX TARGET_IO('f', 1) #define TARGET_FIONCLEXTARGET_IO('f', 2) diff --git a/linux-user/cris/termbits.h b/linux-user/cris/termbits.h index 475ee70fed..0c8d8fc051 100644 --- a/linux-user/cris/termbits.h +++ b/linux-user/cris/termbits.h @@ -5,13 +5,17 @@ #define TARGET_NCCS 19 +typedef unsigned char target_cc_t;/* cc_t */ +typedef unsigned inttarget_speed_t; /* speed_t */ +typedef unsigned inttarget_tcflag_t;/* tcflag_t */ + struct target_termios { -unsigned int c_iflag; /* input mode flags */ -unsigned int c_oflag; /* output mode flags */ -unsigned int c_cflag; /* control mode flags */ -unsigned int c_lflag; /* local mode flags */ -unsigned char c_line;/* line discipline */ -unsigned char c_cc[TARGET_NCCS];/* control characters */ +target_tcflag_t c_iflag; /* input mode flags */ +target_tcflag_t c_oflag; /* output mode flags */ +target_tcflag_t c_cflag; /* control mode flags */ +target_tcflag_t c_lflag; /* local mode flags */ +target_cc_t c_line;/* line discipline */ +target_cc_t c_cc[TARGET_NCCS]; /* control characters */ }; /* c_iflag bits */ @@ -29,6 +33,7 @@ struct target_termios { #define TARGET_IXANY 0004000 #define TARGET_IXOFF 001 #define TARGET_IMAXBEL 002 +#define TARGET_IUTF8 004 /* c_oflag bits */ #define TARGET_OPOST 001 @@ -118,6 +123,7 @@ struct target_termios { #define TARGET_FLUSHO 001 #define TARGET_PENDIN 004 #define TARGET_IEXTEN 010 +#define TARGET_EXTPROC 020 /* c_cc character offsets */ #define TARGET_VINTR 0 diff --git a/linux-user/hppa/termbits.h b/linux-user/hppa/termbits.h index 8fba839dd4..11fd4eed62 100644 --- a/linux-user/hppa/termbits.h +++ b/linux-user/hppa/termbits.h @@ -5,13 +5,17 @@ #define TARGET_NCCS 19 +typedef unsigned char target_cc_t;/* cc_t */ +typedef unsigned inttarget_speed_t; /* speed_t */ +typedef unsigned inttarget_tcflag_t;/* tcflag_t */ + struct target_termios { -unsigned int c_iflag; /* input mode flags */ -unsigned int c_oflag; /* output mode flags */ -unsigned int c_cflag; /* control mode flags */ -unsigned int c_lflag; /* local mode flags */ -unsigned char c_line;/* line discipline */ -unsigned char c_cc[TARGET_NCCS];/* control characters */ +target_tcflag_t c_iflag; /* input mode flags */ +target_tcflag_t c_oflag; /* output mode flags */ +target_tcflag_t c_cflag; /* control mode flags */ +target_tcflag_t c_lflag; /* local mode flags */ +target_cc_t c_line;/* line discipline */ +target_cc_t c_cc[TARGET_NCCS]; /* control characters */ }; /* c_iflag bits */ @@ -120,6 +124,7 @@ struct target_termios { #define TARGET_FLUSHO 001 #define TARGET_PENDIN 004 #define TARGET_IEXTEN 010 +#define TARGET_EXTPROC 020 /* c_cc character offsets */ #define TARGET_VINTR0 diff --git a/linux-user/mips/termbits.h b/linux-user/mips/termbits.h index 3287cf6df8..e8b4b58d87 100644 --- a/linux-user/mips/termbits.h +++ b/linux-user/mips/termbits.h @@ -5,13 +5,17 @@ #define TARGET_NCCS 23 +typedef unsigned char target_cc_t;/* cc_t */ +typedef unsigned inttarget_speed_t; /* speed_t */ +typedef unsigned
[PATCH v3 1/5] linux-user: Make cpu_env accessible in strace.c
Variable "cpu_env" is used in file "syscall.c" to store the information about the cpu environment. This variable is used because values of some syscalls can vary between cpu architectures. This patch makes the "cpu_env" accessible in "strace.c" so it can enable aproppriate "-strace" argument printing for these syscalls. This will be a useful addition for future "-strace" implementation in QEMU. Implementation notes: Functions "print_syscall()" and "print_syscall_ret()" which are stated and defined in "qemu.h" and "strace.c" respectively are used to print syscall arguments before and after syscall execution. These functions were changed with addition of a new argument "void *cpu_env". Strucute "struct syscallname" in "strace.c" is used to store the information about syscalls. Fields "call" and "result" represent pointers to functions which are used to print syscall arguments before and after execution. These fields were also changed with addition of a new "void *" argumetn. Also, all defined "print_*" and "print_syscall_ret*" functions in "strace.c" were changed to have the new "void *cpu_env". This was done to not cause build errors (even though none of these functions use this argument). Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/qemu.h| 4 +- linux-user/strace.c | 479 ++- linux-user/syscall.c | 5 +- 3 files changed, 247 insertions(+), 241 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 5c964389c1..63ddfe86fd 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -400,10 +400,10 @@ extern long safe_syscall_base(int *pending, long number, ...); int host_to_target_waitstatus(int status); /* strace.c */ -void print_syscall(int num, +void print_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6); -void print_syscall_ret(int num, abi_long ret, +void print_syscall_ret(void *cpu_env, int num, abi_long ret, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6); /** diff --git a/linux-user/strace.c b/linux-user/strace.c index 13981341b3..f0624b6206 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -16,10 +16,10 @@ struct syscallname { int nr; const char *name; const char *format; -void (*call)(const struct syscallname *, +void (*call)(void *, const struct syscallname *, abi_long, abi_long, abi_long, abi_long, abi_long, abi_long); -void (*result)(const struct syscallname *, abi_long, +void (*result)(void *, const struct syscallname *, abi_long, abi_long, abi_long, abi_long, abi_long, abi_long, abi_long); }; @@ -634,7 +634,7 @@ print_clockid(int clockid, int last) /* select */ #ifdef TARGET_NR__newselect static void -print_newselect(const struct syscallname *name, +print_newselect(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -652,7 +652,7 @@ print_newselect(const struct syscallname *name, #ifdef TARGET_NR_semctl static void -print_semctl(const struct syscallname *name, +print_semctl(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -664,7 +664,7 @@ print_semctl(const struct syscallname *name, #endif static void -print_execve(const struct syscallname *name, +print_execve(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -697,7 +697,7 @@ print_execve(const struct syscallname *name, #ifdef TARGET_NR_ipc static void -print_ipc(const struct syscallname *name, +print_ipc(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -741,9 +741,10 @@ print_syscall_err(abi_long ret) } static void -print_syscall_ret_addr(const struct syscallname *name, abi_long ret, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_syscall_ret_addr(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) { if (!p
[PATCH v3 4/5] linux-user: Add an api to print enumareted argument values with strace
This patch introduces a type 'struct enums' and function 'print_enums()' that can be used to print enumerated argument values of some syscalls in strace. This can be used in future strace implementations. Also, macros 'ENUM_GENERIC()', 'ENUM_TARGET()' and 'ENUM_END', are introduced to enable automatic generation of aproppriate enumarated values and their repsective string representations (these macros are exactly the same as 'FLAG_GENERIC()', 'FLAG_TARGET()' and 'FLAG_END'). Future patches are planned to modify all existing print functions in 'strace.c' that print arguments of syscalls with enumerated values to use this new api. Signed-off-by: Filip Bozuta --- linux-user/strace.c | 31 +++ 1 file changed, 31 insertions(+) diff --git a/linux-user/strace.c b/linux-user/strace.c index 40f863c6e2..def92c4d73 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -52,9 +52,23 @@ struct flags { /* end of flags array */ #define FLAG_END { 0, NULL } +/* Structure used to translate enumerated values into strings */ +struct enums { +abi_longe_value; /* enum value */ +const char *e_string; /* stringified enum */ +}; + +/* common enums for all architectures */ +#define ENUM_GENERIC(name) { name, #name } +/* target specific enums */ +#define ENUM_TARGET(name) { TARGET_ ## name, #name } +/* end of enums array */ +#define ENUM_END { 0, NULL } + UNUSED static const char *get_comma(int); UNUSED static void print_pointer(abi_long, int); UNUSED static void print_flags(const struct flags *, abi_long, int); +UNUSED static void print_enums(const struct enums *, abi_long, int); UNUSED static void print_at_dirfd(abi_long, int); UNUSED static void print_file_mode(abi_long, int); UNUSED static void print_open_flags(abi_long, int); @@ -1248,6 +1262,23 @@ print_flags(const struct flags *f, abi_long flags, int last) } } +static void +print_enums(const struct enums *e, abi_long enum_arg, int last) +{ +for (; e->e_string != NULL; e++) { +if (e->e_value == enum_arg) { +qemu_log("%s", e->e_string); +break; +} +} + +if (e->e_string == NULL) { +qemu_log("%#x", (unsigned int)enum_arg); +} + +qemu_log("%s", get_comma(last)); +} + static void print_at_dirfd(abi_long dirfd, int last) { -- 2.25.1
[PATCH v3 5/5] linux-user: Add strace support for printing arguments of some clock and time functions
This patch implements strace argument printing functionality for following syscalls: * clock_getres, clock_gettime, clock_settime - clock and time functions int clock_getres(clockid_t clockid, struct timespec *res) int clock_gettime(clockid_t clockid, struct timespec *tp) int clock_settime(clockid_t clockid, const struct timespec *tp) man page: https://man7.org/linux/man-pages/man2/clock_getres.2.html * gettimeofday - get time int gettimeofday(struct timeval *tv, struct timezone *tz) man page: https://man7.org/linux/man-pages/man2/gettimeofday.2.html * getitimer, setitimer - get or set value of an interval timer int getitimer(int which, struct itimerval *curr_value) int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value) man page: https://man7.org/linux/man-pages/man2/getitimer.2.html Implementation notes: All of the syscalls have some structue types as argument types and thus a separate printing function was stated in file "strace.list" for each of them. All of these functions use existing functions for their appropriate structure types ("print_timeval()" and "print_timezone()"). Functions "print_timespec()" and "print_itimerval()" were added in this patch so that they can be used to print types "struct timespec" and "struct itimerval" used by some of the syscalls. Function "print_itimerval()" uses the existing function "print_timeval()" to print fields of the structure "struct itimerval" that are of type "struct timeval". Function "print_enums()", which was introduced in the previous patch, is used to print the interval timer type which is the first argument of "getitimer()" and "setitimer()". Also, this function is used to print the clock id which is the first argument of "clock_getres()" and "clock_gettime()". For that reason, the existing function "print_clockid()" was removed in this patch. Existing function "print_clock_adjtime()" was also changed for this reason to use "print_enums()". The existing function "print_timeval()" was changed a little so that it prints the field names beside the values. Syscalls "clock_getres()" and "clock_gettime()" have the same number and types of arguments and thus their print functions "print_clock_getres" and "print_clock_gettime" share a common definition in file "strace.c". Signed-off-by: Filip Bozuta --- linux-user/strace.c| 285 +++-- linux-user/strace.list | 17 ++- 2 files changed, 230 insertions(+), 72 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index def92c4d73..aa5539f468 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -78,7 +78,9 @@ UNUSED static void print_string(abi_long, int); UNUSED static void print_buf(abi_long addr, abi_long len, int last); UNUSED static void print_raw_param(const char *, abi_long, int); UNUSED static void print_timeval(abi_ulong, int); +UNUSED static void print_timespec(abi_ulong, int); UNUSED static void print_timezone(abi_ulong, int); +UNUSED static void print_itimerval(abi_ulong, int); UNUSED static void print_number(abi_long, int); UNUSED static void print_signal(abi_ulong, int); UNUSED static void print_sockaddr(abi_ulong, abi_long, int); @@ -578,69 +580,6 @@ print_fdset(int n, abi_ulong target_fds_addr) } #endif -#ifdef TARGET_NR_clock_adjtime -/* IDs of the various system clocks */ -#define TARGET_CLOCK_REALTIME 0 -#define TARGET_CLOCK_MONOTONIC 1 -#define TARGET_CLOCK_PROCESS_CPUTIME_ID2 -#define TARGET_CLOCK_THREAD_CPUTIME_ID 3 -#define TARGET_CLOCK_MONOTONIC_RAW 4 -#define TARGET_CLOCK_REALTIME_COARSE 5 -#define TARGET_CLOCK_MONOTONIC_COARSE 6 -#define TARGET_CLOCK_BOOTTIME 7 -#define TARGET_CLOCK_REALTIME_ALARM8 -#define TARGET_CLOCK_BOOTTIME_ALARM9 -#define TARGET_CLOCK_SGI_CYCLE 10 -#define TARGET_CLOCK_TAI 11 - -static void -print_clockid(int clockid, int last) -{ -switch (clockid) { -case TARGET_CLOCK_REALTIME: -qemu_log("CLOCK_REALTIME"); -break; -case TARGET_CLOCK_MONOTONIC: -qemu_log("CLOCK_MONOTONIC"); -break; -case TARGET_CLOCK_PROCESS_CPUTIME_ID: -qemu_log("CLOCK_PROCESS_CPUTIME_ID"); -break; -case TARGET_CLOCK_THREAD_CPUTIME_ID: -qemu_log("CLOCK_THREAD_CPUTIME_ID"); -break; -case TARGET_CLOCK_MONOTONIC_RAW: -qemu_log("CLOCK_MONOTONIC_RAW"); -break; -case TARGET_CLOCK_RE
[PATCH v3 3/5] linux-user: Add strace support for printing arguments of syscalls used to lock and unlock memory
This patch implements strace argument printing functionality for following syscalls: * mlock, munlock, mlockall, munlockall - lock and unlock memory int mlock(const void *addr, size_t len) int munlock(const void *addr, size_t len) int mlockall(int flags) int munlockall(void) man page: https://man7.org/linux/man-pages/man2/mlock.2.html Implementation notes: Syscall mlockall() takes an argument that is composed of predefined values which represent flags that determine the type of locking operation that is to be performed. For that reason, a printing function "print_mlockall" was stated in file "strace.list". This printing function uses an already existing function "print_flags()" to print the "flags" argument. These flags are stated inside an array "mlockall_flags" that contains values of type "struct flags". These values are instantiated using an existing macro "FLAG_TARGET()" that crates aproppriate target flag values based on those defined in files '/target_syscall.h'. These target flag values were changed from "TARGET_MLOCKALL_MCL*" to "TARGET_MCL_*" so that they can be aproppriately set and recognised in "strace.c" with "FLAG_TARGET()". Value for "MCL_ONFAULT" was added in this patch. This value was also added in "syscall.c" in function "target_to_host_mlockall_arg()". Because this flag value was added in kernel version 4.4, it is enwrapped in an #ifdef directive (both in "syscall.c" and in "strace.c") as to support older kernel versions. The other syscalls have only primitive argument types, so the rest of the implementation was handled by stating an appropriate printing format in file "strace.list". Syscall mlock2() is not implemented in "syscall.c" and thus it's argument printing is not implemented in this patch. Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/aarch64/target_syscall.h| 5 +++-- linux-user/alpha/target_syscall.h | 5 +++-- linux-user/arm/target_syscall.h| 6 -- linux-user/cris/target_syscall.h | 5 +++-- linux-user/hppa/target_syscall.h | 5 +++-- linux-user/i386/target_syscall.h | 5 +++-- linux-user/m68k/target_syscall.h | 6 +++--- linux-user/microblaze/target_syscall.h | 5 +++-- linux-user/mips/target_syscall.h | 5 +++-- linux-user/mips64/target_syscall.h | 5 +++-- linux-user/nios2/target_syscall.h | 5 +++-- linux-user/openrisc/target_syscall.h | 5 +++-- linux-user/ppc/target_syscall.h| 5 +++-- linux-user/riscv/target_syscall.h | 5 +++-- linux-user/s390x/target_syscall.h | 5 +++-- linux-user/sh4/target_syscall.h| 5 +++-- linux-user/sparc/target_syscall.h | 5 +++-- linux-user/sparc64/target_syscall.h| 5 +++-- linux-user/strace.c| 21 + linux-user/strace.list | 8 linux-user/syscall.c | 10 -- linux-user/tilegx/target_syscall.h | 5 +++-- linux-user/x86_64/target_syscall.h | 5 +++-- linux-user/xtensa/target_syscall.h | 5 +++-- 24 files changed, 97 insertions(+), 49 deletions(-) diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h index 995e475c73..3194e6b009 100644 --- a/linux-user/aarch64/target_syscall.h +++ b/linux-user/aarch64/target_syscall.h @@ -16,8 +16,9 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "3.8.0" #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #define TARGET_PR_SVE_SET_VL 50 #define TARGET_PR_SVE_GET_VL 51 diff --git a/linux-user/alpha/target_syscall.h b/linux-user/alpha/target_syscall.h index 3426cc5b4e..fd389422e3 100644 --- a/linux-user/alpha/target_syscall.h +++ b/linux-user/alpha/target_syscall.h @@ -258,7 +258,8 @@ struct target_pt_regs { #define TARGET_UAC_NOFIX 2 #define TARGET_UAC_SIGBUS 4 #define TARGET_MINSIGSTKSZ 4096 -#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 -#define TARGET_MLOCKALL_MCL_FUTURE 0x4000 +#define TARGET_MCL_CURRENT 0x2000 +#define TARGET_MCL_FUTURE 0x4000 +#define TARGET_MCL_ONFAULT 0x8000 #endif /* ALPHA_TARGET_SYSCALL_H */ diff --git a/linux-user/arm/target_syscall.h b/linux-user/arm/target_syscall.h index f85cbdaf56..e870ed7a54 100644 --- a/linux-user/arm/target_syscall.h +++ b/linux-user/arm/target_syscall.h @@ -28,8 +28,10 @@ struct target_pt_regs { #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_M
[PATCH v3 0/5] Add strace support for printing arguments for a group of selected syscalls
This series covers strace support for following syscalls: *truncate() *munlock() *clock_gettimeofday() *ftruncate()*munlockall() *clock_getitimer() *getsid() *clock_getres() *clock_setitimer() *mlock()*clock_gettime() *mlockall() *clock_settime() Testing method: Mini test programs were written that run these syscalls for different arguments. Those programs were compiled (sometimes using cross-compilers) for the following architectures: * Intel 64-bit (little endian) (gcc) * Power pc 32-bit (big endian) (powerpc-linux-gnu-gcc) * Power pc 64-bit (big endian) (powerpc64-linux-gnu-gcc) The corresponding native programs were executed with strace, without using QEMU, on intel (x86_64) host. All applicable compiled programs were in turn executed with "-strace" through QEMU and the strace printing results obtained were the same ones gotten for native execution. v2: * added patch that enables 'cpu_env' to be accessible from "strace.c" * cut and pasted "regpairs_aligned" from 'syscall.c' to 'qemu.h' so that it can be used for "print_truncate64" and "print_ftruncate64" * changed flag names from 'TARGET_MLOCKALL_MCL_*' to 'TARGET_MCL_*' * added target flag value 'TARGET_MCL_ONFAULT' for 'MCL_ONFAULT' * added 'print_syscall_ret_setitimer' for old value of the interval timer * added a function 'print_itimer_type' that prints the interval timer type v3: * added patch that introduces an api that prints enumarted values with strace * used this new introduced api to print certain arguments of syscalls in patch 4 * rebased the series to use the new 'print_syscall_err()' Filip Bozuta (5): linux-user: Make cpu_env accessible in strace.c linux-user: Add strace support for printing arguments of truncate()/ftruncate() and getsid() linux-user: Add strace support for printing arguments of syscalls used to lock and unlock memory linux-user: Add an api to print enumareted argument values with strace linux-user: Add strace support for printing arguments of some clock and time functions linux-user/aarch64/target_syscall.h| 5 +- linux-user/alpha/target_syscall.h | 5 +- linux-user/arm/target_syscall.h| 6 +- linux-user/cris/target_syscall.h | 5 +- linux-user/hppa/target_syscall.h | 5 +- linux-user/i386/target_syscall.h | 5 +- linux-user/m68k/target_syscall.h | 6 +- linux-user/microblaze/target_syscall.h | 5 +- linux-user/mips/target_syscall.h | 5 +- linux-user/mips64/target_syscall.h | 5 +- linux-user/nios2/target_syscall.h | 5 +- linux-user/openrisc/target_syscall.h | 5 +- linux-user/ppc/target_syscall.h| 5 +- linux-user/qemu.h | 39 +- linux-user/riscv/target_syscall.h | 5 +- linux-user/s390x/target_syscall.h | 5 +- linux-user/sh4/target_syscall.h| 5 +- linux-user/sparc/target_syscall.h | 5 +- linux-user/sparc64/target_syscall.h| 5 +- linux-user/strace.c| 863 - linux-user/strace.list | 35 +- linux-user/syscall.c | 47 +- linux-user/tilegx/target_syscall.h | 5 +- linux-user/x86_64/target_syscall.h | 5 +- linux-user/xtensa/target_syscall.h | 5 +- 25 files changed, 692 insertions(+), 399 deletions(-) -- 2.25.1
[PATCH v3 2/5] linux-user: Add strace support for printing arguments of truncate()/ftruncate() and getsid()
This patch implements strace argument printing functionality for following syscalls: * truncate, ftruncate - truncate a file to a specified length int truncate/truncate64(const char *path, off_t length) int ftruncate/ftruncate64(int fd, off_t length) man page: https://man7.org/linux/man-pages/man2/truncate.2.html * getsid - get session ID pid_t getsid(pid_t pid) man page: https://man7.org/linux/man-pages/man2/getsid.2.html Implementation notes: Syscalls truncate/truncate64 take string argument types and thus a separate print function "print_truncate/print_truncate64" is stated in file "strace.list". This function is defined and implemented in "strace.c" by using an existing function used to print string arguments: "print_string()". For syscall ftruncate64, a separate printing function was also stated in "strace.c" as it requires a special kind of handling. The other syscalls have only primitive argument types, so the rest of the implementation was handled by stating an appropriate printing format in file "strace.list". Function "regpairs_aligned()" was cut & pasted from "syscall.c" to "qemu.h" as it is used by functions "print_truncate64()" and "print_ftruncate64()" to print the offset arguments of "truncate64()" and "ftruncate64()". Signed-off-by: Filip Bozuta Reviewed-by: Laurent Vivier --- linux-user/qemu.h | 35 +++ linux-user/strace.c| 47 ++ linux-user/strace.list | 10 - linux-user/syscall.c | 32 4 files changed, 87 insertions(+), 37 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 63ddfe86fd..f431805e57 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -706,6 +706,41 @@ static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) } #endif /* TARGET_ABI_BITS != 32 */ + +/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ +#ifdef TARGET_ARM +static inline int regpairs_aligned(void *cpu_env, int num) +{ +return CPUARMState *)cpu_env)->eabi) == 1) ; +} +#elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32) +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#elif defined(TARGET_PPC) && !defined(TARGET_PPC64) +/* + * SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs + * of registers which translates to the same as ARM/MIPS, because we start with + * r3 as arg1 + */ +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#elif defined(TARGET_SH4) +/* SH4 doesn't align register pairs, except for p{read,write}64 */ +static inline int regpairs_aligned(void *cpu_env, int num) +{ +switch (num) { +case TARGET_NR_pread64: +case TARGET_NR_pwrite64: +return 1; + +default: +return 0; +} +} +#elif defined(TARGET_XTENSA) +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#else +static inline int regpairs_aligned(void *cpu_env, int num) { return 0; } +#endif + /** * preexit_cleanup: housekeeping before the guest exits * diff --git a/linux-user/strace.c b/linux-user/strace.c index f0624b6206..7dc239b9f1 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1958,6 +1958,53 @@ print_lseek(void *cpu_env, const struct syscallname *name, } #endif +#ifdef TARGET_NR_truncate +static void +print_truncate(void *cpu_env, 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_string(arg0, 0); +print_raw_param(TARGET_ABI_FMT_ld, arg1, 1); +print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_truncate64 +static void +print_truncate64(void *cpu_env, 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_string(arg0, 0); +if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) { +arg1 = arg2; +arg2 = arg3; +} +print_raw_param("%" PRIu64, target_offset64(arg1, arg2), 1); +print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_ftruncate64 +static void +print_ftruncate64(void *cpu_env, 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_raw_param("%d", arg0, 0); +if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) { +arg1 = arg2; +arg2 = arg3; +} +print_raw_param("%" PRIu64, target_
[PATCH v2 0/2] This two patch series introduces functionality for a group
The list of implemented syscalls and implementation details can be found in the second patch of the series which introduces the implementation. The first patch introduces a little modification to already existing converting functions that convert values of 'struct itimerspec' between target and host and vice versa. This modification was also used in the second patch in similar converting functions which convert type 'struct itimerspec64' between target and host. Testing method: The implementation of the implemented syscalls was tested using already existing tests from LTP test suite which was built inside chroot. v2: *changed 'target_to_host/host_to_target_itimerspec/64()' to use 'offsetof()' to determine converting adress for 'timespec' instead of 'sizeof()' Filip Bozuta (2): linux-user: Modify 'target_to_host/host_to_target_itimerspec()' linux-user: Add support for a group of 2038 safe syscalls linux-user/syscall.c | 181 -- linux-user/syscall_defs.h | 5 ++ 2 files changed, 160 insertions(+), 26 deletions(-) -- 2.25.1
[PATCH v2 2/2] linux-user: Add support for a group of 2038 safe syscalls
This patch implements functionality for following time64 syscalls: *clock_getres_time64 This a year 2038 safe variant of syscall: int clock_getres(clockid_t clockid, struct timespec *res) --finding the resoultion of a specified clock-- man page: https://man7.org/linux/man-pages/man2/clock_getres.2.html *timer_gettime64 *timer_settime64 These are year 2038 safe variants of syscalls: int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) int timer_gettime(timer_t timerid, struct itimerspec *curr_value) --arming/dissarming and fetching state of POSIX per-process timer-- man page: https://man7.org/linux/man-pages/man2/timer_settime.2.html *timerfd_gettime64 *timerfd_settime64 These are year 2038 safe variants of syscalls: int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) int timerfd_gettime(int fd, struct itimerspec *curr_value) --timers that notify via file descriptor-- man page: https://man7.org/linux/man-pages/man2/timerfd_settime.2.html Implementation notes: Syscall 'clock_getres_time64' was implemented similarly to 'clock_getres()'. The only difference was that for the conversion of 'struct timespec' from host to target, function 'host_to_target_timespec64()' was used instead of 'host_to_target_timespec()'. For other syscalls, new functions 'host_to_target_itimerspec64()' and 'target_to_host_itimerspec64()' were added to convert the value of the 'struct itimerspec' from host to target and vice versa. A new type 'struct target__kernel_itimerspec' was added in 'syscall_defs.h'. This type was defined with fields which are of the already defined type 'struct target_timespec'. This new 'struct target__kernel_itimerspec' type is used in these new converting functions. These new functions were defined similarly to 'host_to_target_itimerspec()' and 'target_to_host_itimerspec()' the only difference being that 'target_to_host_timespec64()' and 'host_to_target_timespec64()' were used. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 139 +- linux-user/syscall_defs.h | 5 ++ 2 files changed, 143 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b1baed346c..9040e794ec 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1254,7 +1254,9 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts, } #endif -#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) +#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \ +defined(TARGET_NR_timer_settime64) || \ +(defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) static inline abi_long target_to_host_timespec64(struct timespec *host_ts, abi_ulong target_addr) { @@ -6808,6 +6810,24 @@ static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its, } #endif +#if defined(TARGET_NR_timer_settime64) || \ +(defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) +static inline abi_long target_to_host_itimerspec64(struct itimerspec *host_its, + abi_ulong target_addr) +{ +if (target_to_host_timespec64(_its->it_interval, target_addr + + offsetof(struct target__kernel_itimerspec, + it_interval)) || +target_to_host_timespec64(_its->it_value, target_addr + + offsetof(struct target__kernel_itimerspec, + it_value))) { +return -TARGET_EFAULT; +} + +return 0; +} +#endif + #if ((defined(TARGET_NR_timerfd_gettime) || \ defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \ defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime) @@ -6826,6 +6846,26 @@ static inline abi_long host_to_target_itimerspec(abi_ulong target_addr, } #endif +#if ((defined(TARGET_NR_timerfd_gettime64) || \ + defined(TARGET_NR_timerfd_settime64)) && defined(CONFIG_TIMERFD)) || \ + defined(TARGET_NR_timer_gettime64) || defined(TARGET_NR_timer_settime64) +static inline abi_long host_to_target_itimerspec64(abi_ulong target_addr, + struct itimerspec *host_its) +{ +if (host_to_target_timespec64(target_addr + + offsetof(struct target__kernel_itimerspec, + it_interval), + _its->it_interval) || +
[PATCH v2 1/2] linux-user: Modify 'target_to_host/host_to_target_itimerspec()'
Functions 'target_to_host_itimerspec()' and 'host_to_target_itimerspec()' are used to convert values of type 'struct itimerspec' between target and host. This type has 'struct timespec' as its fields. That is the reason why this patch introduces a little modification to the converting functions to be implemented using already existing functions that convert 'struct timespec': 'target_to_host_timespec()' and 'host_to_target_timespec()'. This makes the code of 'target_to_host_itimerspec()' and 'host_to_target_itimerspec()' more clean and readable. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 46 ++-- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1211e759c2..b1baed346c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1236,7 +1236,9 @@ static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr, defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \ defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \ defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \ -defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) +defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) || \ +defined(TARGET_NR_timer_settime) || \ +(defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)) static inline abi_long target_to_host_timespec(struct timespec *host_ts, abi_ulong target_addr) { @@ -6790,46 +6792,36 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1, #if defined(TARGET_NR_timer_settime) || \ (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)) -static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec, +static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its, abi_ulong target_addr) { -struct target_itimerspec *target_itspec; - -if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) { +if (target_to_host_timespec(_its->it_interval, target_addr + +offsetof(struct target_itimerspec, + it_interval)) || +target_to_host_timespec(_its->it_value, target_addr + +offsetof(struct target_itimerspec, + it_value))) { return -TARGET_EFAULT; } -host_itspec->it_interval.tv_sec = -tswapal(target_itspec->it_interval.tv_sec); -host_itspec->it_interval.tv_nsec = -tswapal(target_itspec->it_interval.tv_nsec); -host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec); -host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec); - -unlock_user_struct(target_itspec, target_addr, 1); return 0; } #endif #if ((defined(TARGET_NR_timerfd_gettime) || \ defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \ -defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime) + defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime) static inline abi_long host_to_target_itimerspec(abi_ulong target_addr, - struct itimerspec *host_its) -{ -struct target_itimerspec *target_itspec; - -if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) { + struct itimerspec *host_its) +{ +if (host_to_target_timespec(target_addr + offsetof(struct target_itimerspec, + it_interval), +_its->it_interval) || +host_to_target_timespec(target_addr + offsetof(struct target_itimerspec, + it_value), +_its->it_value)) { return -TARGET_EFAULT; } - -target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec); -target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec); - -target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec); -target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec); - -unlock_user_struct(target_itspec, target_addr, 0); return 0; } #endif -- 2.25.1
[PATCH 0/2] Adding support for a group of year 2038 safe syscalls
This two patch series introduces functionality for a group of time64 syscalls. The list of implemented syscalls and implementation details can be found in the second patch of the series which introduces the implementation. The first patch introduces a little modification to already existing converting functions that convert values of 'struct itimerspec' between target and host and vice versa. This modification was also used in the second patch in similar converting functions which convert type 'struct itimerspec64' between target and host. Testing method: The implementation of the implemented syscalls was tested using already existing tests from LTP test suite which was built inside chroot. Filip Bozuta (2): linux-user: Modify 'target_to_host/host_to_target_itimerspec()' linux-user: Add support for a group of 2038 safe syscalls linux-user/syscall.c | 166 --- 1 file changed, 141 insertions(+), 25 deletions(-) -- 2.25.1
[PATCH 2/2] linux-user: Add support for a group of 2038 safe syscalls
This patch implements functionality for following time64 syscalls: *clock_getres_time64 This a year 2038 safe variant of syscall: int clock_getres(clockid_t clockid, struct timespec *res) --finding the resoultion of a specified clock-- man page: https://man7.org/linux/man-pages/man2/clock_getres.2.html *timer_gettime64 *timer_settime64 These are year 2038 safe variants of syscalls: int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) int timer_gettime(timer_t timerid, struct itimerspec *curr_value) --arming/dissarming and fetching state of POSIX per-process timer-- man page: https://man7.org/linux/man-pages/man2/timer_settime.2.html *timerfd_gettime64 *timerfd_settime64 These are year 2038 safe variants of syscalls: int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) int timerfd_gettime(int fd, struct itimerspec *curr_value) --timers that notify via file descriptor-- man page: https://man7.org/linux/man-pages/man2/timerfd_settime.2.html Implementation notes: Syscall 'clock_getres_time64' was implemented similarly to 'clock_getres()'. The only difference was that for the conversion of 'struct timespec' from host to target, function 'host_to_target_timespec64()' was used instead of 'host_to_target_timespec()'. For other syscalls, new functions 'host_to_target_itimerspec64()' and 'target_to_host_itimerspec64()' were added to convert the value of the 'struct itimerspec' from host to target and vice versa. A new type 'struct target__kernel_itimerspec' was added in 'syscall_defs.h'. This type was defined with fields which are of the already defined type 'struct target_timespec'. This new 'struct target__kernel_itimerspec' type is used in these new converting functions. These new functions were defined similarly to 'host_to_target_itimerspec()' and 'target_to_host_itimerspec()' the only difference being that 'target_to_host_timespec64()' and 'host_to_target_timespec64()' were used. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 132 ++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 17e09c3cd3..9084a0bd3f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1254,7 +1254,9 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts, } #endif -#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) +#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \ +defined(TARGET_NR_timer_settime64) || \ +(defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) static inline abi_long target_to_host_timespec64(struct timespec *host_ts, abi_ulong target_addr) { @@ -6805,6 +6807,21 @@ static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its, } #endif +#if defined(TARGET_NR_timer_settime64) || \ +(defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) +static inline abi_long target_to_host_itimerspec64(struct itimerspec *host_its, + abi_ulong target_addr) +{ +if (target_to_host_timespec64(_its->it_interval, target_addr) || +target_to_host_timespec64(_its->it_value, target_addr + + sizeof(struct target__kernel_timespec))) { +return -TARGET_EFAULT; +} + +return 0; +} +#endif + #if ((defined(TARGET_NR_timerfd_gettime) || \ defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \ defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime) @@ -6820,6 +6837,22 @@ static inline abi_long host_to_target_itimerspec(abi_ulong target_addr, } #endif +#if ((defined(TARGET_NR_timerfd_gettime64) || \ + defined(TARGET_NR_timerfd_settime64)) && defined(CONFIG_TIMERFD)) || \ + defined(TARGET_NR_timer_gettime64) || defined(TARGET_NR_timer_settime64) +static inline abi_long host_to_target_itimerspec64(abi_ulong target_addr, + struct itimerspec *host_its) +{ +if (host_to_target_timespec64(target_addr, _its->it_interval) || +host_to_target_timespec64(target_addr + + sizeof(struct target__kernel_timespec), + _its->it_value)) { +return -TARGET_EFAULT; +} +return 0; +} +#endif + #if defined(TARGET_NR_adjtimex) || \ (defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)) static inline abi_long target_to_host_timex(struct timex *host_tx,
[PATCH 1/2] linux-user: Modify 'target_to_host/host_to_target_itimerspec()'
Functions 'target_to_host_itimerspec()' and 'host_to_target_itimerspec()' are used to convert values of type 'struct itimerspec' between target and host. This type has 'struct timespec' as its fields. That is the reason why this patch introduces a little modification to the converting functions to be implemented using already existing functions that convert 'struct timespec': 'target_to_host_timespec()' and 'host_to_target_timespec()'. This makes the code of 'target_to_host_itimerspec()' and 'host_to_target_itimerspec()' more clean and readable. Signed-off-by: Filip Bozuta --- linux-user/syscall.c | 38 -- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1211e759c2..17e09c3cd3 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1236,7 +1236,9 @@ static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr, defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \ defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \ defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \ -defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) +defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) || \ +defined(TARGET_NR_timer_settime) || \ +(defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)) static inline abi_long target_to_host_timespec(struct timespec *host_ts, abi_ulong target_addr) { @@ -6790,46 +6792,30 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1, #if defined(TARGET_NR_timer_settime) || \ (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)) -static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec, +static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its, abi_ulong target_addr) { -struct target_itimerspec *target_itspec; - -if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) { +if (target_to_host_timespec(_its->it_interval, target_addr) || +target_to_host_timespec(_its->it_value, target_addr + +sizeof(struct target_timespec))) { return -TARGET_EFAULT; } -host_itspec->it_interval.tv_sec = -tswapal(target_itspec->it_interval.tv_sec); -host_itspec->it_interval.tv_nsec = -tswapal(target_itspec->it_interval.tv_nsec); -host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec); -host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec); - -unlock_user_struct(target_itspec, target_addr, 1); return 0; } #endif #if ((defined(TARGET_NR_timerfd_gettime) || \ defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \ -defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime) + defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime) static inline abi_long host_to_target_itimerspec(abi_ulong target_addr, - struct itimerspec *host_its) + struct itimerspec *host_its) { -struct target_itimerspec *target_itspec; - -if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) { +if (host_to_target_timespec(target_addr, _its->it_interval) || +host_to_target_timespec(target_addr + sizeof(struct target_timespec), +_its->it_value)) { return -TARGET_EFAULT; } - -target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec); -target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec); - -target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec); -target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec); - -unlock_user_struct(target_itspec, target_addr, 0); return 0; } #endif -- 2.25.1
[PATCH v2 1/4] linux-user: Add support for a group of btrfs inode ioctls
This patch implements functionality of following ioctls: BTRFS_IOC_INO_LOOKUP - Reading tree root id and path Read tree root id and path for a given file or directory. The name and tree root id are returned in an ioctl's third argument that represents a pointer to a following type: struct btrfs_ioctl_ino_lookup_args { __u64 treeid; __u64 objectid; char name[BTRFS_INO_LOOKUP_PATH_MAX]; }; Before calling this ioctl, field 'objectid' should be filled with the object id value for which the tree id and path are to be read. Value 'BTRFS_FIRST_FREE_OBJECTID' represents the object id for the first available btrfs object (directory or file). BTRFS_IOC_INO_PATHS - Reading paths to all files Read path to all files with a certain inode number. The paths are returned in the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_ino_path_args { __u64 inum; /* in */ __u64 size; /* in */ __u64 reserved[4]; /* struct btrfs_data_container *fspath; out */ __u64 fspath; /* out */ }; Before calling this ioctl, the 'inum' and 'size' field should be filled with the aproppriate inode number and size of the directory where file paths should be looked for. For now, the paths are returned in an '__u64' (unsigned long long) value 'fspath'. BTRFS_IOC_LOGICAL_INO - Reading inode numbers Read inode numbers for files on a certain logical adress. The inode numbers are returned in the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_logical_ino_args { __u64 logical;/* in */ __u64 size; /* in */ __u64 reserved[3];/* must be 0 for now */ __u64 flags; /* in, v2 only */ /* struct btrfs_data_container *inodes;out */ __u64 inodes; }; Before calling this ioctl, the 'logical' and 'size' field should be filled with the aproppriate logical adress and size of where the inode numbers of files should be looked for. For now, the inode numbers are returned in an '__u64' (unsigned long long) value 'inodes'. BTRFS_IOC_LOGICAL_INO_V2 - Reading inode numbers Same as the above mentioned ioctl except that it allows passing a flags 'BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET'. BTRFS_IOC_INO_LOOKUP_USER - Reading subvolume name and path Read name and path of a subvolume. The tree root id and path are read in an ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_ino_lookup_user_args { /* in, inode number containing the subvolume of 'subvolid' */ __u64 dirid; /* in */ __u64 treeid; /* out, name of the subvolume of 'treeid' */ char name[BTRFS_VOL_NAME_MAX + 1]; /* * out, constructed path from the directory with which the ioctl is * called to dirid */ char path[BTRFS_INO_LOOKUP_USER_PATH_MAX]; }; Before calling this ioctl, the 'dirid' and 'treeid' field should be filled with aproppriate values which represent the inode number of the directory that contains the subvolume and treeid of the subvolume. Implementation notes: All of the ioctls in this patch use structure types as third arguments. That is the reason why aproppriate thunk definitions were added in file 'syscall_types.h'. Signed-off-by: Filip Bozuta --- linux-user/ioctls.h| 20 linux-user/syscall_defs.h | 10 ++ linux-user/syscall_types.h | 24 3 files changed, 54 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index c6303a0406..a7f5664487 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -202,6 +202,10 @@ IOCTL(BTRFS_IOC_SNAP_DESTROY, IOC_W, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) #endif +#ifdef BTRFS_IOC_INO_LOOKUP + IOCTL(BTRFS_IOC_INO_LOOKUP, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_args))) +#endif #ifdef BTRFS_IOC_SUBVOL_GETFLAGS IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG)) #endif @@ -212,6 +216,14 @@ IOCTL(BTRFS_IOC_DEV_INFO, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_dev_info_args))) #endif +#ifdef BTRFS_IOC_INO_PATHS + IOCTL(BTRFS_IOC_INO_PATHS, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_path_args))) +#endif +#ifdef BTRFS_IOC_LOGICAL_INO + IOCTL(BTRFS_IOC_LOGICAL_INO, IOC_RW, + MK_PTR(MK_STRUCT
[PATCH v2 3/4] linux-user: Add support for btrfs ioctls used to manage quota
This patch implements functionality for following ioctls: BTRFS_IOC_QUOTA_CTL - Enabling/Disabling quota support Enable or disable quota support for a btrfs filesystem. Quota support is enabled or disabled using the ioctls third argument which represents a pointer to a following type: struct btrfs_ioctl_quota_ctl_args { __u64 cmd; __u64 status; }; Before calling this ioctl, the 'cmd' field should be filled with one of the values 'BTRFS_QUOTA_CTL_ENABLE' (enabling quota) 'BTRFS_QUOTA_CTL_DISABLE' (disabling quota). BTRFS_IOC_QGROUP_CREATE - Creating/Removing a subvolume quota group Create or remove a subvolume quota group. The subvolume quota group is created or removed using the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_qgroup_create_args { __u64 create; __u64 qgroupid; }; Before calling this ioctl, the 'create' field should be filled with the aproppriate value depending on if the user wants to create or remove a quota group (0 for removing, everything else for creating). Also, the 'qgroupid' field should be filled with the value for the quota group id that is to be created. BTRFS_IOC_QGROUP_ASSIGN - Asigning or removing a quota group as child group Asign or remove a quota group as child quota group of another group in the btrfs filesystem. The asignment is done using the ioctl's third argument which represents a pointert to a following type: struct btrfs_ioctl_qgroup_assign_args { __u64 assign; __u64 src; __u64 dst; }; Before calling this ioctl, the 'assign' field should be filled with the aproppriate value depending on if the user wants to asign or remove a quota group as a child quota group of another group (0 for removing, everythin else for asigning). Also, the 'src' and 'dst' fields should be filled with the aproppriate quota group id values depending on which quota group needs to asigned or removed as child quota group of another group ('src' gets asigned or removed as child group of 'dst'). BTRFS_IOC_QGROUP_LIMIT - Limiting the size of a quota group Limit the size of a quota group. The size of the quota group is limited with the ioctls third argument which represents a pointer to a following type: struct btrfs_ioctl_qgroup_limit_args { __u64 qgroupid; struct btrfs_qgroup_limit lim; }; Before calling this ioctl, the 'qgroup' id field should be filled with aproppriate value of the quota group id for which the size is to be limited. The second field is of following type: struct btrfs_qgroup_limit { __u64 flags; __u64 max_rfer; __u64 max_excl; __u64 rsv_rfer; __u64 rsv_excl; }; The 'max_rfer' field should be filled with the size to which the quota group should be limited. The 'flags' field can be used for passing additional options and can have values which can be found on: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/btrfs.h#L67 BTRFS_IOC_QUOTA_RESCAN_STATUS - Checking status of running rescan operation Check status of a running rescan operation. The status is checked using the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_quota_rescan_args { __u64 flags; __u64 progress; __u64 reserved[6]; }; If there is a rescan operation running, 'flags' field is set to 1, and 'progress' field is set to aproppriate value which represents the progress of the operation. BTRFS_IOC_QUOTA_RESCAN - Starting a rescan operation Start ar rescan operation to Trash all quota groups and scan the metadata again with the current config. Before calling this ioctl, BTRFS_IOC_QUOTA_RESCAN_STATUS sould be run to check if there is already a rescan operation runing. After that ioctl call, the received 'struct btrfs_ioctl_quota_rescan_args' should be than passed as this ioctls third argument. BTRFS_IOC_QUOTA_RESCAN_WAIT - Waiting for a rescan operation to finish Wait until a rescan operation is finished (if there is a rescan operation running). The third ioctls argument is ignored. Implementation notes: Almost all of the ioctls in this patch use structure types as third arguments. That is the reason why aproppriate thunk definitions were added in file 'syscall_types.h'. Signed-off-by: Filip Bozuta --- linux-user/ioctls.h| 27 +++ linux-user/syscall_defs.h | 14 ++ linux-user/syscall_types.h | 29 + 3 files changed, 70 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 2c553103e6..8665f504bf 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -227,6 +227,33 @@ IOCTL(BTRFS_IOC_LOGICAL_INO
[PATCH v2 2/4] linux-user: Add support for two btrfs ioctls used for subvolume
This patch implements functionality for following ioctl: BTRFS_IOC_DEFAULT_SUBVOL - Setting a default subvolume Set a default subvolume for a btrfs filesystem. The third ioctl's argument is a '__u64' (unsigned long long) which represents the id of a subvolume that is to be set as the default. BTRFS_IOC_GET_SUBVOL_ROOTREF - Getting tree and directory id of subvolumes Read tree and directory id of subvolumes from a btrfs filesystem. The tree and directory id's are returned in the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_get_subvol_rootref_args { /* in/out, minimum id of rootref's treeid to be searched */ __u64 min_treeid; /* out */ struct { __u64 treeid; __u64 dirid; } rootref[BTRFS_MAX_ROOTREF_BUFFER_NUM]; /* out, number of found items */ __u8 num_items; __u8 align[7]; }; Before calling this ioctl, 'min_treeid' field should be filled with value that represent the minimum value for the tree id. Implementation notes: Ioctl BTRFS_IOC_GET_SUBVOL_ROOTREF uses the above mentioned structure type as third argument. That is the reason why a aproppriate thunk structure definition is added in file 'syscall_types.h'. Signed-off-by: Filip Bozuta --- linux-user/ioctls.h| 7 +++ linux-user/syscall_defs.h | 4 linux-user/syscall_types.h | 11 +++ 3 files changed, 22 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index a7f5664487..2c553103e6 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -206,6 +206,9 @@ IOCTL(BTRFS_IOC_INO_LOOKUP, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_args))) #endif +#ifdef BTRFS_IOC_DEFAULT_SUBVOL + IOCTL(BTRFS_IOC_DEFAULT_SUBVOL, IOC_W, MK_PTR(TYPE_ULONGLONG)) +#endif #ifdef BTRFS_IOC_SUBVOL_GETFLAGS IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG)) #endif @@ -248,6 +251,10 @@ IOCTL(BTRFS_IOC_GET_SUBVOL_INFO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_subvol_info_args))) #endif +#ifdef BTRFS_IOC_GET_SUBVOL_ROOTREF + IOCTL(BTRFS_IOC_GET_SUBVOL_ROOTREF, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_subvol_rootref_args))) +#endif #ifdef BTRFS_IOC_INO_LOOKUP_USER IOCTL(BTRFS_IOC_INO_LOOKUP_USER, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_user_args))) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 7bb105428b..f4b4fc4a20 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -984,6 +984,8 @@ struct target_rtc_pll_info { 15, struct btrfs_ioctl_vol_args) #define TARGET_BTRFS_IOC_INO_LOOKUP TARGET_IOWR(BTRFS_IOCTL_MAGIC,\ 18, struct btrfs_ioctl_ino_lookup_args) +#define TARGET_BTRFS_IOC_DEFAULT_SUBVOL TARGET_IOW(BTRFS_IOCTL_MAGIC, \ + 19, abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_GETFLAGSTARGET_IOR(BTRFS_IOCTL_MAGIC, \ 25, abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_SETFLAGSTARGET_IOW(BTRFS_IOCTL_MAGIC, \ @@ -1006,6 +1008,8 @@ struct target_rtc_pll_info { 59, struct btrfs_ioctl_logical_ino_args) #define TARGET_BTRFS_IOC_GET_SUBVOL_INFOTARGET_IOR(BTRFS_IOCTL_MAGIC, \ 60, struct btrfs_ioctl_get_subvol_info_args) +#define TARGET_BTRFS_IOC_GET_SUBVOL_ROOTREF TARGET_IOWR(BTRFS_IOCTL_MAGIC,\ +61, struct btrfs_ioctl_get_subvol_rootref_args) #define TARGET_BTRFS_IOC_INO_LOOKUP_USERTARGET_IOWR(BTRFS_IOCTL_MAGIC,\ 62, struct btrfs_ioctl_ino_lookup_user_args) diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index 980c29000a..d2f1b30ff3 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -381,6 +381,17 @@ STRUCT(btrfs_ioctl_dev_info_args, MK_ARRAY(TYPE_ULONGLONG, 379), /* unused */ MK_ARRAY(TYPE_CHAR, BTRFS_DEVICE_PATH_NAME_MAX)) /* path */ +STRUCT(rootref, + TYPE_ULONGLONG, /* treeid */ + TYPE_ULONGLONG) /* dirid */ + +STRUCT(btrfs_ioctl_get_subvol_rootref_args, +TYPE_ULONGLONG, /* min_treeid */ +MK_ARRAY(MK_STRUCT(STRUCT_rootref), + BTRFS_MAX_ROOTREF_BUFFER_NUM), /* rootref */ +TYPE_CHAR, /* num_items */ +MK_ARRAY(TYPE_CHAR, 7)) /* align */ + STRUCT(btrfs_ioctl_get_dev_stats, TYPE_ULONGLONG, /* devid */ TYPE_ULONGLONG, /* nr_items */ -- 2.25.1
[PATCH v2 4/4] linux-user: Add support for btrfs ioctls used to scrub a filesystem
This patch implements functionality for following ioctls: BTRFS_IOC_SCRUB - Starting a btrfs filesystem scrub Start a btrfs filesystem scrub. The third ioctls argument is a pointer to a following type: struct btrfs_ioctl_scrub_args { __u64 devid;/* in */ __u64 start;/* in */ __u64 end; /* in */ __u64 flags;/* in */ struct btrfs_scrub_progress progress; /* out */ /* pad to 1k */ __u64 unused[(1024-32-sizeof(struct btrfs_scrub_progress))/8]; }; Before calling this ioctl, field 'devid' should be filled with value that represents the device id of the btrfs filesystem for which the scrub is to be started. BTRFS_IOC_SCRUB_CANCEL - Canceling scrub of a btrfs filesystem Cancel a btrfs filesystem scrub if it is running. The third ioctls argument is ignored. BTRFS_IOC_SCRUB_PROGRESS - Getting status of a running scrub Read the status of a running btrfs filesystem scrub. The third ioctls argument is a pointer to the above mentioned 'struct btrfs_ioctl_scrub_args'. Similarly as with 'BTRFS_IOC_SCRUB', the 'devid' field should be filled with value that represents the id of the btrfs device for which the scrub has started. The status of a running scrub is returned in the field 'progress' which is of type 'struct btrfs_scrub_progress' and its definition can be found at: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/btrfs.h#L150 Implementation nots: Ioctls in this patch use type 'struct btrfs_ioctl_scrub_args' as their third argument. That is the reason why an aproppriate thunk type definition is added in file 'syscall_types.h'. Signed-off-by: Filip Bozuta --- linux-user/ioctls.h| 11 +++ linux-user/syscall_defs.h | 6 ++ linux-user/syscall_types.h | 26 ++ 3 files changed, 43 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 8665f504bf..bf80615438 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -215,6 +215,17 @@ #ifdef BTRFS_IOC_SUBVOL_SETFLAGS IOCTL(BTRFS_IOC_SUBVOL_SETFLAGS, IOC_W, MK_PTR(TYPE_ULONGLONG)) #endif +#ifdef BTRFS_IOC_SCRUB + IOCTL(BTRFS_IOC_SCRUB, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_scrub_args))) +#endif +#ifdef BTRFS_IOC_SCRUB_CANCEL + IOCTL(BTRFS_IOC_SCRUB_CANCEL, 0, TYPE_NULL) +#endif +#ifdef BTRFS_IOC_SCRUB_PROGRESS + IOCTL(BTRFS_IOC_SCRUB_PROGRESS, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_scrub_args))) +#endif #ifdef BTRFS_IOC_DEV_INFO IOCTL(BTRFS_IOC_DEV_INFO, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_dev_info_args))) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 3f771ae5d1..589ec3e9b0 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -990,6 +990,12 @@ struct target_rtc_pll_info { 25, abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_SETFLAGSTARGET_IOW(BTRFS_IOCTL_MAGIC, \ 26, abi_ullong) +#define TARGET_BTRFS_IOC_SCRUB TARGET_IOWR(BTRFS_IOCTL_MAGIC,\ + 27, struct btrfs_ioctl_scrub_args) +#define TARGET_BTRFS_IOC_SCRUB_CANCEL TARGET_IO(BTRFS_IOCTL_MAGIC, \ + 28) +#define TARGET_BTRFS_IOC_SCRUB_PROGRESS TARGET_IOWR(BTRFS_IOCTL_MAGIC,\ + 29, struct btrfs_ioctl_scrub_args) #define TARGET_BTRFS_IOC_DEV_INFO TARGET_IOWR(BTRFS_IOCTL_MAGIC,\ 30, struct btrfs_ioctl_dev_info_args) #define TARGET_BTRFS_IOC_INO_PATHS TARGET_IOWR(BTRFS_IOCTL_MAGIC,\ diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index b4f462b5c6..345193270c 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -373,6 +373,32 @@ STRUCT(btrfs_ioctl_ino_lookup_user_args, MK_ARRAY(TYPE_CHAR, BTRFS_VOL_NAME_MAX + 1), /* name */ MK_ARRAY(TYPE_CHAR, BTRFS_INO_LOOKUP_USER_PATH_MAX)) /* path */ +STRUCT(btrfs_scrub_progress, + TYPE_ULONGLONG, /* data_extents_scrubbed */ + TYPE_ULONGLONG, /* tree_extents_scrubbed */ + TYPE_ULONGLONG, /* data_bytes_scrubbed */ + TYPE_ULONGLONG, /* tree_bytes_scrubbed */ + TYPE_ULONGLONG, /* read_errors */ + TYPE_ULONGLONG, /* csum_errors */ + TYPE_ULONGLONG, /* verify_errors */ + TYPE_ULONGLONG, /* no_csum */ + TYPE_ULONGLONG, /* csum_discards */ + TYPE_ULONGLONG, /* super_errors */ + TYPE_ULONGLONG, /* malloc_errors */ + TYPE_ULONGLONG, /* uncorrectable_errors */ + TYPE_ULONGLONG, /* corrected_er */ + TYPE_ULONGLONG
[PATCH v2 0/4] Add support for a group of btrfs ioctls - 2
This series covers support for following btrfs ioctls *BTRFS_IOC_DEFAULT_SUBVOL*BTRFS_IOC_QUOTA_RESCAN *BTRFS_IOC_GET_SUBVOL_ROOTREF*BTRFS_IOC_QUOTA_RESCAN_WAIT *BTRFS_IOC_QUOTA_CTL *BTRFS_IOC_SCRUB *BTRFS_IOC_QGROUP_CREATE *BTRFS_IOC_SCRUB_CANCEL *BTRFS_IOC_QGROUP_ASSIGN *BTRFS_IOC_SCRUB_PROGRESS *BTRFS_IOC_INO_PATHS *BTRFS_IOC_QGROUP_LIMIT *BTRFS_IOC_LOGICAL_INO *BTRFS_IOC_QUOTA_RESCAN_STATUS *BTRFS_IOC_LOGICAL_INO_V2 *BTRFS_IOC_INO_LOOKUP_USER *BTRFS_IOC_INO_LOOKUP The functionalities of individual ioctls were described in this series patch commit messages. Since all of these ioctls are added in kernel version 3.9, their definitions in file 'linux-user/ioctls.h' are enwrapped in an #ifdef directive. Testing method: Mini test programs were written for these ioctls. These test programs can be found on a repository which is located on the link: https://github.com/bozutaf/btrfs-tests bozutaf/btrfs-tests Contribute to bozutaf/btrfs-tests development by creating an account on GitHub. github.com These test programs were compiled (sometimes using cross compilers) for following architectures: * Intel 64-bit (little endian) * Power pc 32-bit (big endian) * Power pc 64-bit (big endian) The corresponding native programs were executed without using QEMU on an intel x86_64 host. All applicable compiled programs were in turn executed through QEMU and the results obtained were the same ones gotten for native execution v2: * added Signed-off-by tag (forgot in v1...) Based-on: <20200709155203.21106-1-filip.boz...@syrmia.com> Filip Bozuta (4): linux-user: Add support for a group of btrfs inode ioctls linux-user: Add support for two btrfs ioctls used for subvolume linux-user: Add support for btrfs ioctls used to manage quota linux-user: Add support for btrfs ioctls used to scrub a filesystem linux-user/ioctls.h| 65 +++ linux-user/syscall_defs.h | 34 ++ linux-user/syscall_types.h | 90 ++ 3 files changed, 189 insertions(+) -- 2.25.1
[PATCH 0/4] Add support for a group of btrfs ioctls - 2
This series covers support for following btrfs ioctls *BTRFS_IOC_DEFAULT_SUBVOL*BTRFS_IOC_QUOTA_RESCAN *BTRFS_IOC_GET_SUBVOL_ROOTREF*BTRFS_IOC_QUOTA_RESCAN_WAIT *BTRFS_IOC_QUOTA_CTL *BTRFS_IOC_SCRUB *BTRFS_IOC_QGROUP_CREATE *BTRFS_IOC_SCRUB_CANCEL *BTRFS_IOC_QGROUP_ASSIGN *BTRFS_IOC_SCRUB_PROGRESS *BTRFS_IOC_INO_PATHS *BTRFS_IOC_QGROUP_LIMIT *BTRFS_IOC_LOGICAL_INO *BTRFS_IOC_QUOTA_RESCAN_STATUS *BTRFS_IOC_LOGICAL_INO_V2 *BTRFS_IOC_INO_LOOKUP_USER *BTRFS_IOC_INO_LOOKUP The functionalities of individual ioctls were described in this series patch commit messages. Since all of these ioctls are added in kernel version 3.9, their definitions in file 'linux-user/ioctls.h' are enwrapped in an #ifdef directive. Testing method: Mini test programs were written for these ioctls. These test programs can be found on a repository which is located on the link: https://github.com/bozutaf/btrfs-tests These test programs were compiled (sometimes using cross compilers) for following architectures: * Intel 64-bit (little endian) * Power pc 32-bit (big endian) * Power pc 64-bit (big endian) The corresponding native programs were executed without using QEMU on an intel x86_64 host. All applicable compiled programs were in turn executed through QEMU and the results obtained were the same ones gotten for native execution. Based-on: <20200709155203.21106-1-filip.boz...@syrmia.com> Filip Bozuta (4): linux-user: Add support for a group of btrfs inode ioctls linux-user: Add support for two btrfs ioctls used for subvolume linux-user: Add support for btrfs ioctls used to manage quota linux-user: Add support for btrfs ioctls used to scrub a filesystem linux-user/ioctls.h| 65 +++ linux-user/syscall_defs.h | 34 ++ linux-user/syscall_types.h | 90 ++ 3 files changed, 189 insertions(+) -- 2.25.1
[PATCH 3/4] linux-user: Add support for btrfs ioctls used to manage quota
This patch implements functionality for following ioctls: BTRFS_IOC_QUOTA_CTL - Enabling/Disabling quota support Enable or disable quota support for a btrfs filesystem. Quota support is enabled or disabled using the ioctls third argument which represents a pointer to a following type: struct btrfs_ioctl_quota_ctl_args { __u64 cmd; __u64 status; }; Before calling this ioctl, the 'cmd' field should be filled with one of the values 'BTRFS_QUOTA_CTL_ENABLE' (enabling quota) 'BTRFS_QUOTA_CTL_DISABLE' (disabling quota). BTRFS_IOC_QGROUP_CREATE - Creating/Removing a subvolume quota group Create or remove a subvolume quota group. The subvolume quota group is created or removed using the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_qgroup_create_args { __u64 create; __u64 qgroupid; }; Before calling this ioctl, the 'create' field should be filled with the aproppriate value depending on if the user wants to create or remove a quota group (0 for removing, everything else for creating). Also, the 'qgroupid' field should be filled with the value for the quota group id that is to be created. BTRFS_IOC_QGROUP_ASSIGN - Asigning or removing a quota group as child group Asign or remove a quota group as child quota group of another group in the btrfs filesystem. The asignment is done using the ioctl's third argument which represents a pointert to a following type: struct btrfs_ioctl_qgroup_assign_args { __u64 assign; __u64 src; __u64 dst; }; Before calling this ioctl, the 'assign' field should be filled with the aproppriate value depending on if the user wants to asign or remove a quota group as a child quota group of another group (0 for removing, everythin else for asigning). Also, the 'src' and 'dst' fields should be filled with the aproppriate quota group id values depending on which quota group needs to asigned or removed as child quota group of another group ('src' gets asigned or removed as child group of 'dst'). BTRFS_IOC_QGROUP_LIMIT - Limiting the size of a quota group Limit the size of a quota group. The size of the quota group is limited with the ioctls third argument which represents a pointer to a following type: struct btrfs_ioctl_qgroup_limit_args { __u64 qgroupid; struct btrfs_qgroup_limit lim; }; Before calling this ioctl, the 'qgroup' id field should be filled with aproppriate value of the quota group id for which the size is to be limited. The second field is of following type: struct btrfs_qgroup_limit { __u64 flags; __u64 max_rfer; __u64 max_excl; __u64 rsv_rfer; __u64 rsv_excl; }; The 'max_rfer' field should be filled with the size to which the quota group should be limited. The 'flags' field can be used for passing additional options and can have values which can be found on: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/btrfs.h#L67 BTRFS_IOC_QUOTA_RESCAN_STATUS - Checking status of running rescan operation Check status of a running rescan operation. The status is checked using the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_quota_rescan_args { __u64 flags; __u64 progress; __u64 reserved[6]; }; If there is a rescan operation running, 'flags' field is set to 1, and 'progress' field is set to aproppriate value which represents the progress of the operation. BTRFS_IOC_QUOTA_RESCAN - Starting a rescan operation Start ar rescan operation to Trash all quota groups and scan the metadata again with the current config. Before calling this ioctl, BTRFS_IOC_QUOTA_RESCAN_STATUS sould be run to check if there is already a rescan operation runing. After that ioctl call, the received 'struct btrfs_ioctl_quota_rescan_args' should be than passed as this ioctls third argument. BTRFS_IOC_QUOTA_RESCAN_WAIT - Waiting for a rescan operation to finish Wait until a rescan operation is finished (if there is a rescan operation running). The third ioctls argument is ignored. Implementation notes: Almost all of the ioctls in this patch use structure types as third arguments. That is the reason why aproppriate thunk definitions were added in file 'syscall_types.h'. --- linux-user/ioctls.h| 27 +++ linux-user/syscall_defs.h | 14 ++ linux-user/syscall_types.h | 29 + 3 files changed, 70 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 2c553103e6..8665f504bf 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -227,6 +227,33 @@ IOCTL(BTRFS_IOC_LOGICAL_INO, IOC_RW,
[PATCH 4/4] linux-user: Add support for btrfs ioctls used to scrub a filesystem
This patch implements functionality for following ioctls: BTRFS_IOC_SCRUB - Starting a btrfs filesystem scrub Start a btrfs filesystem scrub. The third ioctls argument is a pointer to a following type: struct btrfs_ioctl_scrub_args { __u64 devid;/* in */ __u64 start;/* in */ __u64 end; /* in */ __u64 flags;/* in */ struct btrfs_scrub_progress progress; /* out */ /* pad to 1k */ __u64 unused[(1024-32-sizeof(struct btrfs_scrub_progress))/8]; }; Before calling this ioctl, field 'devid' should be filled with value that represents the device id of the btrfs filesystem for which the scrub is to be started. BTRFS_IOC_SCRUB_CANCEL - Canceling scrub of a btrfs filesystem Cancel a btrfs filesystem scrub if it is running. The third ioctls argument is ignored. BTRFS_IOC_SCRUB_PROGRESS - Getting status of a running scrub Read the status of a running btrfs filesystem scrub. The third ioctls argument is a pointer to the above mentioned 'struct btrfs_ioctl_scrub_args'. Similarly as with 'BTRFS_IOC_SCRUB', the 'devid' field should be filled with value that represents the id of the btrfs device for which the scrub has started. The status of a running scrub is returned in the field 'progress' which is of type 'struct btrfs_scrub_progress' and its definition can be found at: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/btrfs.h#L150 Implementation nots: Ioctls in this patch use type 'struct btrfs_ioctl_scrub_args' as their third argument. That is the reason why an aproppriate thunk type definition is added in file 'syscall_types.h'. --- linux-user/ioctls.h| 11 +++ linux-user/syscall_defs.h | 6 ++ linux-user/syscall_types.h | 26 ++ 3 files changed, 43 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 8665f504bf..bf80615438 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -215,6 +215,17 @@ #ifdef BTRFS_IOC_SUBVOL_SETFLAGS IOCTL(BTRFS_IOC_SUBVOL_SETFLAGS, IOC_W, MK_PTR(TYPE_ULONGLONG)) #endif +#ifdef BTRFS_IOC_SCRUB + IOCTL(BTRFS_IOC_SCRUB, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_scrub_args))) +#endif +#ifdef BTRFS_IOC_SCRUB_CANCEL + IOCTL(BTRFS_IOC_SCRUB_CANCEL, 0, TYPE_NULL) +#endif +#ifdef BTRFS_IOC_SCRUB_PROGRESS + IOCTL(BTRFS_IOC_SCRUB_PROGRESS, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_scrub_args))) +#endif #ifdef BTRFS_IOC_DEV_INFO IOCTL(BTRFS_IOC_DEV_INFO, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_dev_info_args))) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 3f771ae5d1..589ec3e9b0 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -990,6 +990,12 @@ struct target_rtc_pll_info { 25, abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_SETFLAGSTARGET_IOW(BTRFS_IOCTL_MAGIC, \ 26, abi_ullong) +#define TARGET_BTRFS_IOC_SCRUB TARGET_IOWR(BTRFS_IOCTL_MAGIC,\ + 27, struct btrfs_ioctl_scrub_args) +#define TARGET_BTRFS_IOC_SCRUB_CANCEL TARGET_IO(BTRFS_IOCTL_MAGIC, \ + 28) +#define TARGET_BTRFS_IOC_SCRUB_PROGRESS TARGET_IOWR(BTRFS_IOCTL_MAGIC,\ + 29, struct btrfs_ioctl_scrub_args) #define TARGET_BTRFS_IOC_DEV_INFO TARGET_IOWR(BTRFS_IOCTL_MAGIC,\ 30, struct btrfs_ioctl_dev_info_args) #define TARGET_BTRFS_IOC_INO_PATHS TARGET_IOWR(BTRFS_IOCTL_MAGIC,\ diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index b4f462b5c6..345193270c 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -373,6 +373,32 @@ STRUCT(btrfs_ioctl_ino_lookup_user_args, MK_ARRAY(TYPE_CHAR, BTRFS_VOL_NAME_MAX + 1), /* name */ MK_ARRAY(TYPE_CHAR, BTRFS_INO_LOOKUP_USER_PATH_MAX)) /* path */ +STRUCT(btrfs_scrub_progress, + TYPE_ULONGLONG, /* data_extents_scrubbed */ + TYPE_ULONGLONG, /* tree_extents_scrubbed */ + TYPE_ULONGLONG, /* data_bytes_scrubbed */ + TYPE_ULONGLONG, /* tree_bytes_scrubbed */ + TYPE_ULONGLONG, /* read_errors */ + TYPE_ULONGLONG, /* csum_errors */ + TYPE_ULONGLONG, /* verify_errors */ + TYPE_ULONGLONG, /* no_csum */ + TYPE_ULONGLONG, /* csum_discards */ + TYPE_ULONGLONG, /* super_errors */ + TYPE_ULONGLONG, /* malloc_errors */ + TYPE_ULONGLONG, /* uncorrectable_errors */ + TYPE_ULONGLONG, /* corrected_er */ + TYPE_ULONGLONG, /* last_physical */ +
[PATCH 1/4] linux-user: Add support for a group of btrfs inode ioctls
This patch implements functionality of following ioctls: BTRFS_IOC_INO_LOOKUP - Reading tree root id and path Read tree root id and path for a given file or directory. The name and tree root id are returned in an ioctl's third argument that represents a pointer to a following type: struct btrfs_ioctl_ino_lookup_args { __u64 treeid; __u64 objectid; char name[BTRFS_INO_LOOKUP_PATH_MAX]; }; Before calling this ioctl, field 'objectid' should be filled with the object id value for which the tree id and path are to be read. Value 'BTRFS_FIRST_FREE_OBJECTID' represents the object id for the first available btrfs object (directory or file). BTRFS_IOC_INO_PATHS - Reading paths to all files Read path to all files with a certain inode number. The paths are returned in the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_ino_path_args { __u64 inum; /* in */ __u64 size; /* in */ __u64 reserved[4]; /* struct btrfs_data_container *fspath; out */ __u64 fspath; /* out */ }; Before calling this ioctl, the 'inum' and 'size' field should be filled with the aproppriate inode number and size of the directory where file paths should be looked for. For now, the paths are returned in an '__u64' (unsigned long long) value 'fspath'. BTRFS_IOC_LOGICAL_INO - Reading inode numbers Read inode numbers for files on a certain logical adress. The inode numbers are returned in the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_logical_ino_args { __u64 logical;/* in */ __u64 size; /* in */ __u64 reserved[3];/* must be 0 for now */ __u64 flags; /* in, v2 only */ /* struct btrfs_data_container *inodes;out */ __u64 inodes; }; Before calling this ioctl, the 'logical' and 'size' field should be filled with the aproppriate logical adress and size of where the inode numbers of files should be looked for. For now, the inode numbers are returned in an '__u64' (unsigned long long) value 'inodes'. BTRFS_IOC_LOGICAL_INO_V2 - Reading inode numbers Same as the above mentioned ioctl except that it allows passing a flags 'BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET'. BTRFS_IOC_INO_LOOKUP_USER - Reading subvolume name and path Read name and path of a subvolume. The tree root id and path are read in an ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_ino_lookup_user_args { /* in, inode number containing the subvolume of 'subvolid' */ __u64 dirid; /* in */ __u64 treeid; /* out, name of the subvolume of 'treeid' */ char name[BTRFS_VOL_NAME_MAX + 1]; /* * out, constructed path from the directory with which the ioctl is * called to dirid */ char path[BTRFS_INO_LOOKUP_USER_PATH_MAX]; }; Before calling this ioctl, the 'dirid' and 'treeid' field should be filled with aproppriate values which represent the inode number of the directory that contains the subvolume and treeid of the subvolume. Implementation notes: All of the ioctls in this patch use structure types as third arguments. That is the reason why aproppriate thunk definitions were added in file 'syscall_types.h'. --- linux-user/ioctls.h| 20 linux-user/syscall_defs.h | 10 ++ linux-user/syscall_types.h | 24 3 files changed, 54 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index c6303a0406..a7f5664487 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -202,6 +202,10 @@ IOCTL(BTRFS_IOC_SNAP_DESTROY, IOC_W, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_vol_args))) #endif +#ifdef BTRFS_IOC_INO_LOOKUP + IOCTL(BTRFS_IOC_INO_LOOKUP, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_args))) +#endif #ifdef BTRFS_IOC_SUBVOL_GETFLAGS IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG)) #endif @@ -212,6 +216,14 @@ IOCTL(BTRFS_IOC_DEV_INFO, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_dev_info_args))) #endif +#ifdef BTRFS_IOC_INO_PATHS + IOCTL(BTRFS_IOC_INO_PATHS, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_path_args))) +#endif +#ifdef BTRFS_IOC_LOGICAL_INO + IOCTL(BTRFS_IOC_LOGICAL_INO, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_logical_ino_args))) +#endif #ifdef
[PATCH 2/4] linux-user: Add support for two btrfs ioctls used for subvolume
This patch implements functionality for following ioctl: BTRFS_IOC_DEFAULT_SUBVOL - Setting a default subvolume Set a default subvolume for a btrfs filesystem. The third ioctl's argument is a '__u64' (unsigned long long) which represents the id of a subvolume that is to be set as the default. BTRFS_IOC_GET_SUBVOL_ROOTREF - Getting tree and directory id of subvolumes Read tree and directory id of subvolumes from a btrfs filesystem. The tree and directory id's are returned in the ioctl's third argument which represents a pointer to a following type: struct btrfs_ioctl_get_subvol_rootref_args { /* in/out, minimum id of rootref's treeid to be searched */ __u64 min_treeid; /* out */ struct { __u64 treeid; __u64 dirid; } rootref[BTRFS_MAX_ROOTREF_BUFFER_NUM]; /* out, number of found items */ __u8 num_items; __u8 align[7]; }; Before calling this ioctl, 'min_treeid' field should be filled with value that represent the minimum value for the tree id. Implementation notes: Ioctl BTRFS_IOC_GET_SUBVOL_ROOTREF uses the above mentioned structure type as third argument. That is the reason why a aproppriate thunk structure definition is added in file 'syscall_types.h'. --- linux-user/ioctls.h| 7 +++ linux-user/syscall_defs.h | 4 linux-user/syscall_types.h | 11 +++ 3 files changed, 22 insertions(+) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index a7f5664487..2c553103e6 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -206,6 +206,9 @@ IOCTL(BTRFS_IOC_INO_LOOKUP, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_args))) #endif +#ifdef BTRFS_IOC_DEFAULT_SUBVOL + IOCTL(BTRFS_IOC_DEFAULT_SUBVOL, IOC_W, MK_PTR(TYPE_ULONGLONG)) +#endif #ifdef BTRFS_IOC_SUBVOL_GETFLAGS IOCTL(BTRFS_IOC_SUBVOL_GETFLAGS, IOC_R, MK_PTR(TYPE_ULONGLONG)) #endif @@ -248,6 +251,10 @@ IOCTL(BTRFS_IOC_GET_SUBVOL_INFO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_subvol_info_args))) #endif +#ifdef BTRFS_IOC_GET_SUBVOL_ROOTREF + IOCTL(BTRFS_IOC_GET_SUBVOL_ROOTREF, IOC_RW, + MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_get_subvol_rootref_args))) +#endif #ifdef BTRFS_IOC_INO_LOOKUP_USER IOCTL(BTRFS_IOC_INO_LOOKUP_USER, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_btrfs_ioctl_ino_lookup_user_args))) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 7bb105428b..f4b4fc4a20 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -984,6 +984,8 @@ struct target_rtc_pll_info { 15, struct btrfs_ioctl_vol_args) #define TARGET_BTRFS_IOC_INO_LOOKUP TARGET_IOWR(BTRFS_IOCTL_MAGIC,\ 18, struct btrfs_ioctl_ino_lookup_args) +#define TARGET_BTRFS_IOC_DEFAULT_SUBVOL TARGET_IOW(BTRFS_IOCTL_MAGIC, \ + 19, abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_GETFLAGSTARGET_IOR(BTRFS_IOCTL_MAGIC, \ 25, abi_ullong) #define TARGET_BTRFS_IOC_SUBVOL_SETFLAGSTARGET_IOW(BTRFS_IOCTL_MAGIC, \ @@ -1006,6 +1008,8 @@ struct target_rtc_pll_info { 59, struct btrfs_ioctl_logical_ino_args) #define TARGET_BTRFS_IOC_GET_SUBVOL_INFOTARGET_IOR(BTRFS_IOCTL_MAGIC, \ 60, struct btrfs_ioctl_get_subvol_info_args) +#define TARGET_BTRFS_IOC_GET_SUBVOL_ROOTREF TARGET_IOWR(BTRFS_IOCTL_MAGIC,\ +61, struct btrfs_ioctl_get_subvol_rootref_args) #define TARGET_BTRFS_IOC_INO_LOOKUP_USERTARGET_IOWR(BTRFS_IOCTL_MAGIC,\ 62, struct btrfs_ioctl_ino_lookup_user_args) diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index 980c29000a..d2f1b30ff3 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -381,6 +381,17 @@ STRUCT(btrfs_ioctl_dev_info_args, MK_ARRAY(TYPE_ULONGLONG, 379), /* unused */ MK_ARRAY(TYPE_CHAR, BTRFS_DEVICE_PATH_NAME_MAX)) /* path */ +STRUCT(rootref, + TYPE_ULONGLONG, /* treeid */ + TYPE_ULONGLONG) /* dirid */ + +STRUCT(btrfs_ioctl_get_subvol_rootref_args, +TYPE_ULONGLONG, /* min_treeid */ +MK_ARRAY(MK_STRUCT(STRUCT_rootref), + BTRFS_MAX_ROOTREF_BUFFER_NUM), /* rootref */ +TYPE_CHAR, /* num_items */ +MK_ARRAY(TYPE_CHAR, 7)) /* align */ + STRUCT(btrfs_ioctl_get_dev_stats, TYPE_ULONGLONG, /* devid */ TYPE_ULONGLONG, /* nr_items */ -- 2.25.1
[PATCH] linux-user: Add strace support for printing arguments for ioctls used for terminals and serial lines
Functions "print_ioctl()" and "print_syscall_ret_ioctl()" are used to print arguments of "ioctl()" with "-strace". These functions use "thunk_print()", which is defined in "thunk.c", to print the contents of ioctl's third arguments that are not basic types. However, this function doesn't handle ioctls of group ioctl_tty which are used for terminals and serial lines. These ioctls use a type "struct termios" which thunk type is defined in a non standard way using "STRUCT_SPECIAL()". This means that this type is not decoded regularly using "thunk_convert()" and uses special converting functions "target_to_host_termios()" and "host_to_target_termios()", which are defined in "syscall.c" to decode it's values. For simillar reasons, this type is also not printed regularly using "thunk_print()". That is the reason why a separate printing function "print_termios()" is defined in file "strace.c". This function decodes and prints flag values of the "termios" structure. Implementation notes: Function "print_termios()" was implemented in "strace.c" using an existing function "print_flags()" to print flag values of "struct termios" fields. These flag values were defined using an existing macro "FLAG_TARGET()" that generates aproppriate target flag values and string representations of these flags. This function was declared in "qemu.h" so that it can be accessed in "syscall.c". Type "StructEntry" defined in "exec/user/thunk.h" contains information that is used to decode structure values. Field "void print(void *arg)" was added in this structure as a special print function. Also, function "thunk_print()" was changed a little so that it uses this special print function in case it is defined. This printing function was instantiated with the defined "print_termios()" in "syscall.c" in "struct_termios_def". Signed-off-by: Filip Bozuta --- include/exec/user/thunk.h | 1 + linux-user/qemu.h | 2 + linux-user/strace.c | 193 ++ linux-user/syscall.c | 1 + thunk.c | 23 +++-- 5 files changed, 211 insertions(+), 9 deletions(-) diff --git a/include/exec/user/thunk.h b/include/exec/user/thunk.h index 7992475c9f..a5bbb2c733 100644 --- a/include/exec/user/thunk.h +++ b/include/exec/user/thunk.h @@ -55,6 +55,7 @@ typedef struct { int *field_offsets[2]; /* special handling */ void (*convert[2])(void *dst, const void *src); +void (*print)(void *arg); int size[2]; int align[2]; const char *name; diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 5c964389c1..e51a0ededb 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -706,6 +706,8 @@ static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) } #endif /* TARGET_ABI_BITS != 32 */ +extern void print_termios(void *arg); + /** * preexit_cleanup: housekeeping before the guest exits * diff --git a/linux-user/strace.c b/linux-user/strace.c index 5235b2260c..7b5408cf4a 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1193,6 +1193,138 @@ UNUSED static struct flags falloc_flags[] = { #endif }; +UNUSED static struct flags termios_iflags[] = { +FLAG_TARGET(IGNBRK), +FLAG_TARGET(BRKINT), +FLAG_TARGET(IGNPAR), +FLAG_TARGET(PARMRK), +FLAG_TARGET(INPCK), +FLAG_TARGET(ISTRIP), +FLAG_TARGET(INLCR), +FLAG_TARGET(IGNCR), +FLAG_TARGET(ICRNL), +FLAG_TARGET(IUCLC), +FLAG_TARGET(IXON), +FLAG_TARGET(IXANY), +FLAG_TARGET(IXOFF), +FLAG_TARGET(IMAXBEL), +FLAG_END, +}; + +UNUSED static struct flags termios_oflags[] = { +FLAG_TARGET(OPOST), +FLAG_TARGET(OLCUC), +FLAG_TARGET(ONLCR), +FLAG_TARGET(OCRNL), +FLAG_TARGET(ONOCR), +FLAG_TARGET(ONLRET), +FLAG_TARGET(OFILL), +FLAG_TARGET(OFDEL), +FLAG_END, +}; + +UNUSED static struct flags termios_oflags_NLDLY[] = { +FLAG_TARGET(NL0), +FLAG_TARGET(NL1), +FLAG_END, +}; + +UNUSED static struct flags termios_oflags_CRDLY[] = { +FLAG_TARGET(CR0), +FLAG_TARGET(CR1), +FLAG_TARGET(CR2), +FLAG_TARGET(CR3), +FLAG_END, +}; + +UNUSED static struct flags termios_oflags_TABDLY[] = { +FLAG_TARGET(TAB0), +FLAG_TARGET(TAB1), +FLAG_TARGET(TAB2), +FLAG_TARGET(TAB3), +FLAG_END, +}; + +UNUSED static struct flags termios_oflags_VTDLY[] = { +FLAG_TARGET(VT0), +FLAG_TARGET(VT1), +FLAG_END, +}; + +UNUSED static struct flags termios_oflags_FFDLY[] = { +FLAG_TARGET(FF0), +FLAG_TARGET(FF1), +FLAG_END, +}; + +UNUSED static struct flags termios_oflags_BSDLY[] = { +FLAG_TARGET(BS0), +FLAG_TARGET(BS1), +FLAG_
[PATCH v2 0/4] Add strace support for printing arguments for a group of selected syscalls
This series covers strace support for following syscalls: *truncate() *munlock() *clock_gettimeofday() *ftruncate()*munlockall() *clock_getitimer() *getsid() *clock_getres() *clock_setitimer() *mlock()*clock_gettime() *mlockall() *clock_settime() Testing method: Mini test programs were written that run these syscalls for different arguments. Those programs were compiled (sometimes using cross-compilers) for the following architectures: * Intel 64-bit (little endian) (gcc) * Power pc 32-bit (big endian) (powerpc-linux-gnu-gcc) * Power pc 64-bit (big endian) (powerpc64-linux-gnu-gcc) The corresponding native programs were executed with strace, without using QEMU, on intel (x86_64) host. All applicable compiled programs were in turn executed with "-strace" through QEMU and the strace printing results obtained were the same ones gotten for native execution. v2: * added patch that enables 'cpu_env' to be accessible from "strace.c" * cut and pasted "regpairs_aligned" from 'syscall.c' to 'qemu.h' so that it can be used for "print_truncate64" and "print_ftruncate64" * changed flag names from 'TARGET_MLOCKALL_MCL_*' to 'TARGET_MCL_*' * added target flag value 'TARGET_MCL_ONFAULT' for 'MCL_ONFAULT' * added 'print_syscall_ret_setitimer' for old value of the interval timer * added a function 'print_itimer_type' that prints the interval timer type Filip Bozuta (4): linux-user: Make cpu_env accessible in strace.c linux-user: Add strace support for printing arguments of truncate()/ftruncate() and getsid() linux-user: Add strace support for printing arguments of syscalls used to lock and unlock memory linux-user: Add strace support for printing arguments of some clock and time functions linux-user/aarch64/target_syscall.h| 5 +- linux-user/alpha/target_syscall.h | 5 +- linux-user/arm/target_syscall.h| 6 +- linux-user/cris/target_syscall.h | 5 +- linux-user/hppa/target_syscall.h | 5 +- linux-user/i386/target_syscall.h | 5 +- linux-user/m68k/target_syscall.h | 6 +- linux-user/microblaze/target_syscall.h | 5 +- linux-user/mips/target_syscall.h | 5 +- linux-user/mips64/target_syscall.h | 5 +- linux-user/nios2/target_syscall.h | 5 +- linux-user/openrisc/target_syscall.h | 5 +- linux-user/ppc/target_syscall.h| 5 +- linux-user/qemu.h | 39 +- linux-user/riscv/target_syscall.h | 5 +- linux-user/s390x/target_syscall.h | 5 +- linux-user/sh4/target_syscall.h| 5 +- linux-user/sparc/target_syscall.h | 5 +- linux-user/sparc64/target_syscall.h| 5 +- linux-user/strace.c| 755 + linux-user/strace.list | 35 +- linux-user/syscall.c | 47 +- linux-user/tilegx/target_syscall.h | 5 +- linux-user/x86_64/target_syscall.h | 5 +- linux-user/xtensa/target_syscall.h | 5 +- 25 files changed, 648 insertions(+), 335 deletions(-) -- 2.25.1
[PATCH v2 4/4] linux-user: Add strace support for printing arguments of some clock and time functions
This patch implements strace argument printing functionality for following syscalls: * clock_getres, clock_gettime, clock_settime - clock and time functions int clock_getres(clockid_t clockid, struct timespec *res) int clock_gettime(clockid_t clockid, struct timespec *tp) int clock_settime(clockid_t clockid, const struct timespec *tp) man page: https://man7.org/linux/man-pages/man2/clock_getres.2.html * gettimeofday - get time int gettimeofday(struct timeval *tv, struct timezone *tz) man page: https://man7.org/linux/man-pages/man2/gettimeofday.2.html * getitimer, setitimer - get or set value of an interval timer int getitimer(int which, struct itimerval *curr_value) int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value) man page: https://man7.org/linux/man-pages/man2/getitimer.2.html Implementation notes: All of the syscalls have some structue types as argument types and thus a separate printing function was stated in file "strace.list" for each of them. All of these functions use existing functions for their appropriate structure types ("print_timeval()" and "print_timezone()"). Functions "print_timespec()" and "print_itimerval()" were added in this patch so that they can be used to print types "struct timespec" and "struct itimerval" used by some of the syscalls. Function "print_itimerval()" uses the existing function "print_timeval()" to print fields of the structure "struct itimerval" that are of type "struct timeval". Function "print_itimer_type()" was added to print the type of the interval typer which is the firt argument of "getitimer()" and "setitimer()". Also, the existing function "print_timeval()" was changed a little so that it prints the field names beside the values. Syscalls "clock_getres()" and "clocK_gettime()" have the same number and types of arguments and thus their print functions "print_clock_getres" and "print_clock_gettime" shate a common definition in file "strace.c". Signed-off-by: Filip Bozuta --- linux-user/strace.c| 208 - linux-user/strace.list | 17 ++-- 2 files changed, 217 insertions(+), 8 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 0d95cc6089..9bdee3b495 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -64,7 +64,10 @@ UNUSED static void print_string(abi_long, int); UNUSED static void print_buf(abi_long addr, abi_long len, int last); UNUSED static void print_raw_param(const char *, abi_long, int); UNUSED static void print_timeval(abi_ulong, int); +UNUSED static void print_timespec(abi_ulong, int); UNUSED static void print_timezone(abi_ulong, int); +UNUSED static void print_itimer_type(abi_ulong, int); +UNUSED static void print_itimerval(abi_ulong, int); UNUSED static void print_number(abi_long, int); UNUSED static void print_signal(abi_ulong, int); UNUSED static void print_sockaddr(abi_ulong, abi_long, int); @@ -829,6 +832,89 @@ print_syscall_ret_adjtimex(void *cpu_env, const struct syscallname *name, } #endif +#if defined(TARGET_NR_clock_gettime) || defined(TARGET_NR_clock_getres) +static void +print_syscall_ret_clock_gettime(void *cpu_env, const struct syscallname *name, +abi_long ret, abi_long arg0, abi_long arg1, +abi_long arg2, abi_long arg3, abi_long arg4, +abi_long arg5) +{ +print_syscall_err(ret); + +if (ret >= 0) { +qemu_log(TARGET_ABI_FMT_ld, ret); +qemu_log(" ("); +print_timespec(arg1, 1); +qemu_log(")"); +} + +qemu_log("\n"); +} +#define print_syscall_ret_clock_getres print_syscall_ret_clock_gettime +#endif + +#ifdef TARGET_NR_gettimeofday +static void +print_syscall_ret_gettimeofday(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) +{ +print_syscall_err(ret); + +if (ret >= 0) { +qemu_log(TARGET_ABI_FMT_ld, ret); +qemu_log(" ("); +print_timeval(arg0, 0); +print_timezone(arg1, 1); +qemu_log(")"); +} + +qemu_log("\n"); +} +#endif + +#ifdef TARGET_NR_getitimer +static void +print_syscall_ret_getitimer(void *cpu_env, const struct syscallname *name, +abi_long ret, abi_long arg0, abi_long arg1, +abi_long arg2, abi_long arg3, abi_long arg4,
[PATCH v2 3/4] linux-user: Add strace support for printing arguments of syscalls used to lock and unlock memory
This patch implements strace argument printing functionality for following syscalls: * mlock, munlock, mlockall, munlockall - lock and unlock memory int mlock(const void *addr, size_t len) int munlock(const void *addr, size_t len) int mlockall(int flags) int munlockall(void) man page: https://man7.org/linux/man-pages/man2/mlock.2.html Implementation notes: Syscall mlockall() takes an argument that is composed of predefined values which represent flags that determine the type of locking operation that is to be performed. For that reason, a printing function "print_mlockall" was stated in file "strace.list". This printing function uses an already existing function "print_flags()" to print the "flags" argument. These flags are stated inside an array "mlockall_flags" that contains values of type "struct flags". These values are instantiated using an existing macro "FLAG_TARGET()" that crates aproppriate target flag values based on those defined in files '/target_syscall.h'. These target flag values were changed from "TARGET_MLOCKALL_MCL*" to "TARGET_MCL_*" so that they can be aproppriately set and recognised in "strace.c" with "FLAG_TARGET()". Value for "MCL_ONFAULT" was added in this patch. This value was also added in "syscall.c" in function "target_to_host_mlockall_arg()". Because this flag value was added in kernel version 4.4, it is enwrapped in an #ifdef directive (both in "syscall.c" and in "strace.c") as to support older kernel versions. The other syscalls have only primitive argument types, so the rest of the implementation was handled by stating an appropriate printing format in file "strace.list". Syscall mlock2() is not implemented in "syscall.c" and thus it's argument printing is not implemented in this patch. Signed-off-by: Filip Bozuta --- linux-user/aarch64/target_syscall.h| 5 +++-- linux-user/alpha/target_syscall.h | 5 +++-- linux-user/arm/target_syscall.h| 6 -- linux-user/cris/target_syscall.h | 5 +++-- linux-user/hppa/target_syscall.h | 5 +++-- linux-user/i386/target_syscall.h | 5 +++-- linux-user/m68k/target_syscall.h | 6 +++--- linux-user/microblaze/target_syscall.h | 5 +++-- linux-user/mips/target_syscall.h | 5 +++-- linux-user/mips64/target_syscall.h | 5 +++-- linux-user/nios2/target_syscall.h | 5 +++-- linux-user/openrisc/target_syscall.h | 5 +++-- linux-user/ppc/target_syscall.h| 5 +++-- linux-user/riscv/target_syscall.h | 5 +++-- linux-user/s390x/target_syscall.h | 5 +++-- linux-user/sh4/target_syscall.h| 5 +++-- linux-user/sparc/target_syscall.h | 5 +++-- linux-user/sparc64/target_syscall.h| 5 +++-- linux-user/strace.c| 21 + linux-user/strace.list | 8 linux-user/syscall.c | 10 -- linux-user/tilegx/target_syscall.h | 5 +++-- linux-user/x86_64/target_syscall.h | 5 +++-- linux-user/xtensa/target_syscall.h | 5 +++-- 24 files changed, 97 insertions(+), 49 deletions(-) diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h index 995e475c73..3194e6b009 100644 --- a/linux-user/aarch64/target_syscall.h +++ b/linux-user/aarch64/target_syscall.h @@ -16,8 +16,9 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "3.8.0" #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 #define TARGET_PR_SVE_SET_VL 50 #define TARGET_PR_SVE_GET_VL 51 diff --git a/linux-user/alpha/target_syscall.h b/linux-user/alpha/target_syscall.h index 3426cc5b4e..fd389422e3 100644 --- a/linux-user/alpha/target_syscall.h +++ b/linux-user/alpha/target_syscall.h @@ -258,7 +258,8 @@ struct target_pt_regs { #define TARGET_UAC_NOFIX 2 #define TARGET_UAC_SIGBUS 4 #define TARGET_MINSIGSTKSZ 4096 -#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 -#define TARGET_MLOCKALL_MCL_FUTURE 0x4000 +#define TARGET_MCL_CURRENT 0x2000 +#define TARGET_MCL_FUTURE 0x4000 +#define TARGET_MCL_ONFAULT 0x8000 #endif /* ALPHA_TARGET_SYSCALL_H */ diff --git a/linux-user/arm/target_syscall.h b/linux-user/arm/target_syscall.h index f85cbdaf56..e870ed7a54 100644 --- a/linux-user/arm/target_syscall.h +++ b/linux-user/arm/target_syscall.h @@ -28,8 +28,10 @@ struct target_pt_regs { #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_MLOCKALL_MCL_CURRENT 1 -#define TARGET_MLOCKALL_M
[PATCH v2 1/4] linux-user: Make cpu_env accessible in strace.c
Variable "cpu_env" is used in file "syscall.c" to store the information about the cpu environment. This variable is used because values of some syscalls can vary between cpu architectures. This patch makes the "cpu_env" accessible in "strace.c" so it can enable aproppriate "-strace" argument printing for these syscalls. This will be a useful addition for future "-strace" implementation in QEMU. Implementation notes: Functions "print_syscall()" and "print_syscall_ret()" which are stated and defined in "qemu.h" and "strace.c" respectively are used to print syscall arguments before and after syscall execution. These functions were changed with addition of a new argument "void *cpu_env". Strucute "struct syscallname" in "strace.c" is used to store the information about syscalls. Fields "call" and "result" represent pointers to functions which are used to print syscall arguments before and after execution. These fields were also changed with addition of a new "void *" argumetn. Also, all defined "print_*" and "print_syscall_ret*" functions in "strace.c" were changed to have the new "void *cpu_env". This was done to not cause build errors (even though none of these functions use this argument). Signed-off-by: Filip Bozuta --- linux-user/qemu.h| 4 +- linux-user/strace.c | 479 ++- linux-user/syscall.c | 5 +- 3 files changed, 247 insertions(+), 241 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 5c964389c1..63ddfe86fd 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -400,10 +400,10 @@ extern long safe_syscall_base(int *pending, long number, ...); int host_to_target_waitstatus(int status); /* strace.c */ -void print_syscall(int num, +void print_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6); -void print_syscall_ret(int num, abi_long ret, +void print_syscall_ret(void *cpu_env, int num, abi_long ret, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6); /** diff --git a/linux-user/strace.c b/linux-user/strace.c index 5235b2260c..ff3d584ccc 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -16,10 +16,10 @@ struct syscallname { int nr; const char *name; const char *format; -void (*call)(const struct syscallname *, +void (*call)(void *, const struct syscallname *, abi_long, abi_long, abi_long, abi_long, abi_long, abi_long); -void (*result)(const struct syscallname *, abi_long, +void (*result)(void *, const struct syscallname *, abi_long, abi_long, abi_long, abi_long, abi_long, abi_long, abi_long); }; @@ -634,7 +634,7 @@ print_clockid(int clockid, int last) /* select */ #ifdef TARGET_NR__newselect static void -print_newselect(const struct syscallname *name, +print_newselect(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -652,7 +652,7 @@ print_newselect(const struct syscallname *name, #ifdef TARGET_NR_semctl static void -print_semctl(const struct syscallname *name, +print_semctl(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -664,7 +664,7 @@ print_semctl(const struct syscallname *name, #endif static void -print_execve(const struct syscallname *name, +print_execve(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -697,7 +697,7 @@ print_execve(const struct syscallname *name, #ifdef TARGET_NR_ipc static void -print_ipc(const struct syscallname *name, +print_ipc(void *cpu_env, const struct syscallname *name, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { @@ -740,9 +740,10 @@ print_syscall_err(abi_long ret) } static void -print_syscall_ret_addr(const struct syscallname *name, abi_long ret, - abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) +print_syscall_ret_addr(void *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) { print_syscall_err(ret); @
[PATCH v2 2/4] linux-user: Add strace support for printing arguments of truncate()/ftruncate() and getsid()
This patch implements strace argument printing functionality for following syscalls: * truncate, ftruncate - truncate a file to a specified length int truncate/truncate64(const char *path, off_t length) int ftruncate/ftruncate64(int fd, off_t length) man page: https://man7.org/linux/man-pages/man2/truncate.2.html * getsid - get session ID pid_t getsid(pid_t pid) man page: https://man7.org/linux/man-pages/man2/getsid.2.html Implementation notes: Syscalls truncate/truncate64 take string argument types and thus a separate print function "print_truncate/print_truncate64" is stated in file "strace.list". This function is defined and implemented in "strace.c" by using an existing function used to print string arguments: "print_string()". For syscall ftruncate64, a separate printing function was also stated in "strace.c" as it requires a special kind of handling. The other syscalls have only primitive argument types, so the rest of the implementation was handled by stating an appropriate printing format in file "strace.list". Function "regpairs_aligned()" was cut & pasted from "syscall.c" to "qemu.h" as it is used by functions "print_truncate64()" and "print_ftruncate64()" to print the offset arguments of "truncate64()" and "ftruncate64()". Signed-off-by: Filip Bozuta --- linux-user/qemu.h | 35 +++ linux-user/strace.c| 47 ++ linux-user/strace.list | 10 - linux-user/syscall.c | 32 4 files changed, 87 insertions(+), 37 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 63ddfe86fd..f431805e57 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -706,6 +706,41 @@ static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) } #endif /* TARGET_ABI_BITS != 32 */ + +/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ +#ifdef TARGET_ARM +static inline int regpairs_aligned(void *cpu_env, int num) +{ +return CPUARMState *)cpu_env)->eabi) == 1) ; +} +#elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32) +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#elif defined(TARGET_PPC) && !defined(TARGET_PPC64) +/* + * SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs + * of registers which translates to the same as ARM/MIPS, because we start with + * r3 as arg1 + */ +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#elif defined(TARGET_SH4) +/* SH4 doesn't align register pairs, except for p{read,write}64 */ +static inline int regpairs_aligned(void *cpu_env, int num) +{ +switch (num) { +case TARGET_NR_pread64: +case TARGET_NR_pwrite64: +return 1; + +default: +return 0; +} +} +#elif defined(TARGET_XTENSA) +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#else +static inline int regpairs_aligned(void *cpu_env, int num) { return 0; } +#endif + /** * preexit_cleanup: housekeeping before the guest exits * diff --git a/linux-user/strace.c b/linux-user/strace.c index ff3d584ccc..ce02f62efc 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1962,6 +1962,53 @@ print_lseek(void *cpu_env, const struct syscallname *name, } #endif +#ifdef TARGET_NR_truncate +static void +print_truncate(void *cpu_env, 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_string(arg0, 0); +print_raw_param(TARGET_ABI_FMT_ld, arg1, 1); +print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_truncate64 +static void +print_truncate64(void *cpu_env, 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_string(arg0, 0); +if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) { +arg1 = arg2; +arg2 = arg3; +} +print_raw_param("%" PRIu64, target_offset64(arg1, arg2), 1); +print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_ftruncate64 +static void +print_ftruncate64(void *cpu_env, 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_raw_param("%d", arg0, 0); +if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) { +arg1 = arg2; +arg2 = arg3; +} +print_raw_param("%" PRIu64, target_offset64(arg1, arg2), 1); +pr
Re: [PATCH v2 1/2] linux-user: fix the errno value in print_syscall_err()
On 8.7.20. 17:24, Laurent Vivier wrote: errno of the target is returned as a negative value by the syscall, not in the host errno variable. The emulation of the target syscall can return an error while the host doesn't set an errno value. Target errnos and host errnos can also differ in some cases. Fixes: c84be71f6854 ("linux-user: Extend strace support to enable argument printing after syscall execution") Cc: filip.boz...@syrmia.com Signed-off-by: Laurent Vivier --- linux-user/strace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 5235b2260cdd..b42664bbd180 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -731,7 +731,7 @@ print_syscall_err(abi_long ret) qemu_log(" = "); if (ret < 0) { -qemu_log("-1 errno=%d", errno); +qemu_log("-1 errno=%d", (int)-ret); errstr = target_strerror(-ret); if (errstr) { qemu_log(" (%s)", errstr); Reviewed-by: Filip Bozuta
[PATCH 0/4] Add support for a group of btrfs filesystem ioctl
This series covers support for following btrfs ioctls *BTRFS_SUBVOL_CREATE *BTRFS_IOC_ADD_DEV *BTRFS_SUBVOL_SETFLAGS*BTRFS_IOC_RM_DEV *BTRFS_SUBVOL_GETFLAGS*BTRFS_IOC_DEV_INFO *BTRFS_GET_SUBVOL_INFO*BTRFS_IOC_GET_DEV_STATS *BTRFS_IOC_SNAP_CREATE*BTRFS_IOC_GET_FEATURES *BTRFS_IOC_SNAP_DESTROY *BTRFS_IOC_SET_FEATURES *BTRFS_IOC_SCAN_DEV *BTRFS_IOC_GET_SUPPORTED_FEATURES The functionalities of individual ioctls were described in this series patch commit messages. Since all of these ioctls are added in kernel version 3.9, their definitions in file 'linux-user/ioctls.h' are enwrapped in an #ifdef directive. Testing method: Mini test programs were written for these ioctls. These test programs can be found on a repositort which is located on the link: https://github.com/bozutaf/btrfs-tests These test programs were compiled (sometimes using cross compilers) for following architectures: * Intel 64-bit (little endian) * Power pc 32-bit (big endian) * Power pc 64-bit (big endian) The corresponding native programs were executed without using QEMU on an intel x86_64 host. All applicable compiled programs were in turn executed through QEMU and the results obtained were the same ones gotten for native execution. Filip Bozuta (4): linux-user: Add support for a group of btrfs ioctls used for subvolumes linux-user: Add support for a group of btrfs ioctls used for snapshots linux-user: Add support for btrfs ioctls used to manipulate with devices linux-user: Add support for btrfs ioctls used to get/set features configure | 9 ++ linux-user/ioctls.h| 59 ++ linux-user/syscall.c | 3 ++ linux-user/syscall_defs.h | 32 + linux-user/syscall_types.h | 49 +++ 5 files changed, 152 insertions(+) -- 2.25.1