diff options
author | Jan Kara <jack@suse.cz> | 2014-01-10 12:40:43 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2014-01-10 12:40:43 +1100 |
commit | 1c867760648dab7acf93086efcc9a5794fa80636 (patch) | |
tree | 0ecf4313e7e3147116e3960ce492327ceb1ea94f /kernel | |
parent | 02b764b4234c64af173f1d428ff2f1fb03a7ea5d (diff) |
fsnotify: do not share events between notification groups
Currently fsnotify framework creates one event structure for each
notification event and links this event into all interested notification
groups. This is done so that we save memory when several notification
groups are interested in the event. However the need for event structure
shared between inotify & fanotify bloats the event structure so the result
is often higher memory consumption.
Another problem is that fsnotify framework keeps path references with
outstanding events so that fanotify can return open file descriptors with
its events. This has the undesirable effect that filesystem cannot be
unmounted while there are outstanding events - a regression for inotify
compared to a situation before it was converted to fsnotify framework.
For fanotify this problem is hard to avoid and users of fanotify should
kind of expect this behavior when they ask for file descriptors from
notified files.
This patch changes fsnotify and its users to create separate event
structure for each group. This allows for much simpler code (~400 lines
removed by this patch) and also smaller event structures. For example on
64-bit system original struct fsnotify_event consumes 120 bytes, plus
additional space for file name, additional 24 bytes for second and each
subsequent group linking the event, and additional 32 bytes for each
inotify group for private data. After the conversion inotify event
consumes 48 bytes plus space for file name which is considerably less
memory unless file names are long and there are several groups interested
in the events (both of which are uncommon). Fanotify event fits in 56
bytes after the conversion (fanotify doesn't care about file names so its
events don't have to have it allocated). A win unless there are four or
more fanotify groups interested in the event.
The conversion also solves the problem with unmount when only inotify is
used as we don't have to grab path references for inotify events.
Signed-off-by: Jan Kara <jack@suse.cz>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Cc: Eric Paris <eparis@parisplace.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit_tree.c | 8 | ||||
-rw-r--r-- | kernel/audit_watch.c | 14 |
2 files changed, 12 insertions, 10 deletions
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 43c307dc9453..bcc0b1821227 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -912,9 +912,11 @@ static void evict_chunk(struct audit_chunk *chunk) } static int audit_tree_handle_event(struct fsnotify_group *group, + struct inode *to_tell, struct fsnotify_mark *inode_mark, - struct fsnotify_mark *vfsmonut_mark, - struct fsnotify_event *event) + struct fsnotify_mark *vfsmount_mark, + u32 mask, void *data, int data_type, + const unsigned char *file_name) { BUG(); return -EOPNOTSUPP; @@ -945,7 +947,7 @@ static const struct fsnotify_ops audit_tree_ops = { .handle_event = audit_tree_handle_event, .should_send_event = audit_tree_send_event, .free_group_priv = NULL, - .free_event_priv = NULL, + .free_event = NULL, .freeing_mark = audit_tree_freeing_mark, }; diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 22831c4d369c..a760c32cb639 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -475,25 +475,25 @@ static bool audit_watch_should_send_event(struct fsnotify_group *group, struct i /* Update watch data in audit rules based on fsnotify events. */ static int audit_watch_handle_event(struct fsnotify_group *group, + struct inode *to_tell, struct fsnotify_mark *inode_mark, struct fsnotify_mark *vfsmount_mark, - struct fsnotify_event *event) + u32 mask, void *data, int data_type, + const unsigned char *dname) { struct inode *inode; - __u32 mask = event->mask; - const char *dname = event->file_name; struct audit_parent *parent; parent = container_of(inode_mark, struct audit_parent, mark); BUG_ON(group != audit_watch_group); - switch (event->data_type) { + switch (data_type) { case (FSNOTIFY_EVENT_PATH): - inode = event->path.dentry->d_inode; + inode = ((struct path *)data)->dentry->d_inode; break; case (FSNOTIFY_EVENT_INODE): - inode = event->inode; + inode = (struct inode *)data; break; default: BUG(); @@ -516,7 +516,7 @@ static const struct fsnotify_ops audit_watch_fsnotify_ops = { .handle_event = audit_watch_handle_event, .free_group_priv = NULL, .freeing_mark = NULL, - .free_event_priv = NULL, + .free_event = NULL, }; static int __init audit_watch_init(void) |