All of lore.kernel.org
 help / color / mirror / Atom feed
From: Amir Goldstein <amir73il@gmail.com>
To: Jan Kara <jack@suse.cz>
Cc: linux-fsdevel@vger.kernel.org
Subject: [PATCH 5/6] fanotify: merge duplicate events on parent and child
Date: Tue, 14 Jan 2020 17:16:54 +0200	[thread overview]
Message-ID: <20200114151655.29473-6-amir73il@gmail.com> (raw)
In-Reply-To: <20200114151655.29473-1-amir73il@gmail.com>

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
tag 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 dentry instead of inode as
the tag for event merging, so that the event reported on parent will be
merged with the event reported on the child.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 34454390e4b6..2ae82040f26f 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -265,17 +265,21 @@ static int fanotify_encode_fid(struct fanotify_event *event,
  * FS_CREATE reports the modified dir inode and not the created inode.
  */
 static struct inode *fanotify_fid_inode(struct inode *to_tell, u32 event_mask,
-					const void *data, int data_type)
+					const void *data, int data_type,
+					struct dentry **pdentry)
 {
 	if (event_mask & ALL_FSNOTIFY_DIRENT_EVENTS)
 		return to_tell;
 	else if (data_type == FSNOTIFY_EVENT_INODE)
 		return (struct inode *)data;
 	else if (data_type == FSNOTIFY_EVENT_DENTRY)
-		return d_inode(data);
+		*pdentry = (struct dentry *)data;
 	else if (data_type == FSNOTIFY_EVENT_PATH)
-		return d_inode(((struct path *)data)->dentry);
-	return NULL;
+		*pdentry = ((struct path *)data)->dentry;
+	else
+		return NULL;
+
+	return d_inode(*pdentry);
 }
 
 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
@@ -285,7 +289,9 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
 {
 	struct fanotify_event *event = NULL;
 	gfp_t gfp = GFP_KERNEL_ACCOUNT;
-	struct inode *id = fanotify_fid_inode(inode, mask, data, data_type);
+	struct dentry *dentry = NULL;
+	struct inode *id = fanotify_fid_inode(inode, mask, data, data_type,
+					      &dentry);
 
 	/*
 	 * For queues with unlimited length lost events are not expected and
@@ -316,7 +322,12 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
 	if (!event)
 		goto out;
 init: __maybe_unused
-	fsnotify_init_event(&event->fse, inode);
+	/*
+	 * Use the dentry instead of inode as tag 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, (void *)dentry ?: inode);
 	event->mask = mask;
 	if (FAN_GROUP_FLAG(group, FAN_REPORT_TID))
 		event->pid = get_pid(task_pid(current));
-- 
2.17.1


  parent reply	other threads:[~2020-01-14 15:17 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-14 15:16 [PATCH 0/6] Prepare for fanotify name events Amir Goldstein
2020-01-14 15:16 ` [PATCH 1/6] fsnotify: tidy up FS_ and FAN_ constants Amir Goldstein
2020-01-14 15:16 ` [PATCH 2/6] fsnotify: pass dentry instead of inode for events possible on child Amir Goldstein
2020-01-14 15:16 ` [PATCH 3/6] fsnotify: simplify arguments passing to fsnotify_parent() Amir Goldstein
2020-01-14 15:16 ` [PATCH 4/6] fsnotify: replace inode pointer with tag Amir Goldstein
2020-01-14 15:16 ` Amir Goldstein [this message]
2020-01-14 15:16 ` [PATCH 6/6] fanotify: fix merging marks masks with FAN_ONDIR Amir Goldstein

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200114151655.29473-6-amir73il@gmail.com \
    --to=amir73il@gmail.com \
    --cc=jack@suse.cz \
    --cc=linux-fsdevel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.