diff options
-rw-r--r-- | Changes | 5 | ||||
-rw-r--r-- | ev++.h | 1 | ||||
-rw-r--r-- | ev.c | 85 | ||||
-rw-r--r-- | ev_vars.h | 1 | ||||
-rw-r--r-- | ev_wrap.h | 2 |
5 files changed, 61 insertions, 33 deletions
@@ -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 @@ -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, }; @@ -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, µ) != 3) + return; - if (sscanf (buf.release, "%d.%d.%d", &major, &minor, µ) != 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); @@ -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 @@ -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 |