--- libev/ev.c 2008/11/03 12:17:40 1.272 +++ libev/ev.c 2008/11/03 14:27:06 1.273 @@ -289,6 +289,7 @@ #if EV_USE_INOTIFY # include +# include # include /* some very old inotify.h headers don't have IN_DONT_FOLLOW */ # ifndef IN_DONT_FOLLOW @@ -2416,8 +2417,9 @@ # 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 @@ 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 @@ } } 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 @@ } 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 @@ 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 @@ 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 @@ 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);