summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2020-03-19 17:10:16 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-05-14 07:58:30 +0200
commit9bd5a84ceba320abe25f752a0bd390e3308f7b2c (patch)
treeccbc5e76f695d4309f3d2e20213dab508f0d90f1
parent4638e0ff0fa4bc88330f28e756bbcce114afe281 (diff)
downloadlinux-stable-9bd5a84ceba320abe25f752a0bd390e3308f7b2c.tar.gz
linux-stable-9bd5a84ceba320abe25f752a0bd390e3308f7b2c.tar.bz2
linux-stable-9bd5a84ceba320abe25f752a0bd390e3308f7b2c.zip
fanotify: merge duplicate events on parent and child
[ Upstream commit f367a62a7cad2447d835a9f14fc63997a9137246 ] With inotify, when a watch is set on a directory and on its child, an event on the child is reported twice, once with wd of the parent watch and once with wd of the child watch without the filename. With fanotify, when a watch is set on a directory and on its child, an event on the child is reported twice, but it has the exact same information - either an open file descriptor of the child or an encoded fid of the child. The reason that the two identical events are not merged is because the object id used for merging events in the queue is the child inode in one event and parent inode in the other. For events with path or dentry data, use the victim inode instead of the watched inode as the object id for event merging, so that the event reported on parent will be merged with the event reported on the child. Link: https://lore.kernel.org/r/20200319151022.31456-9-amir73il@gmail.com Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--fs/notify/fanotify/fanotify.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 14d0ac466459..f5d30573f4a9 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -314,7 +314,12 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
if (!event)
goto out;
init: __maybe_unused
- fsnotify_init_event(&event->fse, (unsigned long)inode);
+ /*
+ * Use the victim inode instead of the watching inode as the id for
+ * event queue, so event reported on parent is merged with event
+ * reported on child when both directory and child watches exist.
+ */
+ fsnotify_init_event(&event->fse, (unsigned long)id);
event->mask = mask;
if (FAN_GROUP_FLAG(group, FAN_REPORT_TID))
event->pid = get_pid(task_pid(current));