Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a9fb89f authored by Eric Paris's avatar Eric Paris
Browse files

fsnotify: include vfsmount in should_send_event when appropriate



To ensure that a group will not duplicate events when it receives it based
on the vfsmount and the inode should_send_event test we should distinguish
those two cases.  We pass a vfsmount to this function so groups can make
their own determinations.

Signed-off-by: default avatarEric Paris <eparis@redhat.com>
parent 7131485a
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -133,8 +133,8 @@ static int dnotify_handle_event(struct fsnotify_group *group,
 * userspace notification for that pair.
 * userspace notification for that pair.
 */
 */
static bool dnotify_should_send_event(struct fsnotify_group *group,
static bool dnotify_should_send_event(struct fsnotify_group *group,
				      struct inode *inode, __u32 mask,
				      struct inode *inode, struct vfsmount *mnt,
				      void *data, int data_type)
				      __u32 mask, void *data, int data_type)
{
{
	struct fsnotify_mark_entry *entry;
	struct fsnotify_mark_entry *entry;
	bool send;
	bool send;
+19 −20
Original line number Original line Diff line number Diff line
@@ -135,13 +135,12 @@ void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask)
}
}
EXPORT_SYMBOL_GPL(__fsnotify_parent);
EXPORT_SYMBOL_GPL(__fsnotify_parent);


static void send_to_group(__u32 mask,
static void send_to_group(struct fsnotify_group *group, struct inode *to_tell,
			  struct fsnotify_group *group,
			  struct vfsmount *mnt, __u32 mask, void *data,
			  void *data, int data_is, const char *file_name,
			  int data_is, u32 cookie, const char *file_name,
			  u32 cookie, struct fsnotify_event **event,
			  struct fsnotify_event **event)
			  struct inode *to_tell)
{
{
	if (!group->ops->should_send_event(group, to_tell, mask,
	if (!group->ops->should_send_event(group, to_tell, mnt, mask,
					   data, data_is))
					   data, data_is))
		return;
		return;
	if (!*event) {
	if (!*event) {
@@ -159,15 +158,9 @@ static void send_to_group(__u32 mask,
	group->ops->handle_event(group, *event);
	group->ops->handle_event(group, *event);
}
}


static bool needed_by_vfsmount(__u32 test_mask, void *data, int data_is)
static bool needed_by_vfsmount(__u32 test_mask, struct vfsmount *mnt)
{
{
	struct path *path;
	if (!mnt)

	if (data_is == FSNOTIFY_EVENT_PATH)
		path = (struct path *)data;
	else if (data_is == FSNOTIFY_EVENT_FILE)
		path = &((struct file *)data)->f_path;
	else
		return false;
		return false;


	/* hook in this when mnt->mnt_fsnotify_mask is defined */
	/* hook in this when mnt->mnt_fsnotify_mask is defined */
@@ -184,6 +177,7 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const
{
{
	struct fsnotify_group *group;
	struct fsnotify_group *group;
	struct fsnotify_event *event = NULL;
	struct fsnotify_event *event = NULL;
	struct vfsmount *mnt = NULL;
	int idx;
	int idx;
	/* global tests shouldn't care about events on child only the specific event */
	/* global tests shouldn't care about events on child only the specific event */
	__u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
	__u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
@@ -198,10 +192,15 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const
	    !(test_mask & fsnotify_vfsmount_mask))
	    !(test_mask & fsnotify_vfsmount_mask))
                return;
                return;
 
 
	if (data_is == FSNOTIFY_EVENT_PATH)
		mnt = ((struct path *)data)->mnt;
	else if (data_is == FSNOTIFY_EVENT_FILE)
		mnt = ((struct file *)data)->f_path.mnt;

	/* if this inode's directed listeners don't care and nothing on the vfsmount
	/* if this inode's directed listeners don't care and nothing on the vfsmount
	 * listeners list cares, nothing to do */
	 * listeners list cares, nothing to do */
	if (!(test_mask & to_tell->i_fsnotify_mask) &&
	if (!(test_mask & to_tell->i_fsnotify_mask) &&
	    !needed_by_vfsmount(test_mask, data, data_is))
	    !needed_by_vfsmount(test_mask, mnt))
                return;
                return;


	/*
	/*
@@ -214,16 +213,16 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const
	if (test_mask & to_tell->i_fsnotify_mask) {
	if (test_mask & to_tell->i_fsnotify_mask) {
		list_for_each_entry_rcu(group, &fsnotify_inode_groups, inode_group_list) {
		list_for_each_entry_rcu(group, &fsnotify_inode_groups, inode_group_list) {
			if (test_mask & group->mask) {
			if (test_mask & group->mask) {
				send_to_group(mask, group, data, data_is,
				send_to_group(group, to_tell, NULL, mask, data, data_is,
					      file_name, cookie, &event, to_tell);
					      cookie, file_name, &event);
			}
			}
		}
		}
	}
	}
	if (needed_by_vfsmount(test_mask, data, data_is)) {
	if (needed_by_vfsmount(test_mask, mnt)) {
		list_for_each_entry_rcu(group, &fsnotify_vfsmount_groups, vfsmount_group_list) {
		list_for_each_entry_rcu(group, &fsnotify_vfsmount_groups, vfsmount_group_list) {
			if (test_mask & group->mask) {
			if (test_mask & group->mask) {
				send_to_group(mask, group, data, data_is,
				send_to_group(group, to_tell, mnt, mask, data, data_is,
					      file_name, cookie, &event, to_tell);
					      cookie, file_name, &event);
			}
			}
		}
		}
	}
	}
+2 −1
Original line number Original line Diff line number Diff line
@@ -141,7 +141,8 @@ static void inotify_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnot
}
}


static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode,
static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode,
				      __u32 mask, void *data, int data_type)
				      struct vfsmount *mnt, __u32 mask, void *data,
				      int data_type)
{
{
	struct fsnotify_mark_entry *entry;
	struct fsnotify_mark_entry *entry;
	bool send;
	bool send;
+2 −1
Original line number Original line Diff line number Diff line
@@ -79,7 +79,8 @@ struct fsnotify_event_private_data;
 */
 */
struct fsnotify_ops {
struct fsnotify_ops {
	bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,
	bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,
				  __u32 mask, void *data, int data_type);
				  struct vfsmount *mnt, __u32 mask, void *data,
				  int data_type);
	int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event);
	int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event);
	void (*free_group_priv)(struct fsnotify_group *group);
	void (*free_group_priv)(struct fsnotify_group *group);
	void (*freeing_mark)(struct fsnotify_mark_entry *entry, struct fsnotify_group *group);
	void (*freeing_mark)(struct fsnotify_mark_entry *entry, struct fsnotify_group *group);
+2 −1
Original line number Original line Diff line number Diff line
@@ -920,7 +920,8 @@ static void audit_tree_freeing_mark(struct fsnotify_mark_entry *entry, struct fs
}
}


static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode,
static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode,
				  __u32 mask, void *data, int data_type)
				  struct vfsmount *mnt, __u32 mask, void *data,
				  int data_type)
{
{
	return 0;
	return 0;
}
}
Loading