diff mbox

[v5,4/8] linux-user: Add support for ustat() syscall

Message ID 20160914202008.14119-5-aleksandar.markovic@rt-rk.com (mailing list archive)
State New, archived
Headers show

Commit Message

Aleksandar Markovic Sept. 14, 2016, 8:19 p.m. UTC
From: Aleksandar Markovic <aleksandar.markovic@imgtec.com>

This patch implements Qemu user mode ustat() syscall support.

Syscall ustat() returns information about a mounted filesystem.

The implementation is similar to the implementations of statfs(),
fstatfs() and other related syscalls. It is based on invocation of
host's ustat(), and its key part is in the correspondent case segment
of the main switch statement of the function do_syscall(), in file
linux-user/syscalls.c. All necessary conversions of data structures
from target to host and from host to target are covered. Sufficient
support for "-strace" option for this syscall is already present,
and this patch does not change it.

This patch also fixes failures of LTP tests ustat01, and ustat02, if
executed on Qemu-emulated systems.

Signed-off-by: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
---
 linux-user/syscall.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

Comments

Laurent Vivier Sept. 17, 2016, 11:39 p.m. UTC | #1
Le 14/09/2016 à 22:19, Aleksandar Markovic a écrit :
> From: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
> 
> This patch implements Qemu user mode ustat() syscall support.
> 
> Syscall ustat() returns information about a mounted filesystem.
> 
> The implementation is similar to the implementations of statfs(),
> fstatfs() and other related syscalls. It is based on invocation of
> host's ustat(), and its key part is in the correspondent case segment
> of the main switch statement of the function do_syscall(), in file
> linux-user/syscalls.c. All necessary conversions of data structures
> from target to host and from host to target are covered. Sufficient
> support for "-strace" option for this syscall is already present,
> and this patch does not change it.
> 
> This patch also fixes failures of LTP tests ustat01, and ustat02, if
> executed on Qemu-emulated systems.
> 
> Signed-off-by: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
> ---
>  linux-user/syscall.c | 25 ++++++++++++++++++++++++-
>  1 file changed, 24 insertions(+), 1 deletion(-)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 3436ee6..7f8ae41 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -48,6 +48,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
>  #include <sys/shm.h>
>  #include <sys/sem.h>
>  #include <sys/statfs.h>
> +#include <ustat.h>
>  #include <utime.h>
>  #include <sys/sysinfo.h>
>  #include <sys/signalfd.h>
> @@ -8098,7 +8099,29 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>          break;
>  #ifdef TARGET_NR_ustat
>      case TARGET_NR_ustat:
> -        goto unimplemented;
> +    {
> +        struct ustat ust;
> +        int cnt;
> +        ret = get_errno(ustat(arg1, &ust));
> +
> +        if (!is_error(ret)) {
> +            struct ustat *target_ust;

You must define your own "struct target_ustat" as __kernel_daddr_t and
__kernel_ino_t are long (or int).

> +
> +            if (!lock_user_struct(VERIFY_WRITE, target_ust, arg2, 0)) {
> +                goto efault;
> +            }
> +
> +            __put_user(ust.f_tfree, &target_ust->f_tfree);
> +            __put_user(ust.f_tinode, &target_ust->f_tinode);
> +
> +            for (cnt = 0; cnt < 6; cnt++) {
> +                __put_user(ust.f_fname[cnt], &target_ust->f_fname[cnt]);
> +                __put_user(ust.f_fpack[cnt], &target_ust->f_fpack[cnt]);
> +            }

As the structure is locked and they are "char", you can do memcpy().

> +            unlock_user_struct(target_ust, arg2, 1);
> +        }
> +        break;
> +      }
>  #endif
>  #ifdef TARGET_NR_dup2
>      case TARGET_NR_dup2:
> 

Laurent
diff mbox

Patch

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 3436ee6..7f8ae41 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -48,6 +48,7 @@  int __clone2(int (*fn)(void *), void *child_stack_base,
 #include <sys/shm.h>
 #include <sys/sem.h>
 #include <sys/statfs.h>
+#include <ustat.h>
 #include <utime.h>
 #include <sys/sysinfo.h>
 #include <sys/signalfd.h>
@@ -8098,7 +8099,29 @@  abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #ifdef TARGET_NR_ustat
     case TARGET_NR_ustat:
-        goto unimplemented;
+    {
+        struct ustat ust;
+        int cnt;
+        ret = get_errno(ustat(arg1, &ust));
+
+        if (!is_error(ret)) {
+            struct ustat *target_ust;
+
+            if (!lock_user_struct(VERIFY_WRITE, target_ust, arg2, 0)) {
+                goto efault;
+            }
+
+            __put_user(ust.f_tfree, &target_ust->f_tfree);
+            __put_user(ust.f_tinode, &target_ust->f_tinode);
+
+            for (cnt = 0; cnt < 6; cnt++) {
+                __put_user(ust.f_fname[cnt], &target_ust->f_fname[cnt]);
+                __put_user(ust.f_fpack[cnt], &target_ust->f_fpack[cnt]);
+            }
+            unlock_user_struct(target_ust, arg2, 1);
+        }
+        break;
+      }
 #endif
 #ifdef TARGET_NR_dup2
     case TARGET_NR_dup2: