[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 1/7] linux-user: Add fanotify implementation
From: |
Lena Djokic |
Subject: |
[Qemu-devel] [PATCH v2 1/7] linux-user: Add fanotify implementation |
Date: |
Thu, 24 Nov 2016 17:08:52 +0100 |
This commit adds implementation of fanotify_init and fanotify_mark.
Second argument for fanotify_init needs conversion because of flags
which can be FAN_NONBLOCK and FAN_CLOEXEC which rely on O_NONBLOCK
and O_CLOEXEC and those can have different values on different platforms.
For fanotify_mark argument layout is different for 32-bit and 64-bit
platforms and this implementation have support for that situation.
Also, support for writing and reading of file descriptor opened by
fanotify_init is added.
Configure file contains checks for excistence of fanotify support on
given build system.
Signed-off-by: Lena Djokic <address@hidden>
---
configure | 20 ++++++++
linux-user/syscall.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 142 insertions(+), 4 deletions(-)
diff --git a/configure b/configure
index fd6f898..56e6c98 100755
--- a/configure
+++ b/configure
@@ -3537,6 +3537,23 @@ if compile_prog "" "" ; then
inotify1=yes
fi
+# check if fanotify group of system calls is supported
+fanotify=no
+cat > $TMPC << EOF
+#include <sys/fanotify.h>
+
+int
+main(void)
+{
+ fanotify_init(0,0);
+ fanotify_mark(0,0,0,0,0);
+ return 0;
+}
+EOF
+if compile_prog "" "" ; then
+ fanotify=yes
+fi
+
# check if utimensat and futimens are supported
utimens=no
cat > $TMPC << EOF
@@ -5335,6 +5352,9 @@ fi
if test "$inotify1" = "yes" ; then
echo "CONFIG_INOTIFY1=y" >> $config_host_mak
fi
+if test "$fanotify" = "yes" ; then
+ echo "CONFIG_FANOTIFY=y" >> $config_host_mak
+fi
if test "$byteswap_h" = "yes" ; then
echo "CONFIG_BYTESWAP_H=y" >> $config_host_mak
fi
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 7b77503..f5d9a26 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -76,6 +76,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
#ifdef CONFIG_SENDFILE
#include <sys/sendfile.h>
#endif
+#ifdef CONFIG_FANOTIFY
+#include <sys/fanotify.h>
+#endif
#define termios host_termios
#define winsize host_winsize
@@ -499,9 +502,13 @@ enum {
QEMU___IFLA_INET6_MAX
};
+typedef abi_long (*TargetFdReadFunc)(void *, size_t);
+typedef abi_long (*TargetFdWriteFunc)(void *, size_t);
typedef abi_long (*TargetFdDataFunc)(void *, size_t);
typedef abi_long (*TargetFdAddrFunc)(void *, abi_ulong, socklen_t);
typedef struct TargetFdTrans {
+ TargetFdReadFunc read_op;
+ TargetFdWriteFunc write_op;
TargetFdDataFunc host_to_target_data;
TargetFdDataFunc target_to_host_data;
TargetFdAddrFunc target_to_host_addr;
@@ -511,6 +518,22 @@ static TargetFdTrans **target_fd_trans;
static unsigned int target_fd_max;
+static TargetFdReadFunc fd_trans_read_op(int fd)
+{
+ if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) {
+ return target_fd_trans[fd]->read_op;
+ }
+ return NULL;
+}
+
+static TargetFdWriteFunc fd_trans_write_op(int fd)
+{
+ if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) {
+ return target_fd_trans[fd]->write_op;
+ }
+ return NULL;
+}
+
static TargetFdDataFunc fd_trans_target_to_host_data(int fd)
{
if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) {
@@ -7527,6 +7550,47 @@ static target_timer_t get_timer_id(abi_long arg)
return timerid;
}
+#if defined(CONFIG_FANOTIFY)
+static inline abi_long fanotify_fd_read_op(void *buf, size_t len)
+{
+ struct fanotify_event_metadata *fem;
+ int num;
+
+ /* Read buffer for fanotify file descriptor contains one or more
+ * of fanotify_event_metadata structures.
+ */
+ fem = (struct fanotify_event_metadata *)buf;
+ num = len / sizeof(struct fanotify_event_metadata);
+ for (int i = 0; i < num; i++) {
+ (fem + i)->event_len = tswap32((fem + i)->event_len);
+ /* Fields (fem+i)->vers and (fem+i)->reserved are single byte,
+ * so swapping is not needed for them.
+ */
+ (fem + i)->metadata_len = tswap16((fem + i)->metadata_len);
+ (fem + i)->mask = tswap64((fem + i)->mask);
+ (fem + i)->fd = tswap32((fem + i)->fd);
+ (fem + i)->pid = tswap32((fem + i)->pid);
+ }
+
+ return len;
+}
+
+static inline abi_long fanotify_fd_write_op(void *buf, size_t len)
+{
+ struct fanotify_response *fr = (struct fanotify_response *)buf;
+
+ fr->fd = tswap32(fr->fd);
+ fr->response = tswap32(fr->response);
+
+ return len;
+}
+
+static TargetFdTrans fanotify_trans = {
+ .read_op = fanotify_fd_read_op,
+ .write_op = fanotify_fd_write_op,
+};
+#endif
+
/* do_syscall() should always have a single exit point at the end so
that actions, such as logging of syscall results, can be performed.
All errnos that do_syscall() returns must be -TARGET_<errcode>. */
@@ -7613,16 +7677,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long
arg1,
if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
goto efault;
ret = get_errno(safe_read(arg1, p, arg3));
- if (ret >= 0 &&
- fd_trans_host_to_target_data(arg1)) {
- ret = fd_trans_host_to_target_data(arg1)(p, ret);
- }
+ if (ret >= 0) {
+ if (fd_trans_read_op(arg1)) {
+ ret = fd_trans_read_op(arg1)(p, ret);
+ }
+ if (fd_trans_host_to_target_data(arg1)) {
+ ret = fd_trans_host_to_target_data(arg1)(p, ret);
+ }
+ }
unlock_user(p, arg2, ret);
}
break;
case TARGET_NR_write:
if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
goto efault;
+ if (fd_trans_write_op(arg1)) {
+ ret = fd_trans_write_op(arg1)(p, arg3);
+ if (is_error(ret)) {
+ unlock_user(p, arg2, 0);
+ break;
+ }
+ }
ret = get_errno(safe_write(arg1, p, arg3));
unlock_user(p, arg2, 0);
break;
@@ -11567,6 +11642,49 @@ abi_long do_syscall(void *cpu_env, int num, abi_long
arg1,
break;
#endif
+#if defined(TARGET_NR_fanotify_init) && defined(CONFIG_FANOTIFY)
+ case TARGET_NR_fanotify_init:
+ {
+ ret = get_errno(fanotify_init(arg1, target_to_host_bitmask(arg2,
+ fcntl_flags_tbl)));
+ if (ret >= 0) {
+ fd_trans_register(ret, &fanotify_trans);
+ }
+ }
+ break;
+#endif
+#if defined(TARGET_NR_fanotify_mark) && defined(CONFIG_FANOTIFY)
+ case TARGET_NR_fanotify_mark:
+ {
+ p = NULL;
+#if (TARGET_ABI_BITS == 32)
+ if (arg6) {
+ p = lock_user_string(arg6);
+ if (!p) {
+ goto efault;
+ }
+ }
+ ret = get_errno(fanotify_mark(arg1, arg2,
+ target_offset64(arg3, arg4), arg5 , p));
+ if (arg6) {
+ unlock_user(p, arg6, 0);
+ }
+#else
+ if (arg5) {
+ p = lock_user_string(arg5);
+ if (!p) {
+ goto efault;
+ }
+ }
+ ret = get_errno(fanotify_mark(arg1, arg2, arg3, arg4 , p));
+ if (arg5) {
+ unlock_user(p, arg5, 0);
+ }
+#endif
+ }
+ break;
+#endif
+
#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
case TARGET_NR_mq_open:
{
--
2.7.4
- [Qemu-devel] [PATCH v2 0/7] Improvements of qemu linux-user, Lena Djokic, 2016/11/24
- [Qemu-devel] [PATCH v2 2/7] linux-user: Fix inotify_init1 support, Lena Djokic, 2016/11/24
- [Qemu-devel] [PATCH v2 7/7] linux-user: Fix mq_open, Lena Djokic, 2016/11/24
- [Qemu-devel] [PATCH v2 4/7] linux-user: Fix fcnt, Lena Djokic, 2016/11/24
- [Qemu-devel] [PATCH v2 3/7] linux-user: Fix flock definition for mips64, Lena Djokic, 2016/11/24
- [Qemu-devel] [PATCH v2 6/7] linux-user: Fix syslog, Lena Djokic, 2016/11/24
- [Qemu-devel] [PATCH v2 1/7] linux-user: Add fanotify implementation,
Lena Djokic <=
- [Qemu-devel] [PATCH v2 5/7] linux-user: Fix readahead, Lena Djokic, 2016/11/24