summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changes5
-rw-r--r--ev++.h1
-rw-r--r--ev.c85
-rw-r--r--ev_vars.h1
-rw-r--r--ev_wrap.h2
5 files changed, 61 insertions, 33 deletions
diff --git a/Changes b/Changes
index 3e01b7c..0a388df 100644
--- a/Changes
+++ b/Changes
@@ -2,7 +2,10 @@ Revision history for libev, a high-performance and full-featured event loop.
WISH? monotonic clocks times/GetTickCount for coarse corrections?
-TODO: "ev_stat on nfs"
+ - ev_stat watchers will now use inotify as a mere hint on
+ kernels <2.6.25, or if the filesystem is not in the
+ "known to be good" list.
+
3.48 Thu Oct 30 09:02:37 CET 2008
- further optimise away the EPOLL_CTL_ADD/MOD combo in the epoll
backend by assuming the kernel event mask hasn't changed if
diff --git a/ev++.h b/ev++.h
index c400bf1..a17efa2 100644
--- a/ev++.h
+++ b/ev++.h
@@ -74,6 +74,7 @@ namespace ev {
FORK = EV_FORK,
ASYNC = EV_ASYNC,
EMBED = EV_EMBED,
+# undef ERROR // some systems stupidly #define ERROR
ERROR = EV_ERROR,
};
diff --git a/ev.c b/ev.c
index 464ce41..c872176 100644
--- a/ev.c
+++ b/ev.c
@@ -289,6 +289,7 @@ extern "C" {
#if EV_USE_INOTIFY
# include <sys/utsname.h>
+# include <sys/statfs.h>
# include <sys/inotify.h>
/* some very old inotify.h headers don't have IN_DONT_FOLLOW */
# ifndef IN_DONT_FOLLOW
@@ -2416,8 +2417,9 @@ ev_child_stop (EV_P_ ev_child *w)
# define lstat(a,b) _stati64 (a,b)
# endif
-#define DEF_STAT_INTERVAL 5.0074891
-#define MIN_STAT_INTERVAL 0.1074891
+#define DEF_STAT_INTERVAL 5.0074891
+#define NFS_STAT_INTERVAL 30.1074891 /* for filesystems potentially failing inotify */
+#define MIN_STAT_INTERVAL 0.1074891
static void noinline stat_timer_cb (EV_P_ ev_timer *w_, int revents);
@@ -2431,7 +2433,8 @@ infy_add (EV_P_ ev_stat *w)
if (w->wd < 0)
{
- ev_timer_start (EV_A_ &w->timer); /* this is not race-free, so we still need to recheck periodically */
+ w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;
+ ev_timer_again (EV_A_ &w->timer); /* this is not race-free, so we still need to recheck periodically */
/* monitor some parent directory for speedup hints */
/* note that exceeding the hardcoded path limit is not a correctness issue, */
@@ -2458,10 +2461,26 @@ infy_add (EV_P_ ev_stat *w)
}
}
else
- ev_timer_stop (EV_A_ &w->timer); /* we can watch this in a race-free way */
+ {
+ wlist_add (&fs_hash [w->wd & (EV_INOTIFY_HASHSIZE - 1)].head, (WL)w);
+
+ /* now local changes will be tracked by inotify, but remote changes won't */
+ /* unless the filesystem it known to be local, we therefore still poll */
+ /* also do poll on <2.6.25, but with normal frequency */
+ struct statfs sfs;
+
+ if (fs_2625 && !statfs (w->path, &sfs))
+ if (sfs.f_type == 0x1373 /* devfs */
+ || sfs.f_type == 0xEF53 /* ext2/3 */
+ || sfs.f_type == 0x3153464a /* jfs */
+ || sfs.f_type == 0x52654973 /* reiser3 */
+ || sfs.f_type == 0x01021994 /* tempfs */
+ || sfs.f_type == 0x58465342 /* xfs */)
+ return;
- if (w->wd >= 0)
- wlist_add (&fs_hash [w->wd & (EV_INOTIFY_HASHSIZE - 1)].head, (WL)w);
+ w->timer.repeat = w->interval ? w->interval : fs_2625 ? NFS_STAT_INTERVAL : DEF_STAT_INTERVAL;
+ ev_timer_again (EV_A_ &w->timer);
+ }
}
static void noinline
@@ -2524,31 +2543,37 @@ infy_cb (EV_P_ ev_io *w, int revents)
}
void inline_size
-infy_init (EV_P)
+check_2625 (EV_P)
{
- if (fs_fd != -2)
- return;
-
/* kernels < 2.6.25 are borked
* http://www.ussg.indiana.edu/hypermail/linux/kernel/0711.3/1208.html
*/
- {
- struct utsname buf;
- int major, minor, micro;
+ struct utsname buf;
+ int major, minor, micro;
- fs_fd = -1;
+ if (uname (&buf))
+ return;
- if (uname (&buf))
- return;
+ if (sscanf (buf.release, "%d.%d.%d", &major, &minor, &micro) != 3)
+ return;
- if (sscanf (buf.release, "%d.%d.%d", &major, &minor, &micro) != 3)
- return;
+ if (major < 2
+ || (major == 2 && minor < 6)
+ || (major == 2 && minor == 6 && micro < 25))
+ return;
- if (major < 2
- || (major == 2 && minor < 6)
- || (major == 2 && minor == 6 && micro < 25))
- return;
- }
+ fs_2625 = 1;
+}
+
+void inline_size
+infy_init (EV_P)
+{
+ if (fs_fd != -2)
+ return;
+
+ fs_fd = -1;
+
+ check_2625 (EV_A);
fs_fd = inotify_init ();
@@ -2586,7 +2611,7 @@ infy_fork (EV_P)
if (fs_fd >= 0)
infy_add (EV_A_ w); /* re-add, no matter what */
else
- ev_timer_start (EV_A_ &w->timer);
+ ev_timer_again (EV_A_ &w->timer);
}
}
}
@@ -2651,16 +2676,12 @@ ev_stat_start (EV_P_ ev_stat *w)
if (expect_false (ev_is_active (w)))
return;
- /* since we use memcmp, we need to clear any padding data etc. */
- memset (&w->prev, 0, sizeof (ev_statdata));
- memset (&w->attr, 0, sizeof (ev_statdata));
-
ev_stat_stat (EV_A_ w);
- if (w->interval < MIN_STAT_INTERVAL)
- w->interval = w->interval ? MIN_STAT_INTERVAL : DEF_STAT_INTERVAL;
+ if (w->interval < MIN_STAT_INTERVAL && w->interval)
+ w->interval = MIN_STAT_INTERVAL;
- ev_timer_init (&w->timer, stat_timer_cb, w->interval, w->interval);
+ ev_timer_init (&w->timer, stat_timer_cb, 0., w->interval ? w->interval : DEF_STAT_INTERVAL);
ev_set_priority (&w->timer, ev_priority (w));
#if EV_USE_INOTIFY
@@ -2670,7 +2691,7 @@ ev_stat_start (EV_P_ ev_stat *w)
infy_add (EV_A_ w);
else
#endif
- ev_timer_start (EV_A_ &w->timer);
+ ev_timer_again (EV_A_ &w->timer);
ev_start (EV_A_ (W)w, 1);
diff --git a/ev_vars.h b/ev_vars.h
index ac0ec61..3290a57 100644
--- a/ev_vars.h
+++ b/ev_vars.h
@@ -156,6 +156,7 @@ VARx(int, asynccnt)
#if EV_USE_INOTIFY || EV_GENWRAP
VARx(int, fs_fd)
VARx(ev_io, fs_w)
+VARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */
VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])
#endif
diff --git a/ev_wrap.h b/ev_wrap.h
index 6ccc1d2..ad545bf 100644
--- a/ev_wrap.h
+++ b/ev_wrap.h
@@ -71,6 +71,7 @@
#define asynccnt ((loop)->asynccnt)
#define fs_fd ((loop)->fs_fd)
#define fs_w ((loop)->fs_w)
+#define fs_2625 ((loop)->fs_2625)
#define fs_hash ((loop)->fs_hash)
#else
#undef EV_WRAP_H
@@ -144,5 +145,6 @@
#undef asynccnt
#undef fs_fd
#undef fs_w
+#undef fs_2625
#undef fs_hash
#endif