Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] inotify: fix event loss on hardlinked files

People have run into a problem when they do this:

watch (file1, all_events);
watch (file2, some_events);

if file2 is a hard link to file1, some events will be missed because by
default we replace the mask. The patch below adds a flag IN_MASK_ADD which
will cause inotify to add to the existing mask if present.

Signed-off-by: John McCutchan <ttb@tentacle.dhs.org>
Signed-off-by: Robert Love <rml@novell.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

John McCutchan and committed by
Linus Torvalds
7ea6040b 8191151d

+9 -1
+8 -1
fs/inotify.c
··· 931 931 struct nameidata nd; 932 932 struct file *filp; 933 933 int ret, fput_needed; 934 + int mask_add = 0; 934 935 935 936 filp = fget_light(fd, &fput_needed); 936 937 if (unlikely(!filp)) ··· 954 953 down(&inode->inotify_sem); 955 954 down(&dev->sem); 956 955 956 + if (mask & IN_MASK_ADD) 957 + mask_add = 1; 958 + 957 959 /* don't let user-space set invalid bits: we don't want flags set */ 958 960 mask &= IN_ALL_EVENTS; 959 961 if (unlikely(!mask)) { ··· 970 966 */ 971 967 old = inode_find_dev(inode, dev); 972 968 if (unlikely(old)) { 973 - old->mask = mask; 969 + if (mask_add) 970 + old->mask |= mask; 971 + else 972 + old->mask = mask; 974 973 ret = old->wd; 975 974 goto out; 976 975 }
+1
include/linux/inotify.h
··· 47 47 #define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves */ 48 48 49 49 /* special flags */ 50 + #define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */ 50 51 #define IN_ISDIR 0x40000000 /* event occurred against dir */ 51 52 #define IN_ONESHOT 0x80000000 /* only send event once */ 52 53