From: Sasha Levin Date: Wed, 13 May 2020 00:50:59 +0000 (-0400) Subject: Fixes for 5.4 X-Git-Tag: v4.19.123~11 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d61e9a0852e93d50d0e9f08b150aa63e77f6d6f7;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/fanotify-merge-duplicate-events-on-parent-and-child.patch b/queue-5.4/fanotify-merge-duplicate-events-on-parent-and-child.patch new file mode 100644 index 00000000000..c0af9be6db9 --- /dev/null +++ b/queue-5.4/fanotify-merge-duplicate-events-on-parent-and-child.patch @@ -0,0 +1,55 @@ +From 38b4ff6cddb1b74473f3d0d9add98ccc9636e2dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2020 17:10:16 +0200 +Subject: fanotify: merge duplicate events on parent and child + +From: Amir Goldstein + +[ 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 +Signed-off-by: Jan Kara +Signed-off-by: Sasha Levin +--- + fs/notify/fanotify/fanotify.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c +index 14d0ac4664595..f5d30573f4a99 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)); +-- +2.20.1 + diff --git a/queue-5.4/fsnotify-replace-inode-pointer-with-an-object-id.patch b/queue-5.4/fsnotify-replace-inode-pointer-with-an-object-id.patch new file mode 100644 index 00000000000..a9ba02d0236 --- /dev/null +++ b/queue-5.4/fsnotify-replace-inode-pointer-with-an-object-id.patch @@ -0,0 +1,113 @@ +From 3f96da8b1c76aa55994f98022967521b21fb1eb2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2020 17:10:15 +0200 +Subject: fsnotify: replace inode pointer with an object id + +From: Amir Goldstein + +[ Upstream commit dfc2d2594e4a79204a3967585245f00644b8f838 ] + +The event inode field is used only for comparison in queue merges and +cannot be dereferenced after handle_event(), because it does not hold a +refcount on the inode. + +Replace it with an abstract id to do the same thing. + +Link: https://lore.kernel.org/r/20200319151022.31456-8-amir73il@gmail.com +Signed-off-by: Amir Goldstein +Signed-off-by: Jan Kara +Signed-off-by: Sasha Levin +--- + fs/notify/fanotify/fanotify.c | 4 ++-- + fs/notify/inotify/inotify_fsnotify.c | 4 ++-- + fs/notify/inotify/inotify_user.c | 2 +- + include/linux/fsnotify_backend.h | 7 +++---- + 4 files changed, 8 insertions(+), 9 deletions(-) + +diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c +index 5778d1347b351..14d0ac4664595 100644 +--- a/fs/notify/fanotify/fanotify.c ++++ b/fs/notify/fanotify/fanotify.c +@@ -26,7 +26,7 @@ static bool should_merge(struct fsnotify_event *old_fsn, + old = FANOTIFY_E(old_fsn); + new = FANOTIFY_E(new_fsn); + +- if (old_fsn->inode != new_fsn->inode || old->pid != new->pid || ++ if (old_fsn->objectid != new_fsn->objectid || old->pid != new->pid || + old->fh_type != new->fh_type || old->fh_len != new->fh_len) + return false; + +@@ -314,7 +314,7 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, + if (!event) + goto out; + init: __maybe_unused +- fsnotify_init_event(&event->fse, inode); ++ fsnotify_init_event(&event->fse, (unsigned long)inode); + event->mask = mask; + if (FAN_GROUP_FLAG(group, FAN_REPORT_TID)) + event->pid = get_pid(task_pid(current)); +diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c +index d510223d302ca..589dee9629938 100644 +--- a/fs/notify/inotify/inotify_fsnotify.c ++++ b/fs/notify/inotify/inotify_fsnotify.c +@@ -39,7 +39,7 @@ static bool event_compare(struct fsnotify_event *old_fsn, + if (old->mask & FS_IN_IGNORED) + return false; + if ((old->mask == new->mask) && +- (old_fsn->inode == new_fsn->inode) && ++ (old_fsn->objectid == new_fsn->objectid) && + (old->name_len == new->name_len) && + (!old->name_len || !strcmp(old->name, new->name))) + return true; +@@ -118,7 +118,7 @@ int inotify_handle_event(struct fsnotify_group *group, + mask &= ~IN_ISDIR; + + fsn_event = &event->fse; +- fsnotify_init_event(fsn_event, inode); ++ fsnotify_init_event(fsn_event, (unsigned long)inode); + event->mask = mask; + event->wd = i_mark->wd; + event->sync_cookie = cookie; +diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c +index 107537a543fd8..81ffc8629fc4b 100644 +--- a/fs/notify/inotify/inotify_user.c ++++ b/fs/notify/inotify/inotify_user.c +@@ -635,7 +635,7 @@ static struct fsnotify_group *inotify_new_group(unsigned int max_events) + return ERR_PTR(-ENOMEM); + } + group->overflow_event = &oevent->fse; +- fsnotify_init_event(group->overflow_event, NULL); ++ fsnotify_init_event(group->overflow_event, 0); + oevent->mask = FS_Q_OVERFLOW; + oevent->wd = -1; + oevent->sync_cookie = 0; +diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h +index 1915bdba2fad9..64cfb5446f4d4 100644 +--- a/include/linux/fsnotify_backend.h ++++ b/include/linux/fsnotify_backend.h +@@ -133,8 +133,7 @@ struct fsnotify_ops { + */ + struct fsnotify_event { + struct list_head list; +- /* inode may ONLY be dereferenced during handle_event(). */ +- struct inode *inode; /* either the inode the event happened to or its parent */ ++ unsigned long objectid; /* identifier for queue merges */ + }; + + /* +@@ -500,10 +499,10 @@ extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info); + extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info); + + static inline void fsnotify_init_event(struct fsnotify_event *event, +- struct inode *inode) ++ unsigned long objectid) + { + INIT_LIST_HEAD(&event->list); +- event->inode = inode; ++ event->objectid = objectid; + } + + #else +-- +2.20.1 + diff --git a/queue-5.4/series b/queue-5.4/series index 9329224a1a3..562295f9a04 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -86,3 +86,5 @@ scripts-decodecode-fix-trapping-instruction-formatting.patch mm-memcg-fix-error-return-value-of-mem_cgroup_css_alloc.patch bdi-move-bdi_dev_name-out-of-line.patch bdi-add-a-dev_name-field-to-struct-backing_dev_info.patch +fsnotify-replace-inode-pointer-with-an-object-id.patch +fanotify-merge-duplicate-events-on-parent-and-child.patch