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

Commit 1968f5ee authored by Eric Paris's avatar Eric Paris
Browse files

fanotify: use both marks when possible



fanotify currently, when given a vfsmount_mark will look up (if it exists)
the corresponding inode mark.  This patch drops that lookup and uses the
mark provided.

Signed-off-by: default avatarEric Paris <eparis@redhat.com>
parent ce8f76fb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -128,7 +128,7 @@ static int dnotify_handle_event(struct fsnotify_group *group,
 * userspace notification for that pair.
 */
static bool dnotify_should_send_event(struct fsnotify_group *group,
				      struct inode *inode, struct vfsmount *mnt,
				      struct inode *inode,
				      struct fsnotify_mark *inode_mark,
				      struct fsnotify_mark *vfsmount_mark,
				      __u32 mask, void *data, int data_type)
+34 −54
Original line number Diff line number Diff line
@@ -153,74 +153,54 @@ static int fanotify_handle_event(struct fsnotify_group *group,
	return ret;
}

static bool should_send_vfsmount_event(struct fsnotify_group *group,
				       struct vfsmount *mnt,
				       struct inode *inode,
				       struct fsnotify_mark *mnt_mark,
				       __u32 mask)
static bool fanotify_should_send_event(struct fsnotify_group *group,
				       struct inode *to_tell,
				       struct fsnotify_mark *inode_mark,
				       struct fsnotify_mark *vfsmnt_mark,
				       __u32 event_mask, void *data, int data_type)
{
	struct fsnotify_mark *inode_mark;

	pr_debug("%s: group=%p vfsmount=%p mark=%p mask=%x\n",
		 __func__, group, mnt, mnt_mark, mask);
	__u32 marks_mask, marks_ignored_mask;

	mask &= mnt_mark->mask;
	mask &= ~mnt_mark->ignored_mask;
	pr_debug("%s: group=%p to_tell=%p inode_mark=%p vfsmnt_mark=%p "
		 "mask=%x data=%p data_type=%d\n", __func__, group, to_tell,
		 inode_mark, vfsmnt_mark, event_mask, data, data_type);

	if (mask) {
		inode_mark = fsnotify_find_inode_mark(group, inode);
		if (inode_mark) {
			mask &= ~inode_mark->ignored_mask;
			fsnotify_put_mark(inode_mark);
		}
	}
	pr_debug("%s: group=%p vfsmount_mark=%p inode_mark=%p mask=%x\n",
		 __func__, group, vfsmnt_mark, inode_mark, event_mask);

	return mask;
}
	/* sorry, fanotify only gives a damn about files and dirs */
	if (!S_ISREG(to_tell->i_mode) &&
	    !S_ISDIR(to_tell->i_mode))
		return false;

static bool should_send_inode_event(struct fsnotify_group *group,
				    struct inode *inode,
				    struct fsnotify_mark *mark,
				    __u32 mask)
{
	pr_debug("%s: group=%p inode=%p mark=%p mask=%x\n",
		 __func__, group, inode, mark, mask);
	/* if we don't have enough info to send an event to userspace say no */
	if (data_type != FSNOTIFY_EVENT_FILE)
		return false;

	if (inode_mark && vfsmnt_mark) {
		marks_mask = (vfsmnt_mark->mask | inode_mark->mask);
		marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask);
	} else if (inode_mark) {
		/*
		 * if the event is for a child and this inode doesn't care about
		 * events on the child, don't send it!
		 */
	if ((mask & FS_EVENT_ON_CHILD) &&
	    !(mark->mask & FS_EVENT_ON_CHILD))
		if ((event_mask & FS_EVENT_ON_CHILD) &&
		    !(inode_mark->mask & FS_EVENT_ON_CHILD))
			return false;
	else
		return true;
		marks_mask = inode_mark->mask;
		marks_ignored_mask = inode_mark->ignored_mask;
	} else if (vfsmnt_mark) {
		marks_mask = vfsmnt_mark->mask;
		marks_ignored_mask = vfsmnt_mark->ignored_mask;
	} else {
		BUG();
	}

static bool fanotify_should_send_event(struct fsnotify_group *group,
				       struct inode *to_tell,
				       struct vfsmount *mnt,
				       struct fsnotify_mark *inode_mark,
				       struct fsnotify_mark *vfsmount_mark,
				       __u32 mask, void *data, int data_type)
{
	pr_debug("%s: group=%p to_tell=%p mnt=%p mask=%x data=%p data_type=%d\n",
		 __func__, group, to_tell, mnt, mask, data, data_type);

	/* sorry, fanotify only gives a damn about files and dirs */
	if (!S_ISREG(to_tell->i_mode) &&
	    !S_ISDIR(to_tell->i_mode))
		return false;
	if (event_mask & marks_mask & ~marks_ignored_mask)
		return true;

	/* if we don't have enough info to send an event to userspace say no */
	if (data_type != FSNOTIFY_EVENT_FILE)
	return false;

	if (mnt)
		return should_send_vfsmount_event(group, mnt, to_tell,
						  vfsmount_mark, mask);
	else
		return should_send_inode_event(group, to_tell, inode_mark, mask);
}

const struct fsnotify_ops fanotify_fsnotify_ops = {
+1 −1
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
	if (!inode_test_mask && !vfsmount_test_mask)
		return 0;

	if (group->ops->should_send_event(group, to_tell, mnt, inode_mark,
	if (group->ops->should_send_event(group, to_tell, inode_mark,
					  vfsmount_mark, mask, data,
					  data_is) == false)
		return 0;
+2 −2
Original line number Diff line number Diff line
@@ -142,11 +142,11 @@ static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify
}

static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode,
				      struct vfsmount *mnt, struct fsnotify_mark *mark,
				      struct fsnotify_mark *inode_mark,
				      struct fsnotify_mark *vfsmount_mark,
				      __u32 mask, void *data, int data_type)
{
	if ((mark->mask & FS_EXCL_UNLINK) &&
	if ((inode_mark->mask & FS_EXCL_UNLINK) &&
	    (data_type == FSNOTIFY_EVENT_FILE)) {
		struct file *file  = data;

+1 −1
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ struct fsnotify_event_private_data;
 */
struct fsnotify_ops {
	bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,
				  struct vfsmount *mnt, struct fsnotify_mark *inode_mark,
				  struct fsnotify_mark *inode_mark,
				  struct fsnotify_mark *vfsmount_mark,
				  __u32 mask, void *data, int data_type);
	int (*handle_event)(struct fsnotify_group *group,
Loading