diff options
author | John McCutchan <ttb@tentacle.dhs.org> | 2005-09-06 18:18:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-07 19:57:39 -0400 |
commit | 7ea6040b0eff07d3a9a4e2d248ac137c6ad02d42 (patch) | |
tree | 0a7bcce73c623f89cd5e8a97d2da7946da3293e3 | |
parent | 8191151d0933d65fb6b659ffbd765479f0f200e1 (diff) |
[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>
-rw-r--r-- | fs/inotify.c | 9 | ||||
-rw-r--r-- | include/linux/inotify.h | 1 |
2 files changed, 9 insertions, 1 deletions
diff --git a/fs/inotify.c b/fs/inotify.c index 2fd97ef547ff..a37e9fb1da58 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
@@ -931,6 +931,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) | |||
931 | struct nameidata nd; | 931 | struct nameidata nd; |
932 | struct file *filp; | 932 | struct file *filp; |
933 | int ret, fput_needed; | 933 | int ret, fput_needed; |
934 | int mask_add = 0; | ||
934 | 935 | ||
935 | filp = fget_light(fd, &fput_needed); | 936 | filp = fget_light(fd, &fput_needed); |
936 | if (unlikely(!filp)) | 937 | if (unlikely(!filp)) |
@@ -953,6 +954,9 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) | |||
953 | down(&inode->inotify_sem); | 954 | down(&inode->inotify_sem); |
954 | down(&dev->sem); | 955 | down(&dev->sem); |
955 | 956 | ||
957 | if (mask & IN_MASK_ADD) | ||
958 | mask_add = 1; | ||
959 | |||
956 | /* don't let user-space set invalid bits: we don't want flags set */ | 960 | /* don't let user-space set invalid bits: we don't want flags set */ |
957 | mask &= IN_ALL_EVENTS; | 961 | mask &= IN_ALL_EVENTS; |
958 | if (unlikely(!mask)) { | 962 | if (unlikely(!mask)) { |
@@ -966,7 +970,10 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) | |||
966 | */ | 970 | */ |
967 | old = inode_find_dev(inode, dev); | 971 | old = inode_find_dev(inode, dev); |
968 | if (unlikely(old)) { | 972 | if (unlikely(old)) { |
969 | old->mask = mask; | 973 | if (mask_add) |
974 | old->mask |= mask; | ||
975 | else | ||
976 | old->mask = mask; | ||
970 | ret = old->wd; | 977 | ret = old->wd; |
971 | goto out; | 978 | goto out; |
972 | } | 979 | } |
diff --git a/include/linux/inotify.h b/include/linux/inotify.h index 93bb3afe646b..ee5b239092ed 100644 --- a/include/linux/inotify.h +++ b/include/linux/inotify.h | |||
@@ -47,6 +47,7 @@ struct inotify_event { | |||
47 | #define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves */ | 47 | #define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves */ |
48 | 48 | ||
49 | /* special flags */ | 49 | /* special flags */ |
50 | #define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */ | ||
50 | #define IN_ISDIR 0x40000000 /* event occurred against dir */ | 51 | #define IN_ISDIR 0x40000000 /* event occurred against dir */ |
51 | #define IN_ONESHOT 0x80000000 /* only send event once */ | 52 | #define IN_ONESHOT 0x80000000 /* only send event once */ |
52 | 53 | ||