[PATCH] linux-user: Protect btrfs ioctl target definitions

2020-09-05 Thread Filip Bozuta
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

2020-09-01 Thread Filip Bozuta



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()

2020-08-27 Thread Filip Bozuta

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

2020-08-25 Thread Filip Bozuta
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()'

2020-08-25 Thread Filip Bozuta
   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()'

2020-08-25 Thread Filip Bozuta
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()

2020-08-24 Thread Filip Bozuta
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

2020-08-24 Thread Filip Bozuta
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()

2020-08-24 Thread Filip Bozuta
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()'

2020-08-24 Thread Filip Bozuta
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()'

2020-08-24 Thread Filip Bozuta
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

2020-08-24 Thread Filip Bozuta
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

2020-08-24 Thread Filip Bozuta
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()'

2020-08-24 Thread Filip Bozuta
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()'

2020-08-24 Thread Filip Bozuta
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

2020-08-23 Thread Filip Bozuta
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

2020-08-23 Thread Filip Bozuta
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

2020-08-23 Thread Filip Bozuta
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

2020-08-23 Thread Filip Bozuta
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

2020-08-23 Thread Filip Bozuta
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

2020-08-23 Thread Filip Bozuta
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

2020-08-23 Thread Filip Bozuta
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

2020-08-23 Thread Filip Bozuta
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

2020-08-23 Thread Filip Bozuta
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

2020-08-23 Thread Filip Bozuta
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

2020-08-21 Thread Filip Bozuta

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

2020-08-18 Thread Filip Bozuta
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

2020-08-17 Thread Filip Bozuta
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

2020-08-12 Thread Filip Bozuta
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

2020-08-12 Thread Filip Bozuta
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()'

2020-08-12 Thread Filip Bozuta
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()'

2020-08-12 Thread Filip Bozuta
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

2020-08-11 Thread Filip Bozuta
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

2020-08-11 Thread Filip Bozuta
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

2020-08-11 Thread Filip Bozuta
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

2020-08-11 Thread Filip Bozuta
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

2020-08-11 Thread Filip Bozuta
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()

2020-08-11 Thread Filip Bozuta
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

2020-08-11 Thread Filip Bozuta
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

2020-08-03 Thread Filip Bozuta
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

2020-08-03 Thread Filip Bozuta
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

2020-08-03 Thread Filip Bozuta
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

2020-08-03 Thread Filip Bozuta
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

2020-08-03 Thread Filip Bozuta
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

2020-08-03 Thread Filip Bozuta
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

2020-08-03 Thread Filip Bozuta
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

2020-08-03 Thread Filip Bozuta
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

2020-08-03 Thread Filip Bozuta
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

2020-07-31 Thread Filip Bozuta
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

2020-07-31 Thread Filip Bozuta
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()'

2020-07-31 Thread Filip Bozuta
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()'

2020-07-31 Thread Filip Bozuta
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

2020-07-31 Thread Filip Bozuta



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

2020-07-31 Thread Filip Bozuta

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

2020-07-27 Thread Filip Bozuta
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()'

2020-07-27 Thread Filip Bozuta
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

2020-07-27 Thread Filip Bozuta
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()'

2020-07-27 Thread Filip Bozuta
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()'

2020-07-26 Thread Filip Bozuta
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()'

2020-07-26 Thread Filip Bozuta
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

2020-07-26 Thread Filip Bozuta
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()'

2020-07-25 Thread Filip Bozuta
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

2020-07-25 Thread Filip Bozuta
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()'

2020-07-25 Thread Filip Bozuta
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()'

2020-07-25 Thread Filip Bozuta
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

2020-07-24 Thread Filip Bozuta
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'

2020-07-23 Thread Filip Bozuta
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

2020-07-23 Thread Filip Bozuta
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

2020-07-23 Thread Filip Bozuta
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

2020-07-23 Thread Filip Bozuta
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

2020-07-22 Thread Filip Bozuta
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

2020-07-22 Thread Filip Bozuta
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

2020-07-22 Thread Filip Bozuta
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

2020-07-22 Thread Filip Bozuta
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

2020-07-22 Thread Filip Bozuta
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()

2020-07-22 Thread Filip Bozuta
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

2020-07-22 Thread Filip Bozuta
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

2020-07-22 Thread Filip Bozuta
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()'

2020-07-22 Thread Filip Bozuta
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

2020-07-22 Thread Filip Bozuta
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

2020-07-22 Thread Filip Bozuta
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()'

2020-07-22 Thread Filip Bozuta
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

2020-07-17 Thread Filip Bozuta
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

2020-07-17 Thread Filip Bozuta
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

2020-07-17 Thread Filip Bozuta
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

2020-07-17 Thread Filip Bozuta
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

2020-07-17 Thread Filip Bozuta
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

2020-07-17 Thread Filip Bozuta
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

2020-07-17 Thread Filip Bozuta
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

2020-07-17 Thread Filip Bozuta
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

2020-07-17 Thread Filip Bozuta
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

2020-07-17 Thread Filip Bozuta
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

2020-07-14 Thread Filip Bozuta
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

2020-07-13 Thread Filip Bozuta
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

2020-07-13 Thread Filip Bozuta
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

2020-07-13 Thread Filip Bozuta
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

2020-07-13 Thread Filip Bozuta
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()

2020-07-13 Thread Filip Bozuta
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()

2020-07-10 Thread Filip Bozuta



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

2020-07-09 Thread Filip Bozuta
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




  1   2   3   >