From 2ec8932c8c9cb71eb9f95e79cce195e64452dfd9 Mon Sep 17 00:00:00 2001 From: Craig Small Date: Mon, 18 Jul 2011 21:23:30 +1000 Subject: [PATCH] conditionally compile in fork for stat --- ChangeLog | 1 + README | 7 +++++++ configure.ac | 10 ++++++++++ src/fuser.c | 15 ++++++++++----- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 815a8a3..4605f7f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ Changes in 22.15 ================ * Really apply patch for SF#31110178 RH#651794 + * Conditionally use fork before stat calls Changes in 22.14 ================ diff --git a/README b/README index 2489b05..2bc973f 100644 --- a/README +++ b/README @@ -17,6 +17,13 @@ They should work with most recent kernels. Man pages are included. src/loop.h was stolen from util-linux package which in turn stole it from the Linux kernel. +fuser on network fs +------------------- +On network filesystems, fuser can hang because its trying to stat files +that may go away. If you use the --with-timeout-stat option during +the configure step then fuser will fork a process to run stat. This means +fuser doesn't hang, but it is much slower. + Translations ------------ My thanks for the various translators who have cheerfully given me the po diff --git a/configure.ac b/configure.ac index d9013d5..e8480cb 100644 --- a/configure.ac +++ b/configure.ac @@ -24,6 +24,16 @@ if test "$enable_selinux" = "yes"; then fi AC_SUBST([SELINUX_LIB]) +dnl Call fork before all stat calls to stop hanging on NFS mounts +AC_SUBST([WITH_TIMEOUT_STAT]) +AC_ARG_ENABLE([TIMEOUT_STAT], + [AS_HELP_STRING([--enable-timeout-stat], [Use a timeout on stat calls])], + [enable_timeout_stat=$enableval], + [enable_timeout_stat="no"]) +if test "$enable_timeout_stat" = "yes"; then + AC_DEFINE([WITH_timeout_stat], [1], [Use timeout on stat calls]) +fi + dnl ipv4 only option AC_SUBST([WITH_IPV6]) AC_ARG_ENABLE([ipv6], diff --git a/src/fuser.c b/src/fuser.c index 8f600aa..bef14e2 100644 --- a/src/fuser.c +++ b/src/fuser.c @@ -106,7 +106,11 @@ static dev_t device(const char *path); static char *expandpath(const char *path); typedef int (*stat_t)(const char*, struct stat*); +#ifdef WITH_TIMEOUT_STAT static int timeout(stat_t func, const char *path, struct stat *buf, unsigned int seconds); +#else +#define timeout(func,path,buf,dummy) (func)((path),(buf)) +#endif /* WITH_TIMEOUT_STAT */ static void usage(const char *errormsg) { @@ -1321,12 +1325,11 @@ static struct stat *get_pidstat(const pid_t pid, const char *filename) if ((st = (struct stat*)malloc(sizeof(struct stat))) == NULL) return NULL; snprintf(pathname, 256, "/proc/%d/%s", pid, filename); - if (timeout(stat, pathname, st, 5) != 0) - goto out; + if (timeout(stat, pathname, st, 5) != 0) { + free(st); + return NULL; + } return st; -out: - free(st); - return NULL; } static void @@ -1783,6 +1786,7 @@ sigalarm(int sig) siglongjmp(jenv, 1); } +#ifdef HAVE_TIMEOUT_STAT static int timeout(stat_t func, const char *path, struct stat *buf, unsigned int seconds) { @@ -1831,6 +1835,7 @@ timeout(stat_t func, const char *path, struct stat *buf, unsigned int seconds) err: return -1; } +#endif /* HAVE_TIMEOUT_STAT */ #ifdef _LISTS_H /* -- 2.50.1