Add a new simulation hint, --sim-hints=fuse-compatible, which causes
a bunch of file-related syscalls to be handled on the might-block
syscall path rather than the fast syscall path.  This fixes deadlocks
when running some FUSE-specific filesystem codes.  Fixes #278057.
(Mike Shal, marfey@gmail.com)



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11993 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index cc217f4..f0134b6 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -177,7 +177,7 @@
 "    --vgdb-prefix=<prefix>    prefix for vgdb FIFOs [%s]\n"
 "    --run-libc-freeres=no|yes free up glibc memory at exit on Linux? [yes]\n"
 "    --sim-hints=hint1,hint2,...  known hints:\n"
-"                                 lax-ioctls, enable-outer [none]\n"
+"                                 lax-ioctls, enable-outer, fuse-compatible [none]\n"
 "    --kernel-variant=variant1,variant2,...  known variants: bproc [none]\n"
 "                              handle non-standard kernel variants\n"
 "    --show-emwarns=no|yes     show warnings about emulation limits? [no]\n"
diff --git a/coregrind/m_syswrap/priv_types_n_macros.h b/coregrind/m_syswrap/priv_types_n_macros.h
index b15d19b..a7890b2 100644
--- a/coregrind/m_syswrap/priv_types_n_macros.h
+++ b/coregrind/m_syswrap/priv_types_n_macros.h
@@ -345,6 +345,9 @@
    if (VG_(clo_trace_syscalls))                      \
       VG_(printf)(format, ## args)
 
+#define FUSE_COMPATIBLE_MAY_BLOCK()                       \
+   if (VG_(strstr)(VG_(clo_sim_hints),"fuse-compatible")) \
+      *flags |= SfMayBlock
 
 
 /* Macros used to tell tools about uses of scalar arguments.  Note,
diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
index ec09e50..87a7c11 100644
--- a/coregrind/m_syswrap/syswrap-generic.c
+++ b/coregrind/m_syswrap/syswrap-generic.c
@@ -2412,6 +2412,7 @@
 
 PRE(sys_fstatfs)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_fstatfs ( %ld, %#lx )",ARG1,ARG2);
    PRE_REG_READ2(long, "fstatfs",
                  unsigned int, fd, struct statfs *, buf);
@@ -2425,6 +2426,7 @@
 
 PRE(sys_fstatfs64)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_fstatfs64 ( %ld, %llu, %#lx )",ARG1,(ULong)ARG2,ARG3);
    PRE_REG_READ3(long, "fstatfs64",
                  unsigned int, fd, vki_size_t, size, struct statfs64 *, buf);
@@ -2471,6 +2473,7 @@
 
 PRE(sys_mknod)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_mknod ( %#lx(%s), 0x%lx, 0x%lx )", ARG1, (char*)ARG1, ARG2, ARG3 );
    PRE_REG_READ3(long, "mknod",
                  const char *, pathname, int, mode, unsigned, dev);
@@ -2849,6 +2852,7 @@
 
 PRE(sys_chdir)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_chdir ( %#lx(%s) )", ARG1,(char*)ARG1);
    PRE_REG_READ1(long, "chdir", const char *, path);
    PRE_MEM_RASCIIZ( "chdir(path)", ARG1 );
@@ -2856,6 +2860,7 @@
 
 PRE(sys_chmod)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_chmod ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
    PRE_REG_READ2(long, "chmod", const char *, path, vki_mode_t, mode);
    PRE_MEM_RASCIIZ( "chmod(path)", ARG1 );
@@ -2863,6 +2868,7 @@
 
 PRE(sys_chown)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_chown ( %#lx(%s), 0x%lx, 0x%lx )", ARG1,(char*)ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "chown",
                  const char *, path, vki_uid_t, owner, vki_gid_t, group);
@@ -2871,6 +2877,7 @@
 
 PRE(sys_lchown)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_lchown ( %#lx(%s), 0x%lx, 0x%lx )", ARG1,(char*)ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "lchown",
                  const char *, path, vki_uid_t, owner, vki_gid_t, group);
@@ -2879,6 +2886,7 @@
 
 PRE(sys_close)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_close ( %ld )", ARG1);
    PRE_REG_READ1(long, "close", unsigned int, fd);
 
@@ -2930,12 +2938,14 @@
 
 PRE(sys_fchdir)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_fchdir ( %ld )", ARG1);
    PRE_REG_READ1(long, "fchdir", unsigned int, fd);
 }
 
 PRE(sys_fchown)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_fchown ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "fchown",
                  unsigned int, fd, vki_uid_t, owner, vki_gid_t, group);
@@ -2943,12 +2953,14 @@
 
 PRE(sys_fchmod)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_fchmod ( %ld, %ld )", ARG1,ARG2);
    PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode);
 }
 
 PRE(sys_newfstat)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_newfstat ( %ld, %#lx )", ARG1,ARG2);
    PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat *, buf);
    PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) );
@@ -3741,6 +3753,7 @@
 
 PRE(sys_readlink)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    Word saved = SYSNO;
 
    PRINT("sys_readlink ( %#lx(%s), %#lx, %llu )", ARG1,(char*)ARG1,ARG2,(ULong)ARG3);
@@ -3822,6 +3835,7 @@
 
 PRE(sys_rename)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_rename ( %#lx(%s), %#lx(%s) )", ARG1,(char*)ARG1,ARG2,(char*)ARG2);
    PRE_REG_READ2(long, "rename", const char *, oldpath, const char *, newpath);
    PRE_MEM_RASCIIZ( "rename(oldpath)", ARG1 );
@@ -4121,6 +4135,7 @@
 
 PRE(sys_utimes)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_utimes ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
    PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp);
    PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 );
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index ac5e8ec..1cfd7b7 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -3267,6 +3267,7 @@
 
 PRE(sys_newfstatat)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_newfstatat ( %ld, %#lx(%s), %#lx )", ARG1,ARG2,(char*)ARG2,ARG3);
    PRE_REG_READ3(long, "fstatat",
                  int, dfd, char *, file_name, struct stat *, buf);
diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c
index 9888cc6..aa7c0b6 100644
--- a/coregrind/m_syswrap/syswrap-x86-linux.c
+++ b/coregrind/m_syswrap/syswrap-x86-linux.c
@@ -1404,6 +1404,7 @@
 
 PRE(sys_stat64)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_stat64 ( %#lx(%s), %#lx )",ARG1,(char*)ARG1,ARG2);
    PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf);
    PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 );
@@ -1417,6 +1418,7 @@
 
 PRE(sys_fstatat64)
 {
+   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_fstatat64 ( %ld, %#lx(%s), %#lx )",ARG1,ARG2,(char*)ARG2,ARG3);
    PRE_REG_READ3(long, "fstatat64",
                  int, dfd, char *, file_name, struct stat64 *, buf);