return fanotify_info_equal(info1, info2);
}
-static bool fanotify_should_merge(struct fsnotify_event *old_fsn,
- struct fsnotify_event *new_fsn)
+static bool fanotify_should_merge(struct fanotify_event *old,
+ struct fanotify_event *new)
{
- struct fanotify_event *old, *new;
+ pr_debug("%s: old=%p new=%p\n", __func__, old, new);
- pr_debug("%s: old=%p new=%p\n", __func__, old_fsn, new_fsn);
- old = FANOTIFY_E(old_fsn);
- new = FANOTIFY_E(new_fsn);
-
- if (old_fsn->objectid != new_fsn->objectid ||
+ if (old->hash != new->hash ||
old->type != new->type || old->pid != new->pid)
return false;
static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
{
struct fsnotify_event *test_event;
- struct fanotify_event *new;
+ struct fanotify_event *old, *new = FANOTIFY_E(event);
pr_debug("%s: list=%p event=%p\n", __func__, list, event);
- new = FANOTIFY_E(event);
/*
* Don't merge a permission event with any other event so that we know
return 0;
list_for_each_entry_reverse(test_event, list, list) {
- if (fanotify_should_merge(test_event, event)) {
- FANOTIFY_E(test_event)->mask |= new->mask;
+ old = FANOTIFY_E(test_event);
+ if (fanotify_should_merge(old, new)) {
+ old->mask |= new->mask;
return 1;
}
}
struct mem_cgroup *old_memcg;
struct inode *child = NULL;
bool name_event = false;
+ unsigned int hash = 0;
if ((fid_mode & FAN_REPORT_DIR_FID) && dirid) {
/*
* Use the victim inode instead of the watching inode as the id for
* event queue, so event reported on parent is merged with event
* reported on child when both directory and child watches exist.
+ * Hash object id for queue merge.
*/
- fanotify_init_event(event, (unsigned long)id, mask);
+ hash = hash_ptr(id, FANOTIFY_EVENT_HASH_BITS);
+ fanotify_init_event(event, hash, mask);
if (FAN_GROUP_FLAG(group, FAN_REPORT_TID))
event->pid = get_pid(task_pid(current));
else
FANOTIFY_EVENT_TYPE_PATH,
FANOTIFY_EVENT_TYPE_PATH_PERM,
FANOTIFY_EVENT_TYPE_OVERFLOW, /* struct fanotify_event */
+ __FANOTIFY_EVENT_TYPE_NUM
};
+#define FANOTIFY_EVENT_TYPE_BITS \
+ (ilog2(__FANOTIFY_EVENT_TYPE_NUM - 1) + 1)
+#define FANOTIFY_EVENT_HASH_BITS \
+ (32 - FANOTIFY_EVENT_TYPE_BITS)
+
struct fanotify_event {
struct fsnotify_event fse;
u32 mask;
- enum fanotify_event_type type;
+ struct {
+ unsigned int type : FANOTIFY_EVENT_TYPE_BITS;
+ unsigned int hash : FANOTIFY_EVENT_HASH_BITS;
+ };
struct pid *pid;
};
static inline void fanotify_init_event(struct fanotify_event *event,
- unsigned long id, u32 mask)
+ unsigned int hash, u32 mask)
{
- fsnotify_init_event(&event->fse, id);
+ fsnotify_init_event(&event->fse);
+ event->hash = hash;
event->mask = mask;
event->pid = NULL;
}