[PATCH] fanotify support save thread id

From: nixiaoming
Date: Mon Sep 17 2018 - 06:02:10 EST


Added FAN_EVENT_INFO_TID to select the thread id of the event trigger

Signed-off-by: nixiaoming <nixiaoming@xxxxxxxxxx>
---
fs/notify/fanotify/fanotify.c | 66 +++++++++++++++++++++++++-------------
fs/notify/fanotify/fanotify.h | 2 +-
fs/notify/fanotify/fanotify_user.c | 4 +--
include/uapi/linux/fanotify.h | 1 +
4 files changed, 48 insertions(+), 25 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 94b5215..cf6ff4e 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -89,14 +89,36 @@ static int fanotify_get_response(struct fsnotify_group *group,
return ret;
}

+static void fanotify_iter_mask(struct fsnotify_iter_info *iter_info,
+ u32 event_mask, __u32 *marks_mask, __u32 *marks_ignored_mask)
+{
+ int type;
+ struct fsnotify_mark *mark;
+
+ fsnotify_foreach_obj_type(type) {
+ if (!fsnotify_iter_should_report_type(iter_info, type))
+ continue;
+ mark = iter_info->marks[type];
+ /*
+ * if the event is for a child and this inode doesn't care about
+ * events on the child, don't send it!
+ */
+ if (type == FSNOTIFY_OBJ_TYPE_INODE &&
+ (event_mask & FS_EVENT_ON_CHILD) &&
+ !(mark->mask & FS_EVENT_ON_CHILD))
+ continue;
+
+ *marks_mask |= mark->mask;
+ *marks_ignored_mask |= mark->ignored_mask;
+ }
+}
+
static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info,
u32 event_mask, const void *data,
int data_type)
{
__u32 marks_mask = 0, marks_ignored_mask = 0;
const struct path *path = data;
- struct fsnotify_mark *mark;
- int type;

pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
__func__, iter_info->report_mask, event_mask, data, data_type);
@@ -110,23 +132,7 @@ static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info,
!d_can_lookup(path->dentry))
return false;

- fsnotify_foreach_obj_type(type) {
- if (!fsnotify_iter_should_report_type(iter_info, type))
- continue;
- mark = iter_info->marks[type];
- /*
- * if the event is for a child and this inode doesn't care about
- * events on the child, don't send it!
- */
- if (type == FSNOTIFY_OBJ_TYPE_INODE &&
- (event_mask & FS_EVENT_ON_CHILD) &&
- !(mark->mask & FS_EVENT_ON_CHILD))
- continue;
-
- marks_mask |= mark->mask;
- marks_ignored_mask |= mark->ignored_mask;
- }
-
+ fanotify_iter_mask(iter_info, event_mask, &marks_mask, &marks_ignored_mask);
if (d_is_dir(path->dentry) &&
!(marks_mask & FS_ISDIR & ~marks_ignored_mask))
return false;
@@ -138,9 +144,20 @@ static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info,
return false;
}

+static bool fanotify_should_save_tid(struct fsnotify_iter_info *iter_info,
+ u32 event_mask)
+{
+ __u32 marks_mask = 0, marks_ignored_mask = 0;
+
+ fanotify_iter_mask(iter_info, event_mask, &marks_mask, &marks_ignored_mask);
+ if (marks_mask & FAN_EVENT_INFO_TID)
+ return true;
+ return false;
+}
+
struct fanotify_event_info *fanotify_alloc_event(struct fsnotify_group *group,
struct inode *inode, u32 mask,
- const struct path *path)
+ const struct path *path, bool should_save_tid)
{
struct fanotify_event_info *event = NULL;
gfp_t gfp = GFP_KERNEL_ACCOUNT;
@@ -171,7 +188,10 @@ struct fanotify_event_info *fanotify_alloc_event(struct fsnotify_group *group,
goto out;
init: __maybe_unused
fsnotify_init_event(&event->fse, inode, mask);
- event->tgid = get_pid(task_tgid(current));
+ if (should_save_tid)
+ event->tgid = get_pid(task_pid(current));
+ else
+ event->tgid = get_pid(task_tgid(current));
if (path) {
event->path = *path;
path_get(&event->path);
@@ -193,6 +213,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
int ret = 0;
struct fanotify_event_info *event;
struct fsnotify_event *fsn_event;
+ bool should_save_tid;

BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
@@ -219,8 +240,9 @@ static int fanotify_handle_event(struct fsnotify_group *group,
if (!fsnotify_prepare_user_wait(iter_info))
return 0;
}
+ should_save_tid = fanotify_should_save_tid(iter_info, mask);

- event = fanotify_alloc_event(group, inode, mask, data);
+ event = fanotify_alloc_event(group, inode, mask, data, should_save_tid);
ret = -ENOMEM;
if (unlikely(!event)) {
/*
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index 8609ba0..c303c574 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -54,4 +54,4 @@ static inline struct fanotify_event_info *FANOTIFY_E(struct fsnotify_event *fse)

struct fanotify_event_info *fanotify_alloc_event(struct fsnotify_group *group,
struct inode *inode, u32 mask,
- const struct path *path);
+ const struct path *path, bool should_save_tid);
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 6905488..99d431b 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -734,7 +734,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
atomic_inc(&user->fanotify_listeners);
group->memcg = get_mem_cgroup_from_mm(current->mm);

- oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL);
+ oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL, false);
if (unlikely(!oevent)) {
fd = -ENOMEM;
goto out_destroy_group;
@@ -805,7 +805,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
struct fsnotify_group *group;
struct fd f;
struct path path;
- u32 valid_mask = FAN_ALL_EVENTS | FAN_EVENT_ON_CHILD;
+ u32 valid_mask = FAN_ALL_EVENTS | FAN_EVENT_ON_CHILD | FAN_EVENT_INFO_TID;
int ret;

pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n",
diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h
index 7424791..d4fa336 100644
--- a/include/uapi/linux/fanotify.h
+++ b/include/uapi/linux/fanotify.h
@@ -18,6 +18,7 @@

#define FAN_ONDIR 0x40000000 /* event occurred against dir */

+#define FAN_EVENT_INFO_TID 0x02000000 /* event save thread id replace tgid */
#define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */

/* helper events */
--
2.10.1