[RFC,3/4] fsnotify: return FSNOTIFY_DROPPED when handle_event() dropped event
diff mbox

Message ID 1482867148-31497-4-git-send-email-amir73il@gmail.com
State New
Headers show

Commit Message

Amir Goldstein Dec. 27, 2016, 7:32 p.m. UTC
The handle_event() op returns a negative value on error and 0 on success -
when event was either queued, merged, delivered (permission) or dropped.

Split the single success 0 value to 2 return values:

FSNOTIFY_DONE (0) indicates that the group has processed the event
(e.g. queued, merged, delivered), which may have also changed group
interenal state.
FSNOTIFY_DROPPED (1) indicates that event was not acted upon by group
nor did it change any group internal state.

This semantic difference matters in case there are several marks of the same
group (i.e. vfsmount_mark and inode_mark) that may process the same event.
If handle_event() with one of the marks returns FSNOTIFY_DONE, the event
won't be sent to the other group marks.
If handle_event() with one of the marks returns FSNOTIFY_DROPPED, the event
will be sent to the other group marks.

This change has no visible effects, because fsnotify() ignores non-negative
return values from handle_event().

Only fanotify_handle_event() and the common should_send_to_group() functions
were modified to return FSNOTIFY_DROPPED, because the rest of the backends
don't support vfsmount marks, so they are not aware of this semantic change.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify.c    |  6 +++---
 fs/notify/fsnotify.c             |  4 ++--
 include/linux/fsnotify_backend.h | 16 ++++++++++++++++
 3 files changed, 21 insertions(+), 5 deletions(-)

Patch
diff mbox

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index fc7658f8..9b26e2f 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -72,7 +72,7 @@  static int fanotify_get_response(struct fsnotify_group *group,
 	/* userspace responded, convert to something usable */
 	switch (event->response) {
 	case FAN_ALLOW:
-		ret = 0;
+		ret = FSNOTIFY_DONE;
 		break;
 	case FAN_DENY:
 	default:
@@ -193,7 +193,7 @@  static int fanotify_handle_event(struct fsnotify_group *group,
 
 	if (!fanotify_should_send_event(inode_mark, fanotify_mark, mask, data,
 					data_type))
-		return 0;
+		return FSNOTIFY_DROPPED;
 
 	pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode,
 		 mask);
@@ -210,7 +210,7 @@  static int fanotify_handle_event(struct fsnotify_group *group,
 		/* Our event wasn't used in the end. Free it. */
 		fsnotify_destroy_event(group, fsn_event);
 
-		return 0;
+		return FSNOTIFY_DONE;
 	}
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index b631df5..caed3c4 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -189,7 +189,7 @@  static int send_to_group(struct inode *to_tell,
 		 ignored_mask, data, data_is, cookie);
 
 	if (!inode_test_mask && !vfsmount_test_mask)
-		return 0;
+		return FSNOTIFY_DROPPED;
 
 	return group->ops->handle_event(group, to_tell, inode_mark,
 					vfsmount_mark, mask, data, data_is,
@@ -290,7 +290,7 @@  int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
 		ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
 				    data, data_is, cookie, file_name);
 
-		if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
+		if (ret < 0 && (mask & ALL_FSNOTIFY_PERM_EVENTS))
 			goto out;
 
 		if (inode_group)
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 0cf34d6..cbf9e92 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -81,6 +81,22 @@  struct fsnotify_event_private_data;
 struct fsnotify_fname;
 
 /*
+ * handle_event() may return a negative error value or one of the values below.
+ * FSNOTIFY_DONE indicates that the group has processed the event and that
+ * there is no need for the group to handle the same event again.
+ * FSNOTIFY_DROPPED indicates that event was not acted upon by group nor did
+ * it change any group internal state.
+ * This semantic difference matters in case there are several marks of the same
+ * group (i.e. vfsmount_mark and inode_mark) that may process the same event.
+ * If handle_event() with one of the marks returns FSNOTIFY_DONE, the event
+ * won't be sent to the other group marks.
+ * If handle_event() with one of the marks returns FSNOTIFY_DROPPED, the event
+ * will be sent to the other group marks.
+ */
+#define FSNOTIFY_DONE		0 /* group is done handling this event */
+#define FSNOTIFY_DROPPED	1 /* group did not handle this event */
+
+/*
  * Each group much define these ops.  The fsnotify infrastructure will call
  * these operations for each relevant group.
  *