From ae7b8f4108bcffb42173f867ce845268c7202d48 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 20:12:04 -0500 Subject: Audit: clean up the audit_watch split No real changes, just cleanup to the audit_watch split patch which we done with minimal code changes for easy review. Now fix interfaces to make things work better. Signed-off-by: Eric Paris --- kernel/audit_watch.c | 67 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 28 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 8df43696f4b..c2ca7168bfd 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -51,12 +51,12 @@ struct audit_watch { unsigned long ino; /* associated inode number */ struct audit_parent *parent; /* associated parent */ struct list_head wlist; /* entry in parent->watches list */ - struct list_head rules; /* associated rules */ + struct list_head rules; /* anchor for krule->rlist */ }; struct audit_parent { - struct list_head ilist; /* entry in inotify registration list */ - struct list_head watches; /* associated watches */ + struct list_head ilist; /* tmp list used to free parents */ + struct list_head watches; /* anchor for audit_watch->wlist */ struct inotify_watch wdata; /* inotify watch data */ unsigned flags; /* status flags */ }; @@ -78,13 +78,18 @@ struct inotify_handle *audit_ih; /* Inotify events we care about. */ #define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF -static void audit_free_parent(struct inotify_watch *i_watch) +static void audit_free_parent(struct audit_parent *parent) +{ + WARN_ON(!list_empty(&parent->watches)); + kfree(parent); +} + +static void audit_destroy_watch(struct inotify_watch *i_watch) { struct audit_parent *parent; parent = container_of(i_watch, struct audit_parent, wdata); - WARN_ON(!list_empty(&parent->watches)); - kfree(parent); + audit_free_parent(parent); } void audit_get_watch(struct audit_watch *watch) @@ -115,19 +120,11 @@ char *audit_watch_path(struct audit_watch *watch) return watch->path; } -struct list_head *audit_watch_rules(struct audit_watch *watch) +int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev) { - return &watch->rules; -} - -unsigned long audit_watch_inode(struct audit_watch *watch) -{ - return watch->ino; -} - -dev_t audit_watch_dev(struct audit_watch *watch) -{ - return watch->dev; + return (watch->ino != (unsigned long)-1) && + (watch->ino == ino) && + (watch->dev == dev); } /* Initialize a parent watch entry. */ @@ -149,7 +146,7 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp) wd = inotify_add_watch(audit_ih, &parent->wdata, ndp->path.dentry->d_inode, AUDIT_IN_WATCH); if (wd < 0) { - audit_free_parent(&parent->wdata); + audit_free_parent(parent); return ERR_PTR(wd); } @@ -251,15 +248,19 @@ static void audit_update_watch(struct audit_parent *parent, struct audit_entry *oentry, *nentry; mutex_lock(&audit_filter_mutex); + /* Run all of the watches on this parent looking for the one that + * matches the given dname */ list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) { if (audit_compare_dname_path(dname, owatch->path, NULL)) continue; /* If the update involves invalidating rules, do the inode-based * filtering now, so we don't omit records. */ - if (invalidating && current->audit_context) + if (invalidating && !audit_dummy_context()) audit_filter_inodes(current, current->audit_context); + /* updating ino will likely change which audit_hash_list we + * are on so we need a new watch for the new list */ nwatch = audit_dupe_watch(owatch); if (IS_ERR(nwatch)) { mutex_unlock(&audit_filter_mutex); @@ -275,12 +276,21 @@ static void audit_update_watch(struct audit_parent *parent, list_del(&oentry->rule.rlist); list_del_rcu(&oentry->list); - nentry = audit_dupe_rule(&oentry->rule, nwatch); + nentry = audit_dupe_rule(&oentry->rule); if (IS_ERR(nentry)) { list_del(&oentry->rule.list); audit_panic("error updating watch, removing"); } else { int h = audit_hash_ino((u32)ino); + + /* + * nentry->rule.watch == oentry->rule.watch so + * we must drop that reference and set it to our + * new watch. + */ + audit_put_watch(nentry->rule.watch); + audit_get_watch(nwatch); + nentry->rule.watch = nwatch; list_add(&nentry->rule.rlist, &nwatch->rules); list_add_rcu(&nentry->list, &audit_inode_hash[h]); list_replace(&oentry->rule.list, @@ -329,14 +339,14 @@ static void audit_remove_parent_watches(struct audit_parent *parent) /* Unregister inotify watches for parents on in_list. * Generates an IN_IGNORED event. */ -void audit_inotify_unregister(struct list_head *in_list) +void audit_watch_inotify_unregister(struct list_head *in_list) { struct audit_parent *p, *n; list_for_each_entry_safe(p, n, in_list, ilist) { list_del(&p->ilist); inotify_rm_watch(audit_ih, &p->wdata); - /* the unpin matching the pin in audit_do_del_rule() */ + /* the unpin matching the pin in audit_remove_watch_rule() */ unpin_inotify_watch(&p->wdata); } } @@ -423,13 +433,13 @@ static void audit_add_to_parent(struct audit_krule *krule, /* Find a matching watch entry, or add this one. * Caller must hold audit_filter_mutex. */ -int audit_add_watch(struct audit_krule *krule) +int audit_add_watch(struct audit_krule *krule, struct list_head **list) { struct audit_watch *watch = krule->watch; struct inotify_watch *i_watch; struct audit_parent *parent; struct nameidata *ndp = NULL, *ndw = NULL; - int ret = 0; + int h, ret = 0; mutex_unlock(&audit_filter_mutex); @@ -475,6 +485,8 @@ int audit_add_watch(struct audit_krule *krule) /* match get in audit_init_parent or inotify_find_watch */ put_inotify_watch(&parent->wdata); + h = audit_hash_ino((u32)watch->ino); + *list = &audit_inode_hash[h]; error: audit_put_nd(ndp, ndw); /* NULL args OK */ return ret; @@ -514,8 +526,7 @@ static void audit_handle_ievent(struct inotify_watch *i_watch, u32 wd, u32 mask, parent = container_of(i_watch, struct audit_parent, wdata); if (mask & (IN_CREATE|IN_MOVED_TO) && inode) - audit_update_watch(parent, dname, inode->i_sb->s_dev, - inode->i_ino, 0); + audit_update_watch(parent, dname, inode->i_sb->s_dev, inode->i_ino, 0); else if (mask & (IN_DELETE|IN_MOVED_FROM)) audit_update_watch(parent, dname, (dev_t)-1, (unsigned long)-1, 1); /* inotify automatically removes the watch and sends IN_IGNORED */ @@ -531,7 +542,7 @@ static void audit_handle_ievent(struct inotify_watch *i_watch, u32 wd, u32 mask, static const struct inotify_operations audit_inotify_ops = { .handle_event = audit_handle_ievent, - .destroy_watch = audit_free_parent, + .destroy_watch = audit_destroy_watch, }; static int __init audit_watch_init(void) -- cgit v1.2.3 From e9fd702a58c49dbb14481dca88dad44758da393a Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 20:12:04 -0500 Subject: audit: convert audit watches to use fsnotify instead of inotify Audit currently uses inotify to pin inodes in core and to detect when watched inodes are deleted or unmounted. This patch uses fsnotify instead of inotify. Signed-off-by: Eric Paris --- include/linux/fsnotify_backend.h | 5 +- kernel/audit_watch.c | 208 ++++++++++++++++++++++++++++----------- 2 files changed, 152 insertions(+), 61 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 4d6f47b5118..8f8341e9f02 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -58,9 +58,12 @@ FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE |\ FS_DELETE) +#define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO) + /* listeners that hard code group numbers near the top */ #define DNOTIFY_GROUP_NUM UINT_MAX -#define INOTIFY_GROUP_NUM (DNOTIFY_GROUP_NUM-1) +#define AUDIT_WATCH_GROUP_NUM (DNOTIFY_GROUP_NUM-1) +#define INOTIFY_GROUP_NUM (AUDIT_WATCH_GROUP_NUM-1) struct fsnotify_group; struct fsnotify_event; diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index c2ca7168bfd..ff5be849473 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -24,18 +24,18 @@ #include #include #include +#include #include #include #include #include -#include #include #include "audit.h" /* * Reference counting: * - * audit_parent: lifetime is from audit_init_parent() to receipt of an IN_IGNORED + * audit_parent: lifetime is from audit_init_parent() to receipt of an FS_IGNORED * event. Each audit_watch holds a reference to its associated parent. * * audit_watch: if added to lists, lifetime is from audit_init_watch() to @@ -57,26 +57,27 @@ struct audit_watch { struct audit_parent { struct list_head ilist; /* tmp list used to free parents */ struct list_head watches; /* anchor for audit_watch->wlist */ - struct inotify_watch wdata; /* inotify watch data */ + struct fsnotify_mark_entry mark; /* fsnotify mark on the inode */ unsigned flags; /* status flags */ }; -/* Inotify handle. */ -struct inotify_handle *audit_ih; +/* fsnotify handle. */ +struct fsnotify_group *audit_watch_group; /* * audit_parent status flags: * * AUDIT_PARENT_INVALID - set anytime rules/watches are auto-removed due to * a filesystem event to ensure we're adding audit watches to a valid parent. - * Technically not needed for IN_DELETE_SELF or IN_UNMOUNT events, as we cannot - * receive them while we have nameidata, but must be used for IN_MOVE_SELF which + * Technically not needed for FS_DELETE_SELF or FS_UNMOUNT events, as we cannot + * receive them while we have nameidata, but must be used for FS_MOVE_SELF which * we can receive while holding nameidata. */ #define AUDIT_PARENT_INVALID 0x001 -/* Inotify events we care about. */ -#define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF +/* fsnotify events we care about. */ +#define AUDIT_FS_WATCH (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\ + FS_MOVE_SELF | FS_EVENT_ON_CHILD) static void audit_free_parent(struct audit_parent *parent) { @@ -84,14 +85,45 @@ static void audit_free_parent(struct audit_parent *parent) kfree(parent); } -static void audit_destroy_watch(struct inotify_watch *i_watch) +static void audit_watch_free_mark(struct fsnotify_mark_entry *entry) { struct audit_parent *parent; - parent = container_of(i_watch, struct audit_parent, wdata); + parent = container_of(entry, struct audit_parent, mark); audit_free_parent(parent); } +static void audit_get_parent(struct audit_parent *parent) +{ + if (likely(parent)) + fsnotify_get_mark(&parent->mark); +} + +static void audit_put_parent(struct audit_parent *parent) +{ + if (likely(parent)) + fsnotify_put_mark(&parent->mark); +} + +/* + * Find and return the audit_parent on the given inode. If found a reference + * is taken on this parent. + */ +static inline struct audit_parent *audit_find_parent(struct inode *inode) +{ + struct audit_parent *parent = NULL; + struct fsnotify_mark_entry *entry; + + spin_lock(&inode->i_lock); + entry = fsnotify_find_mark_entry(audit_watch_group, inode); + spin_unlock(&inode->i_lock); + + if (entry) + parent = container_of(entry, struct audit_parent, mark); + + return parent; +} + void audit_get_watch(struct audit_watch *watch) { atomic_inc(&watch->count); @@ -110,7 +142,7 @@ void audit_put_watch(struct audit_watch *watch) void audit_remove_watch(struct audit_watch *watch) { list_del(&watch->wlist); - put_inotify_watch(&watch->parent->wdata); + audit_put_parent(watch->parent); watch->parent = NULL; audit_put_watch(watch); /* match initial get */ } @@ -130,8 +162,9 @@ int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev) /* Initialize a parent watch entry. */ static struct audit_parent *audit_init_parent(struct nameidata *ndp) { + struct inode *inode = ndp->path.dentry->d_inode; struct audit_parent *parent; - s32 wd; + int ret; parent = kzalloc(sizeof(*parent), GFP_KERNEL); if (unlikely(!parent)) @@ -140,14 +173,14 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp) INIT_LIST_HEAD(&parent->watches); parent->flags = 0; - inotify_init_watch(&parent->wdata); - /* grab a ref so inotify watch hangs around until we take audit_filter_mutex */ - get_inotify_watch(&parent->wdata); - wd = inotify_add_watch(audit_ih, &parent->wdata, - ndp->path.dentry->d_inode, AUDIT_IN_WATCH); - if (wd < 0) { + fsnotify_init_mark(&parent->mark, audit_watch_free_mark); + parent->mark.mask = AUDIT_FS_WATCH; + /* grab a ref so fsnotify mark hangs around until we take audit_filter_mutex */ + audit_get_parent(parent); + ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode); + if (ret < 0) { audit_free_parent(parent); - return ERR_PTR(wd); + return ERR_PTR(ret); } return parent; @@ -176,7 +209,7 @@ int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op) { struct audit_watch *watch; - if (!audit_ih) + if (!audit_watch_group) return -EOPNOTSUPP; if (path[0] != '/' || path[len-1] == '/' || @@ -214,7 +247,7 @@ static struct audit_watch *audit_dupe_watch(struct audit_watch *old) new->dev = old->dev; new->ino = old->ino; - get_inotify_watch(&old->parent->wdata); + audit_get_parent(old->parent); new->parent = old->parent; out: @@ -335,19 +368,21 @@ static void audit_remove_parent_watches(struct audit_parent *parent) audit_remove_watch(w); } mutex_unlock(&audit_filter_mutex); + + fsnotify_destroy_mark_by_entry(&parent->mark); } /* Unregister inotify watches for parents on in_list. - * Generates an IN_IGNORED event. */ + * Generates an FS_IGNORED event. */ void audit_watch_inotify_unregister(struct list_head *in_list) { struct audit_parent *p, *n; list_for_each_entry_safe(p, n, in_list, ilist) { list_del(&p->ilist); - inotify_rm_watch(audit_ih, &p->wdata); - /* the unpin matching the pin in audit_remove_watch_rule() */ - unpin_inotify_watch(&p->wdata); + fsnotify_destroy_mark_by_entry(&p->mark); + /* matches the get in audit_remove_watch_rule() */ + audit_put_parent(p); } } @@ -399,7 +434,7 @@ static void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw) } } -/* Associate the given rule with an existing parent inotify_watch. +/* Associate the given rule with an existing parent. * Caller must hold audit_filter_mutex. */ static void audit_add_to_parent(struct audit_krule *krule, struct audit_parent *parent) @@ -407,6 +442,8 @@ static void audit_add_to_parent(struct audit_krule *krule, struct audit_watch *w, *watch = krule->watch; int watch_found = 0; + BUG_ON(!mutex_is_locked(&audit_filter_mutex)); + list_for_each_entry(w, &parent->watches, wlist) { if (strcmp(watch->path, w->path)) continue; @@ -423,7 +460,7 @@ static void audit_add_to_parent(struct audit_krule *krule, } if (!watch_found) { - get_inotify_watch(&parent->wdata); + audit_get_parent(parent); watch->parent = parent; list_add(&watch->wlist, &parent->watches); @@ -436,7 +473,6 @@ static void audit_add_to_parent(struct audit_krule *krule, int audit_add_watch(struct audit_krule *krule, struct list_head **list) { struct audit_watch *watch = krule->watch; - struct inotify_watch *i_watch; struct audit_parent *parent; struct nameidata *ndp = NULL, *ndw = NULL; int h, ret = 0; @@ -462,8 +498,8 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list) * inotify watch is found, inotify_find_watch() grabs a reference before * returning. */ - if (inotify_find_watch(audit_ih, ndp->path.dentry->d_inode, - &i_watch) < 0) { + parent = audit_find_parent(ndp->path.dentry->d_inode); + if (!parent) { parent = audit_init_parent(ndp); if (IS_ERR(parent)) { /* caller expects mutex locked */ @@ -471,8 +507,7 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list) ret = PTR_ERR(parent); goto error; } - } else - parent = container_of(i_watch, struct audit_parent, wdata); + } mutex_lock(&audit_filter_mutex); @@ -482,8 +517,8 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list) else audit_add_to_parent(krule, parent); - /* match get in audit_init_parent or inotify_find_watch */ - put_inotify_watch(&parent->wdata); + /* match get in audit_find_parent or audit_init_parent */ + audit_put_parent(parent); h = audit_hash_ino((u32)watch->ino); *list = &audit_inode_hash[h]; @@ -504,52 +539,105 @@ void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list) audit_remove_watch(watch); if (list_empty(&parent->watches)) { - /* Put parent on the inotify un-registration - * list. Grab a reference before releasing + /* Put parent on the un-registration list. + * Grab a reference before releasing * audit_filter_mutex, to be released in - * audit_inotify_unregister(). + * audit_watch_inotify_unregister(). * If filesystem is going away, just leave * the sucker alone, eviction will take * care of it. */ - if (pin_inotify_watch(&parent->wdata)) - list_add(&parent->ilist, list); + audit_get_parent(parent); + list_add(&parent->ilist, list); } } } -/* Update watch data in audit rules based on inotify events. */ -static void audit_handle_ievent(struct inotify_watch *i_watch, u32 wd, u32 mask, - u32 cookie, const char *dname, struct inode *inode) +static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode, __u32 mask) { + struct fsnotify_mark_entry *entry; + bool send; + + spin_lock(&inode->i_lock); + entry = fsnotify_find_mark_entry(group, inode); + spin_unlock(&inode->i_lock); + if (!entry) + return false; + + mask = (mask & ~FS_EVENT_ON_CHILD); + send = (entry->mask & mask); + + /* find took a reference */ + fsnotify_put_mark(entry); + + return send; +} + +/* Update watch data in audit rules based on fsnotify events. */ +static int audit_watch_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) +{ + struct inode *inode; + __u32 mask = event->mask; + const char *dname = event->file_name; struct audit_parent *parent; - parent = container_of(i_watch, struct audit_parent, wdata); + BUG_ON(group != audit_watch_group); + + parent = audit_find_parent(event->to_tell); + if (unlikely(!parent)) + return 0; + + switch (event->data_type) { + case (FSNOTIFY_EVENT_PATH): + inode = event->path.dentry->d_inode; + break; + case (FSNOTIFY_EVENT_INODE): + inode = event->inode; + break; + default: + BUG(); + inode = NULL; + break; + }; - if (mask & (IN_CREATE|IN_MOVED_TO) && inode) + if (mask & (FS_CREATE|FS_MOVED_TO) && inode) audit_update_watch(parent, dname, inode->i_sb->s_dev, inode->i_ino, 0); - else if (mask & (IN_DELETE|IN_MOVED_FROM)) + else if (mask & (FS_DELETE|FS_MOVED_FROM)) audit_update_watch(parent, dname, (dev_t)-1, (unsigned long)-1, 1); - /* inotify automatically removes the watch and sends IN_IGNORED */ - else if (mask & (IN_DELETE_SELF|IN_UNMOUNT)) + else if (mask & (FS_DELETE_SELF|FS_UNMOUNT|FS_MOVE_SELF)) audit_remove_parent_watches(parent); - /* inotify does not remove the watch, so remove it manually */ - else if(mask & IN_MOVE_SELF) { - audit_remove_parent_watches(parent); - inotify_remove_watch_locked(audit_ih, i_watch); - } else if (mask & IN_IGNORED) - put_inotify_watch(i_watch); + /* moved put_inotify_watch to freeing mark */ + + /* matched the ref taken by audit_find_parent */ + audit_put_parent(parent); + + return 0; +} + +static void audit_watch_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group) +{ + struct audit_parent *parent; + + parent = container_of(entry, struct audit_parent, mark); + /* taken from audit_handle_ievent & FS_IGNORED please figure out what I match... */ + audit_put_parent(parent); } -static const struct inotify_operations audit_inotify_ops = { - .handle_event = audit_handle_ievent, - .destroy_watch = audit_destroy_watch, +static const struct fsnotify_ops audit_watch_fsnotify_ops = { + .should_send_event = audit_watch_should_send_event, + .handle_event = audit_watch_handle_event, + .free_group_priv = NULL, + .freeing_mark = audit_watch_freeing_mark, + .free_event_priv = NULL, }; static int __init audit_watch_init(void) { - audit_ih = inotify_init(&audit_inotify_ops); - if (IS_ERR(audit_ih)) - audit_panic("cannot initialize inotify handle"); + audit_watch_group = fsnotify_obtain_group(AUDIT_WATCH_GROUP_NUM, AUDIT_FS_WATCH, + &audit_watch_fsnotify_ops); + if (IS_ERR(audit_watch_group)) { + audit_watch_group = NULL; + audit_panic("cannot create audit fsnotify group"); + } return 0; } subsys_initcall(audit_watch_init); -- cgit v1.2.3 From e118e9c5638bbe877aa26b5cd2fd223cc24cdc8a Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 20:12:04 -0500 Subject: audit: redo audit watch locking and refcnt in light of fsnotify fsnotify can handle mutexes to be held across all fsnotify operations since it deals strickly in spinlocks. This can simplify and reduce some of the audit_filter_mutex taking and dropping. Signed-off-by: Eric Paris --- kernel/audit_watch.c | 45 +++++---------------------------------------- 1 file changed, 5 insertions(+), 40 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index ff5be849473..da66197e3ab 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -58,23 +58,11 @@ struct audit_parent { struct list_head ilist; /* tmp list used to free parents */ struct list_head watches; /* anchor for audit_watch->wlist */ struct fsnotify_mark_entry mark; /* fsnotify mark on the inode */ - unsigned flags; /* status flags */ }; /* fsnotify handle. */ struct fsnotify_group *audit_watch_group; -/* - * audit_parent status flags: - * - * AUDIT_PARENT_INVALID - set anytime rules/watches are auto-removed due to - * a filesystem event to ensure we're adding audit watches to a valid parent. - * Technically not needed for FS_DELETE_SELF or FS_UNMOUNT events, as we cannot - * receive them while we have nameidata, but must be used for FS_MOVE_SELF which - * we can receive while holding nameidata. - */ -#define AUDIT_PARENT_INVALID 0x001 - /* fsnotify events we care about. */ #define AUDIT_FS_WATCH (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\ FS_MOVE_SELF | FS_EVENT_ON_CHILD) @@ -171,12 +159,9 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp) return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&parent->watches); - parent->flags = 0; fsnotify_init_mark(&parent->mark, audit_watch_free_mark); parent->mark.mask = AUDIT_FS_WATCH; - /* grab a ref so fsnotify mark hangs around until we take audit_filter_mutex */ - audit_get_parent(parent); ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode); if (ret < 0) { audit_free_parent(parent); @@ -355,7 +340,6 @@ static void audit_remove_parent_watches(struct audit_parent *parent) struct audit_entry *e; mutex_lock(&audit_filter_mutex); - parent->flags |= AUDIT_PARENT_INVALID; list_for_each_entry_safe(w, nextw, &parent->watches, wlist) { list_for_each_entry_safe(r, nextr, &w->rules, rlist) { e = container_of(r, struct audit_entry, rule); @@ -487,35 +471,25 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list) goto error; } + mutex_lock(&audit_filter_mutex); + /* update watch filter fields */ if (ndw) { watch->dev = ndw->path.dentry->d_inode->i_sb->s_dev; watch->ino = ndw->path.dentry->d_inode->i_ino; } - /* The audit_filter_mutex must not be held during inotify calls because - * we hold it during inotify event callback processing. If an existing - * inotify watch is found, inotify_find_watch() grabs a reference before - * returning. - */ + /* either find an old parent or attach a new one */ parent = audit_find_parent(ndp->path.dentry->d_inode); if (!parent) { parent = audit_init_parent(ndp); if (IS_ERR(parent)) { - /* caller expects mutex locked */ - mutex_lock(&audit_filter_mutex); ret = PTR_ERR(parent); goto error; } } - mutex_lock(&audit_filter_mutex); - - /* parent was moved before we took audit_filter_mutex */ - if (parent->flags & AUDIT_PARENT_INVALID) - ret = -ENOENT; - else - audit_add_to_parent(krule, parent); + audit_add_to_parent(krule, parent); /* match get in audit_find_parent or audit_init_parent */ audit_put_parent(parent); @@ -613,20 +587,11 @@ static int audit_watch_handle_event(struct fsnotify_group *group, struct fsnotif return 0; } -static void audit_watch_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group) -{ - struct audit_parent *parent; - - parent = container_of(entry, struct audit_parent, mark); - /* taken from audit_handle_ievent & FS_IGNORED please figure out what I match... */ - audit_put_parent(parent); -} - static const struct fsnotify_ops audit_watch_fsnotify_ops = { .should_send_event = audit_watch_should_send_event, .handle_event = audit_watch_handle_event, .free_group_priv = NULL, - .freeing_mark = audit_watch_freeing_mark, + .freeing_mark = NULL, .free_event_priv = NULL, }; -- cgit v1.2.3 From a05fb6cc573130915380e00d182a4c6571cec6b2 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 20:12:05 -0500 Subject: audit: do not get and put just to free a watch deleting audit watch rules is not currently done under audit_filter_mutex. It was done this way because we could not hold the mutex during inotify manipulation. Since we are using fsnotify we don't need to do the extra get/put pair nor do we need the private list on which to store the parents while they are about to be freed. Signed-off-by: Eric Paris --- kernel/audit.h | 3 +-- kernel/audit_watch.c | 27 +++------------------------ kernel/auditfilter.c | 6 +----- 3 files changed, 5 insertions(+), 31 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/kernel/audit.h b/kernel/audit.h index 82c8a09099f..100b454a735 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -108,8 +108,7 @@ extern void audit_put_watch(struct audit_watch *watch); extern void audit_get_watch(struct audit_watch *watch); extern int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op); extern int audit_add_watch(struct audit_krule *krule, struct list_head **list); -extern void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list); -extern void audit_watch_inotify_unregister(struct list_head *in_list); +extern void audit_remove_watch_rule(struct audit_krule *krule); extern char *audit_watch_path(struct audit_watch *watch); extern int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev); extern struct audit_entry *audit_dupe_rule(struct audit_krule *old); diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index da66197e3ab..75ab53987ec 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -55,7 +55,6 @@ struct audit_watch { }; struct audit_parent { - struct list_head ilist; /* tmp list used to free parents */ struct list_head watches; /* anchor for audit_watch->wlist */ struct fsnotify_mark_entry mark; /* fsnotify mark on the inode */ }; @@ -356,20 +355,6 @@ static void audit_remove_parent_watches(struct audit_parent *parent) fsnotify_destroy_mark_by_entry(&parent->mark); } -/* Unregister inotify watches for parents on in_list. - * Generates an FS_IGNORED event. */ -void audit_watch_inotify_unregister(struct list_head *in_list) -{ - struct audit_parent *p, *n; - - list_for_each_entry_safe(p, n, in_list, ilist) { - list_del(&p->ilist); - fsnotify_destroy_mark_by_entry(&p->mark); - /* matches the get in audit_remove_watch_rule() */ - audit_put_parent(p); - } -} - /* Get path information necessary for adding watches. */ static int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw) { @@ -502,7 +487,7 @@ error: } -void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list) +void audit_remove_watch_rule(struct audit_krule *krule) { struct audit_watch *watch = krule->watch; struct audit_parent *parent = watch->parent; @@ -513,15 +498,9 @@ void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list) audit_remove_watch(watch); if (list_empty(&parent->watches)) { - /* Put parent on the un-registration list. - * Grab a reference before releasing - * audit_filter_mutex, to be released in - * audit_watch_inotify_unregister(). - * If filesystem is going away, just leave - * the sucker alone, eviction will take - * care of it. */ audit_get_parent(parent); - list_add(&parent->ilist, list); + fsnotify_destroy_mark_by_entry(&parent->mark); + audit_put_parent(parent); } } } diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index ac87577f36b..eb7675499fb 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -945,7 +945,6 @@ static inline int audit_del_rule(struct audit_entry *entry) struct audit_watch *watch = entry->rule.watch; struct audit_tree *tree = entry->rule.tree; struct list_head *list; - LIST_HEAD(inotify_unregister_list); int ret = 0; #ifdef CONFIG_AUDITSYSCALL int dont_count = 0; @@ -965,7 +964,7 @@ static inline int audit_del_rule(struct audit_entry *entry) } if (e->rule.watch) - audit_remove_watch_rule(&e->rule, &inotify_unregister_list); + audit_remove_watch_rule(&e->rule); if (e->rule.tree) audit_remove_tree_rule(&e->rule); @@ -983,9 +982,6 @@ static inline int audit_del_rule(struct audit_entry *entry) #endif mutex_unlock(&audit_filter_mutex); - if (!list_empty(&inotify_unregister_list)) - audit_watch_inotify_unregister(&inotify_unregister_list); - out: if (watch) audit_put_watch(watch); /* match initial get */ -- cgit v1.2.3 From 40554c3dae83bd892b7fbfaa2ea9de739cbcf065 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 20:12:05 -0500 Subject: fsnotify: allow addition of duplicate fsnotify marks This patch allows a task to add a second fsnotify mark to an inode for the same group. This mark will be added to the end of the inode's list and this will never be found by the stand fsnotify_find_mark() function. This is useful if a user wants to add a new mark before removing the old one. Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 2 +- fs/notify/inode_mark.c | 8 +++++--- fs/notify/inotify/inotify_user.c | 2 +- include/linux/fsnotify_backend.h | 2 +- kernel/audit_watch.c | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 7e54e52964d..85b97fca14d 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -362,7 +362,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) dnentry = container_of(entry, struct dnotify_mark_entry, fsn_entry); spin_lock(&entry->lock); } else { - fsnotify_add_mark(new_entry, dnotify_group, inode); + fsnotify_add_mark(new_entry, dnotify_group, inode, 0); spin_lock(&new_entry->lock); entry = new_entry; dnentry = new_dnentry; diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index a13cf9e9233..7d2962e5328 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -312,9 +312,10 @@ void fsnotify_init_mark(struct fsnotify_mark_entry *entry, * event types should be delivered to which group and for which inodes. */ int fsnotify_add_mark(struct fsnotify_mark_entry *entry, - struct fsnotify_group *group, struct inode *inode) + struct fsnotify_group *group, struct inode *inode, + int allow_dups) { - struct fsnotify_mark_entry *lentry; + struct fsnotify_mark_entry *lentry = NULL; int ret = 0; inode = igrab(inode); @@ -331,7 +332,8 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry, spin_lock(&group->mark_lock); spin_lock(&inode->i_lock); - lentry = fsnotify_find_mark_entry(group, inode); + if (!allow_dups) + lentry = fsnotify_find_mark_entry(group, inode); if (!lentry) { entry->group = group; entry->inode = inode; diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 653c507b1bb..f22a04005db 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -651,7 +651,7 @@ static int inotify_new_watch(struct fsnotify_group *group, goto out_err; /* we are on the idr, now get on the inode */ - ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode); + ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode, 0); if (ret) { /* we failed to get on the inode, get off the idr */ inotify_remove_from_idr(group, tmp_ientry); diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 39051673295..1679f250d59 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -345,7 +345,7 @@ extern struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_grou /* copy the values from old into new */ extern void fsnotify_duplicate_mark(struct fsnotify_mark_entry *new, struct fsnotify_mark_entry *old); /* attach the mark to both the group and the inode */ -extern int fsnotify_add_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group, struct inode *inode); +extern int fsnotify_add_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group, struct inode *inode, int allow_dups); /* given a mark, flag it to be freed when all references are dropped */ extern void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry); /* run all the marks in a group, and flag them to be freed */ diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 75ab53987ec..c44de0c4fc4 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -161,7 +161,7 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp) fsnotify_init_mark(&parent->mark, audit_watch_free_mark); parent->mark.mask = AUDIT_FS_WATCH; - ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode); + ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode, 0); if (ret < 0) { audit_free_parent(parent); return ERR_PTR(ret); -- cgit v1.2.3 From 1a3aedbce416dfdbd5d5ac14a0edbcf21a62ee50 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 20:12:06 -0500 Subject: Audit: audit watch init should not be before fsnotify init Audit watch init and fsnotify init both use subsys_initcall() but since the audit watch code is linked in before the fsnotify code the audit watch code would be using the fsnotify srcu struct before it was initialized. This patch fixes that problem by moving audit watch init to device_initcall() so it happens after fsnotify is ready. Reported-by: Stephen Rothwell Signed-off-by: Eric Paris Tested-by : Sachin Sant --- kernel/audit_watch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/audit_watch.c') diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index c44de0c4fc4..f8543a41115 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -584,4 +584,4 @@ static int __init audit_watch_init(void) } return 0; } -subsys_initcall(audit_watch_init); +device_initcall(audit_watch_init); -- cgit v1.2.3 From 7b0a04fbfb35650941af87728d4891515b4fc179 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 21:24:21 -0500 Subject: fsnotify: provide the data type to should_send_event fanotify is only interested in event types which contain enough information to open the original file in the context of the fanotify listener. Since fanotify may not want to send events if that data isn't present we pass the data type to the should_send_event function call so fanotify can express its lack of interest. Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 3 ++- fs/notify/fsnotify.c | 2 +- fs/notify/inotify/inotify_fsnotify.c | 3 ++- include/linux/fsnotify_backend.h | 3 ++- kernel/audit_tree.c | 3 ++- kernel/audit_watch.c | 3 ++- 6 files changed, 11 insertions(+), 6 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 85b97fca14d..6f30f496e23 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -133,7 +133,8 @@ 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, __u32 mask) + struct inode *inode, __u32 mask, + int data_type) { struct fsnotify_mark_entry *entry; bool send; diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index fcc2f064af8..fc06e478939 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -157,7 +157,7 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const idx = srcu_read_lock(&fsnotify_grp_srcu); list_for_each_entry_rcu(group, &fsnotify_groups, group_list) { if (test_mask & group->mask) { - if (!group->ops->should_send_event(group, to_tell, mask)) + if (!group->ops->should_send_event(group, to_tell, mask, data_is)) continue; if (!event) { event = fsnotify_create_event(to_tell, mask, data, diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index e27960cd76a..fc7c4952e6a 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -86,7 +86,8 @@ static void inotify_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnot inotify_ignored_and_remove_idr(entry, group); } -static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode, __u32 mask) +static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode, + __u32 mask, int data_type) { struct fsnotify_mark_entry *entry; bool send; diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index e2528437102..61aed0c54fe 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -84,7 +84,8 @@ struct fsnotify_event_private_data; * valid group and inode to use to clean up. */ struct fsnotify_ops { - bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode, __u32 mask); + bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode, + __u32 mask, int data_type); int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event); void (*free_group_priv)(struct fsnotify_group *group); void (*freeing_mark)(struct fsnotify_mark_entry *entry, struct fsnotify_group *group); diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index a164600dd82..b5417cd6521 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -919,7 +919,8 @@ static void audit_tree_freeing_mark(struct fsnotify_mark_entry *entry, struct fs fsnotify_put_mark(entry); } -static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode, __u32 mask) +static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode, + __u32 mask, int data_type) { return 0; } diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index f8543a41115..67d8f2f5287 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -505,7 +505,8 @@ void audit_remove_watch_rule(struct audit_krule *krule) } } -static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode, __u32 mask) +static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode, + __u32 mask, int data_type) { struct fsnotify_mark_entry *entry; bool send; -- cgit v1.2.3 From 8112e2d6a7356e8c3ff1f7f3c86f375ed0305705 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 21:24:21 -0500 Subject: fsnotify: include data in should_send calls fanotify is going to need to look at file->private_data to know if an event should be sent or not. This passes the data (which might be a file, dentry, inode, or none) to the should_send function calls so fanotify can get that information when available Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 2 +- fs/notify/fsnotify.c | 3 ++- fs/notify/inotify/inotify_fsnotify.c | 2 +- include/linux/fsnotify_backend.h | 2 +- kernel/audit_tree.c | 2 +- kernel/audit_watch.c | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 6f30f496e23..a213b83a59c 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -134,7 +134,7 @@ static int dnotify_handle_event(struct fsnotify_group *group, */ static bool dnotify_should_send_event(struct fsnotify_group *group, struct inode *inode, __u32 mask, - int data_type) + void *data, int data_type) { struct fsnotify_mark_entry *entry; bool send; diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index fc06e478939..523337b600a 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -157,7 +157,8 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const idx = srcu_read_lock(&fsnotify_grp_srcu); list_for_each_entry_rcu(group, &fsnotify_groups, group_list) { if (test_mask & group->mask) { - if (!group->ops->should_send_event(group, to_tell, mask, data_is)) + if (!group->ops->should_send_event(group, to_tell, mask, + data, data_is)) continue; if (!event) { event = fsnotify_create_event(to_tell, mask, data, diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index fc7c4952e6a..1f33234cc30 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -87,7 +87,7 @@ static void inotify_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnot } static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode, - __u32 mask, int data_type) + __u32 mask, void *data, int data_type) { struct fsnotify_mark_entry *entry; bool send; diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 61aed0c54fe..2766df67f1e 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -85,7 +85,7 @@ struct fsnotify_event_private_data; */ struct fsnotify_ops { bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode, - __u32 mask, int data_type); + __u32 mask, void *data, int data_type); int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event); void (*free_group_priv)(struct fsnotify_group *group); void (*freeing_mark)(struct fsnotify_mark_entry *entry, struct fsnotify_group *group); diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index b5417cd6521..e3d63b596ef 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -920,7 +920,7 @@ static void audit_tree_freeing_mark(struct fsnotify_mark_entry *entry, struct fs } static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode, - __u32 mask, int data_type) + __u32 mask, void *data, int data_type) { return 0; } diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 67d8f2f5287..85c43aa292e 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -506,7 +506,7 @@ void audit_remove_watch_rule(struct audit_krule *krule) } static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode, - __u32 mask, int data_type) + __u32 mask, void *data, int data_type) { struct fsnotify_mark_entry *entry; bool send; -- cgit v1.2.3 From 74be0cc82835aecad332a29896b0f212ba893403 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 21:24:22 -0500 Subject: fsnotify: remove group_num altogether The original fsnotify interface has a group-num which was intended to be able to find a group after it was added. I no longer think this is a necessary thing to do and so we remove the group_num. Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 3 +-- fs/notify/group.c | 48 ++-------------------------------------- fs/notify/inotify/inotify_user.c | 11 +-------- include/linux/fsnotify_backend.h | 10 +-------- kernel/audit_tree.c | 3 +-- kernel/audit_watch.c | 2 +- 6 files changed, 7 insertions(+), 70 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index a213b83a59c..1f46aeac338 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -433,8 +433,7 @@ static int __init dnotify_init(void) dnotify_struct_cache = KMEM_CACHE(dnotify_struct, SLAB_PANIC); dnotify_mark_entry_cache = KMEM_CACHE(dnotify_mark_entry, SLAB_PANIC); - dnotify_group = fsnotify_obtain_group(DNOTIFY_GROUP_NUM, - 0, &dnotify_fsnotify_ops); + dnotify_group = fsnotify_obtain_group(0, &dnotify_fsnotify_ops); if (IS_ERR(dnotify_group)) panic("unable to allocate fsnotify group for dnotify\n"); return 0; diff --git a/fs/notify/group.c b/fs/notify/group.c index 777ca821225..62fb8961a57 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c @@ -77,15 +77,6 @@ void fsnotify_recalc_group_mask(struct fsnotify_group *group) fsnotify_recalc_global_mask(); } -/* - * Take a reference to a group so things found under the fsnotify_grp_mutex - * can't get freed under us - */ -static void fsnotify_get_group(struct fsnotify_group *group) -{ - atomic_inc(&group->refcnt); -} - /* * Final freeing of a group */ @@ -170,41 +161,15 @@ void fsnotify_put_group(struct fsnotify_group *group) fsnotify_destroy_group(group); } -/* - * Simply run the fsnotify_groups list and find a group which matches - * the given parameters. If a group is found we take a reference to that - * group. - */ -static struct fsnotify_group *fsnotify_find_group(unsigned int group_num, __u32 mask, - const struct fsnotify_ops *ops) -{ - struct fsnotify_group *group_iter; - struct fsnotify_group *group = NULL; - - BUG_ON(!mutex_is_locked(&fsnotify_grp_mutex)); - - list_for_each_entry_rcu(group_iter, &fsnotify_groups, group_list) { - if (group_iter->group_num == group_num) { - if ((group_iter->mask == mask) && - (group_iter->ops == ops)) { - fsnotify_get_group(group_iter); - group = group_iter; - } else - group = ERR_PTR(-EEXIST); - } - } - return group; -} - /* * Either finds an existing group which matches the group_num, mask, and ops or * creates a new group and adds it to the global group list. In either case we * take a reference for the group returned. */ -struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, __u32 mask, +struct fsnotify_group *fsnotify_obtain_group(__u32 mask, const struct fsnotify_ops *ops) { - struct fsnotify_group *group, *tgroup; + struct fsnotify_group *group; /* very low use, simpler locking if we just always alloc */ group = kzalloc(sizeof(struct fsnotify_group), GFP_KERNEL); @@ -214,7 +179,6 @@ struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, __u32 mask, atomic_set(&group->refcnt, 1); group->on_group_list = 0; - group->group_num = group_num; group->mask = mask; mutex_init(&group->notification_mutex); @@ -230,14 +194,6 @@ struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, __u32 mask, group->ops = ops; mutex_lock(&fsnotify_grp_mutex); - tgroup = fsnotify_find_group(group_num, mask, ops); - if (tgroup) { - /* group already exists */ - mutex_unlock(&fsnotify_grp_mutex); - /* destroy the new one we made */ - fsnotify_put_group(group); - return tgroup; - } /* group not found, add a new one */ list_add_rcu(&group->group_list, &fsnotify_groups); diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index cbe16df326f..cae317f5bd9 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -51,12 +51,6 @@ int inotify_max_user_watches __read_mostly; static struct kmem_cache *inotify_inode_mark_cachep __read_mostly; struct kmem_cache *event_priv_cachep __read_mostly; -/* - * When inotify registers a new group it increments this and uses that - * value as an offset to set the fsnotify group "name" and priority. - */ -static atomic_t inotify_grp_num; - #ifdef CONFIG_SYSCTL #include @@ -700,11 +694,8 @@ retry: static struct fsnotify_group *inotify_new_group(struct user_struct *user, unsigned int max_events) { struct fsnotify_group *group; - unsigned int grp_num; - /* fsnotify_obtain_group took a reference to group, we put this when we kill the file in the end */ - grp_num = (INOTIFY_GROUP_NUM - atomic_inc_return(&inotify_grp_num)); - group = fsnotify_obtain_group(grp_num, 0, &inotify_fsnotify_ops); + group = fsnotify_obtain_group(0, &inotify_fsnotify_ops); if (IS_ERR(group)) return group; diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 427f6ffab12..57e503d017c 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -60,12 +60,6 @@ #define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO) -/* listeners that hard code group numbers near the top */ -#define DNOTIFY_GROUP_NUM UINT_MAX -#define AUDIT_WATCH_GROUP_NUM (DNOTIFY_GROUP_NUM-1) -#define AUDIT_TREE_GROUP_NUM (AUDIT_WATCH_GROUP_NUM-1) -#define INOTIFY_GROUP_NUM (AUDIT_TREE_GROUP_NUM-1) - struct fsnotify_group; struct fsnotify_event; struct fsnotify_mark_entry; @@ -124,7 +118,6 @@ struct fsnotify_group { * closed. */ atomic_t refcnt; /* things with interest in this group */ - unsigned int group_num; /* simply prevents accidental group collision */ const struct fsnotify_ops *ops; /* how this group handles things */ @@ -312,8 +305,7 @@ static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode /* must call when a group changes its ->mask */ extern void fsnotify_recalc_global_mask(void); /* get a reference to an existing or create a new group */ -extern struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, - __u32 mask, +extern struct fsnotify_group *fsnotify_obtain_group(__u32 mask, const struct fsnotify_ops *ops); /* run all marks associated with this group and update group->mask */ extern void fsnotify_recalc_group_mask(struct fsnotify_group *group); diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index e3d63b596ef..59065e72a2e 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -937,8 +937,7 @@ static int __init audit_tree_init(void) { int i; - audit_tree_group = fsnotify_obtain_group(AUDIT_TREE_GROUP_NUM, - 0, &audit_tree_ops); + audit_tree_group = fsnotify_obtain_group(0, &audit_tree_ops); if (IS_ERR(audit_tree_group)) audit_panic("cannot initialize fsnotify group for rectree watches"); diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 85c43aa292e..c500104d38c 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -577,7 +577,7 @@ static const struct fsnotify_ops audit_watch_fsnotify_ops = { static int __init audit_watch_init(void) { - audit_watch_group = fsnotify_obtain_group(AUDIT_WATCH_GROUP_NUM, AUDIT_FS_WATCH, + audit_watch_group = fsnotify_obtain_group(AUDIT_FS_WATCH, &audit_watch_fsnotify_ops); if (IS_ERR(audit_watch_group)) { audit_watch_group = NULL; -- cgit v1.2.3 From ffab83402f01555a5fa32efb48a4dd0ce8d12ef5 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 21:24:22 -0500 Subject: fsnotify: fsnotify_obtain_group should be fsnotify_alloc_group fsnotify_obtain_group was intended to be able to find an already existing group. Nothing uses that functionality. This just renames it to fsnotify_alloc_group so it is clear what it is doing. Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 2 +- fs/notify/group.c | 10 +++------- fs/notify/inotify/inotify_user.c | 2 +- include/linux/fsnotify_backend.h | 4 ++-- kernel/audit_tree.c | 2 +- kernel/audit_watch.c | 4 ++-- 6 files changed, 10 insertions(+), 14 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 1f46aeac338..51e4fe33d6b 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -433,7 +433,7 @@ static int __init dnotify_init(void) dnotify_struct_cache = KMEM_CACHE(dnotify_struct, SLAB_PANIC); dnotify_mark_entry_cache = KMEM_CACHE(dnotify_mark_entry, SLAB_PANIC); - dnotify_group = fsnotify_obtain_group(0, &dnotify_fsnotify_ops); + dnotify_group = fsnotify_alloc_group(0, &dnotify_fsnotify_ops); if (IS_ERR(dnotify_group)) panic("unable to allocate fsnotify group for dnotify\n"); return 0; diff --git a/fs/notify/group.c b/fs/notify/group.c index 934860e9809..1d20d26d5fe 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c @@ -162,16 +162,13 @@ void fsnotify_put_group(struct fsnotify_group *group) } /* - * Either finds an existing group which matches the group_num, mask, and ops or - * creates a new group and adds it to the global group list. In either case we - * take a reference for the group returned. + * Create a new fsnotify_group and hold a reference for the group returned. */ -struct fsnotify_group *fsnotify_obtain_group(__u32 mask, - const struct fsnotify_ops *ops) +struct fsnotify_group *fsnotify_alloc_group(__u32 mask, + const struct fsnotify_ops *ops) { struct fsnotify_group *group; - /* very low use, simpler locking if we just always alloc */ group = kzalloc(sizeof(struct fsnotify_group), GFP_KERNEL); if (!group) return ERR_PTR(-ENOMEM); @@ -192,7 +189,6 @@ struct fsnotify_group *fsnotify_obtain_group(__u32 mask, mutex_lock(&fsnotify_grp_mutex); - /* group not found, add a new one */ list_add_rcu(&group->group_list, &fsnotify_groups); group->on_group_list = 1; /* being on the fsnotify_groups list holds one num_marks */ diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index cae317f5bd9..25a2854186e 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -695,7 +695,7 @@ static struct fsnotify_group *inotify_new_group(struct user_struct *user, unsign { struct fsnotify_group *group; - group = fsnotify_obtain_group(0, &inotify_fsnotify_ops); + group = fsnotify_alloc_group(0, &inotify_fsnotify_ops); if (IS_ERR(group)) return group; diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 57e503d017c..7d3c03e4686 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -305,11 +305,11 @@ static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode /* must call when a group changes its ->mask */ extern void fsnotify_recalc_global_mask(void); /* get a reference to an existing or create a new group */ -extern struct fsnotify_group *fsnotify_obtain_group(__u32 mask, +extern struct fsnotify_group *fsnotify_alloc_group(__u32 mask, const struct fsnotify_ops *ops); /* run all marks associated with this group and update group->mask */ extern void fsnotify_recalc_group_mask(struct fsnotify_group *group); -/* drop reference on a group from fsnotify_obtain_group */ +/* drop reference on a group from fsnotify_alloc_group */ extern void fsnotify_put_group(struct fsnotify_group *group); /* take a reference to an event */ diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 59065e72a2e..813274d4eda 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -937,7 +937,7 @@ static int __init audit_tree_init(void) { int i; - audit_tree_group = fsnotify_obtain_group(0, &audit_tree_ops); + audit_tree_group = fsnotify_alloc_group(0, &audit_tree_ops); if (IS_ERR(audit_tree_group)) audit_panic("cannot initialize fsnotify group for rectree watches"); diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index c500104d38c..0f03a6ab96e 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -577,8 +577,8 @@ static const struct fsnotify_ops audit_watch_fsnotify_ops = { static int __init audit_watch_init(void) { - audit_watch_group = fsnotify_obtain_group(AUDIT_FS_WATCH, - &audit_watch_fsnotify_ops); + audit_watch_group = fsnotify_alloc_group(AUDIT_FS_WATCH, + &audit_watch_fsnotify_ops); if (IS_ERR(audit_watch_group)) { audit_watch_group = NULL; audit_panic("cannot create audit fsnotify group"); -- cgit v1.2.3 From 220d14df0dc587c06b97762829a41157c9375b94 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 21:24:22 -0500 Subject: Audit: only set group mask when something is being watched Currently the audit watch group always sets a mask equal to all events it might care about. We instead should only set the group mask if we are actually watching inodes. This should be a perf win when audit watches are compiled in. Signed-off-by: Eric Paris --- kernel/audit_watch.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 0f03a6ab96e..87408b28211 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -167,6 +167,8 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp) return ERR_PTR(ret); } + fsnotify_recalc_group_mask(audit_watch_group); + return parent; } @@ -353,6 +355,9 @@ static void audit_remove_parent_watches(struct audit_parent *parent) mutex_unlock(&audit_filter_mutex); fsnotify_destroy_mark_by_entry(&parent->mark); + + fsnotify_recalc_group_mask(audit_watch_group); + } /* Get path information necessary for adding watches. */ @@ -503,6 +508,9 @@ void audit_remove_watch_rule(struct audit_krule *krule) audit_put_parent(parent); } } + + fsnotify_recalc_group_mask(audit_watch_group); + } static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode, @@ -577,8 +585,7 @@ static const struct fsnotify_ops audit_watch_fsnotify_ops = { static int __init audit_watch_init(void) { - audit_watch_group = fsnotify_alloc_group(AUDIT_FS_WATCH, - &audit_watch_fsnotify_ops); + audit_watch_group = fsnotify_alloc_group(0, &audit_watch_fsnotify_ops); if (IS_ERR(audit_watch_group)) { audit_watch_group = NULL; audit_panic("cannot create audit fsnotify group"); -- cgit v1.2.3 From 0d2e2a1d00d7d23e5bd9bb0935cde7c3d5835c56 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 21:24:22 -0500 Subject: fsnotify: drop mask argument from fsnotify_alloc_group Nothing uses the mask argument to fsnotify_alloc_group. This patch drops that argument. Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 2 +- fs/notify/group.c | 8 +------- fs/notify/inotify/inotify_user.c | 2 +- include/linux/fsnotify_backend.h | 3 +-- kernel/audit_tree.c | 2 +- kernel/audit_watch.c | 2 +- 6 files changed, 6 insertions(+), 13 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 51e4fe33d6b..e0a847bd53b 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -433,7 +433,7 @@ static int __init dnotify_init(void) dnotify_struct_cache = KMEM_CACHE(dnotify_struct, SLAB_PANIC); dnotify_mark_entry_cache = KMEM_CACHE(dnotify_mark_entry, SLAB_PANIC); - dnotify_group = fsnotify_alloc_group(0, &dnotify_fsnotify_ops); + dnotify_group = fsnotify_alloc_group(&dnotify_fsnotify_ops); if (IS_ERR(dnotify_group)) panic("unable to allocate fsnotify group for dnotify\n"); return 0; diff --git a/fs/notify/group.c b/fs/notify/group.c index 1d20d26d5fe..1657349c30a 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c @@ -164,8 +164,7 @@ void fsnotify_put_group(struct fsnotify_group *group) /* * Create a new fsnotify_group and hold a reference for the group returned. */ -struct fsnotify_group *fsnotify_alloc_group(__u32 mask, - const struct fsnotify_ops *ops) +struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) { struct fsnotify_group *group; @@ -175,8 +174,6 @@ struct fsnotify_group *fsnotify_alloc_group(__u32 mask, atomic_set(&group->refcnt, 1); - group->mask = mask; - mutex_init(&group->notification_mutex); INIT_LIST_HEAD(&group->notification_list); init_waitqueue_head(&group->notification_waitq); @@ -196,8 +193,5 @@ struct fsnotify_group *fsnotify_alloc_group(__u32 mask, mutex_unlock(&fsnotify_grp_mutex); - if (mask) - fsnotify_recalc_global_mask(); - return group; } diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 25a2854186e..a48d68a68b2 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -695,7 +695,7 @@ static struct fsnotify_group *inotify_new_group(struct user_struct *user, unsign { struct fsnotify_group *group; - group = fsnotify_alloc_group(0, &inotify_fsnotify_ops); + group = fsnotify_alloc_group(&inotify_fsnotify_ops); if (IS_ERR(group)) return group; diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 7d3c03e4686..58326049ab2 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -305,8 +305,7 @@ static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode /* must call when a group changes its ->mask */ extern void fsnotify_recalc_global_mask(void); /* get a reference to an existing or create a new group */ -extern struct fsnotify_group *fsnotify_alloc_group(__u32 mask, - const struct fsnotify_ops *ops); +extern struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops); /* run all marks associated with this group and update group->mask */ extern void fsnotify_recalc_group_mask(struct fsnotify_group *group); /* drop reference on a group from fsnotify_alloc_group */ diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 813274d4eda..04f16887406 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -937,7 +937,7 @@ static int __init audit_tree_init(void) { int i; - audit_tree_group = fsnotify_alloc_group(0, &audit_tree_ops); + audit_tree_group = fsnotify_alloc_group(&audit_tree_ops); if (IS_ERR(audit_tree_group)) audit_panic("cannot initialize fsnotify group for rectree watches"); diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 87408b28211..83d5f9674ce 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -585,7 +585,7 @@ static const struct fsnotify_ops audit_watch_fsnotify_ops = { static int __init audit_watch_init(void) { - audit_watch_group = fsnotify_alloc_group(0, &audit_watch_fsnotify_ops); + audit_watch_group = fsnotify_alloc_group(&audit_watch_fsnotify_ops); if (IS_ERR(audit_watch_group)) { audit_watch_group = NULL; audit_panic("cannot create audit fsnotify group"); -- cgit v1.2.3 From 3a9fb89f4cd04c23e16397befba92efb5d989b74 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 21:24:23 -0500 Subject: fsnotify: include vfsmount in should_send_event when appropriate To ensure that a group will not duplicate events when it receives it based on the vfsmount and the inode should_send_event test we should distinguish those two cases. We pass a vfsmount to this function so groups can make their own determinations. Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 4 ++-- fs/notify/fsnotify.c | 39 ++++++++++++++++++------------------ fs/notify/inotify/inotify_fsnotify.c | 3 ++- include/linux/fsnotify_backend.h | 3 ++- kernel/audit_tree.c | 3 ++- kernel/audit_watch.c | 3 ++- 6 files changed, 29 insertions(+), 26 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index e0a847bd53b..9eddafa4c7b 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -133,8 +133,8 @@ 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, __u32 mask, - void *data, int data_type) + struct inode *inode, struct vfsmount *mnt, + __u32 mask, void *data, int data_type) { struct fsnotify_mark_entry *entry; bool send; diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index a61aaa71082..78c440c343a 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -135,13 +135,12 @@ void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) } EXPORT_SYMBOL_GPL(__fsnotify_parent); -static void send_to_group(__u32 mask, - struct fsnotify_group *group, - void *data, int data_is, const char *file_name, - u32 cookie, struct fsnotify_event **event, - struct inode *to_tell) +static void send_to_group(struct fsnotify_group *group, struct inode *to_tell, + struct vfsmount *mnt, __u32 mask, void *data, + int data_is, u32 cookie, const char *file_name, + struct fsnotify_event **event) { - if (!group->ops->should_send_event(group, to_tell, mask, + if (!group->ops->should_send_event(group, to_tell, mnt, mask, data, data_is)) return; if (!*event) { @@ -159,15 +158,9 @@ static void send_to_group(__u32 mask, group->ops->handle_event(group, *event); } -static bool needed_by_vfsmount(__u32 test_mask, void *data, int data_is) +static bool needed_by_vfsmount(__u32 test_mask, struct vfsmount *mnt) { - struct path *path; - - if (data_is == FSNOTIFY_EVENT_PATH) - path = (struct path *)data; - else if (data_is == FSNOTIFY_EVENT_FILE) - path = &((struct file *)data)->f_path; - else + if (!mnt) return false; /* hook in this when mnt->mnt_fsnotify_mask is defined */ @@ -184,6 +177,7 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const { struct fsnotify_group *group; struct fsnotify_event *event = NULL; + struct vfsmount *mnt = NULL; int idx; /* global tests shouldn't care about events on child only the specific event */ __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); @@ -198,10 +192,15 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const !(test_mask & fsnotify_vfsmount_mask)) return; + if (data_is == FSNOTIFY_EVENT_PATH) + mnt = ((struct path *)data)->mnt; + else if (data_is == FSNOTIFY_EVENT_FILE) + mnt = ((struct file *)data)->f_path.mnt; + /* if this inode's directed listeners don't care and nothing on the vfsmount * listeners list cares, nothing to do */ if (!(test_mask & to_tell->i_fsnotify_mask) && - !needed_by_vfsmount(test_mask, data, data_is)) + !needed_by_vfsmount(test_mask, mnt)) return; /* @@ -214,16 +213,16 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const if (test_mask & to_tell->i_fsnotify_mask) { list_for_each_entry_rcu(group, &fsnotify_inode_groups, inode_group_list) { if (test_mask & group->mask) { - send_to_group(mask, group, data, data_is, - file_name, cookie, &event, to_tell); + send_to_group(group, to_tell, NULL, mask, data, data_is, + cookie, file_name, &event); } } } - if (needed_by_vfsmount(test_mask, data, data_is)) { + if (needed_by_vfsmount(test_mask, mnt)) { list_for_each_entry_rcu(group, &fsnotify_vfsmount_groups, vfsmount_group_list) { if (test_mask & group->mask) { - send_to_group(mask, group, data, data_is, - file_name, cookie, &event, to_tell); + send_to_group(group, to_tell, mnt, mask, data, data_is, + cookie, file_name, &event); } } } diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 0a0f5d0f0d0..8075ae708ed 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -141,7 +141,8 @@ static void inotify_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnot } static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode, - __u32 mask, void *data, int data_type) + struct vfsmount *mnt, __u32 mask, void *data, + int data_type) { struct fsnotify_mark_entry *entry; bool send; diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index dea48bee057..c2a04b7e4fc 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -79,7 +79,8 @@ struct fsnotify_event_private_data; */ struct fsnotify_ops { bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode, - __u32 mask, void *data, int data_type); + struct vfsmount *mnt, __u32 mask, void *data, + int data_type); int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event); void (*free_group_priv)(struct fsnotify_group *group); void (*freeing_mark)(struct fsnotify_mark_entry *entry, struct fsnotify_group *group); diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 04f16887406..ecf0bf260d0 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -920,7 +920,8 @@ static void audit_tree_freeing_mark(struct fsnotify_mark_entry *entry, struct fs } static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode, - __u32 mask, void *data, int data_type) + struct vfsmount *mnt, __u32 mask, void *data, + int data_type) { return 0; } diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 83d5f9674ce..6304ee5d764 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -514,7 +514,8 @@ void audit_remove_watch_rule(struct audit_krule *krule) } static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode, - __u32 mask, void *data, int data_type) + struct vfsmount *mnt, __u32 mask, void *data, + int data_type) { struct fsnotify_mark_entry *entry; bool send; -- cgit v1.2.3 From e61ce86737b4d60521e4e71f9892fe4bdcfb688b Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 21:24:24 -0500 Subject: fsnotify: rename fsnotify_mark_entry to just fsnotify_mark The name is long and it serves no real purpose. So rename fsnotify_mark_entry to just fsnotify_mark. Signed-off-by: Eric Paris --- fs/inode.c | 2 +- fs/notify/dnotify/dnotify.c | 24 +++++++++--------- fs/notify/group.c | 8 +++--- fs/notify/inode_mark.c | 48 ++++++++++++++++++------------------ fs/notify/inotify/inotify.h | 6 ++--- fs/notify/inotify/inotify_fsnotify.c | 8 +++--- fs/notify/inotify/inotify_user.c | 8 +++--- include/linux/fs.h | 2 +- include/linux/fsnotify.h | 18 +++++++------- include/linux/fsnotify_backend.h | 38 ++++++++++++++-------------- kernel/audit_tree.c | 14 +++++------ kernel/audit_watch.c | 8 +++--- kernel/auditsc.c | 4 +-- 13 files changed, 94 insertions(+), 94 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/inode.c b/fs/inode.c index 8e1bee99879..a2da778467b 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -264,7 +264,7 @@ void inode_init_once(struct inode *inode) INIT_LIST_HEAD(&inode->i_data.i_mmap_nonlinear); i_size_ordered_init(inode); #ifdef CONFIG_FSNOTIFY - INIT_HLIST_HEAD(&inode->i_fsnotify_mark_entries); + INIT_HLIST_HEAD(&inode->i_fsnotify_marks); #endif } EXPORT_SYMBOL(inode_init_once); diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index fc3a9dc567c..e6edae60894 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -34,12 +34,12 @@ static struct fsnotify_group *dnotify_group __read_mostly; static DEFINE_MUTEX(dnotify_mark_mutex); /* - * dnotify will attach one of these to each inode (i_fsnotify_mark_entries) which + * dnotify will attach one of these to each inode (i_fsnotify_marks) which * is being watched by dnotify. If multiple userspace applications are watching * the same directory with dnotify their information is chained in dn */ struct dnotify_mark_entry { - struct fsnotify_mark_entry fsn_entry; + struct fsnotify_mark fsn_entry; struct dnotify_struct *dn; }; @@ -51,7 +51,7 @@ struct dnotify_mark_entry { * it calls the fsnotify function so it can update the set of all events relevant * to this inode. */ -static void dnotify_recalc_inode_mask(struct fsnotify_mark_entry *entry) +static void dnotify_recalc_inode_mask(struct fsnotify_mark *entry) { __u32 new_mask, old_mask; struct dnotify_struct *dn; @@ -85,7 +85,7 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark_entry *entry) static int dnotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) { - struct fsnotify_mark_entry *entry = NULL; + struct fsnotify_mark *entry = NULL; struct dnotify_mark_entry *dnentry; struct inode *to_tell; struct dnotify_struct *dn; @@ -136,7 +136,7 @@ static bool dnotify_should_send_event(struct fsnotify_group *group, struct inode *inode, struct vfsmount *mnt, __u32 mask, void *data, int data_type) { - struct fsnotify_mark_entry *entry; + struct fsnotify_mark *entry; bool send; /* !dir_notify_enable should never get here, don't waste time checking @@ -163,7 +163,7 @@ static bool dnotify_should_send_event(struct fsnotify_group *group, return send; } -static void dnotify_free_mark(struct fsnotify_mark_entry *entry) +static void dnotify_free_mark(struct fsnotify_mark *entry) { struct dnotify_mark_entry *dnentry = container_of(entry, struct dnotify_mark_entry, @@ -184,14 +184,14 @@ static struct fsnotify_ops dnotify_fsnotify_ops = { /* * Called every time a file is closed. Looks first for a dnotify mark on the - * inode. If one is found run all of the ->dn entries attached to that + * inode. If one is found run all of the ->dn structures attached to that * mark for one relevant to this process closing the file and remove that * dnotify_struct. If that was the last dnotify_struct also remove the - * fsnotify_mark_entry. + * fsnotify_mark. */ void dnotify_flush(struct file *filp, fl_owner_t id) { - struct fsnotify_mark_entry *entry; + struct fsnotify_mark *entry; struct dnotify_mark_entry *dnentry; struct dnotify_struct *dn; struct dnotify_struct **prev; @@ -260,7 +260,7 @@ static __u32 convert_arg(unsigned long arg) /* * If multiple processes watch the same inode with dnotify there is only one - * dnotify mark in inode->i_fsnotify_mark_entries but we chain a dnotify_struct + * dnotify mark in inode->i_fsnotify_marks but we chain a dnotify_struct * onto that mark. This function either attaches the new dnotify_struct onto * that list, or it |= the mask onto an existing dnofiy_struct. */ @@ -298,7 +298,7 @@ static int attach_dn(struct dnotify_struct *dn, struct dnotify_mark_entry *dnent int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) { struct dnotify_mark_entry *new_dnentry, *dnentry; - struct fsnotify_mark_entry *new_entry, *entry; + struct fsnotify_mark *new_entry, *entry; struct dnotify_struct *dn; struct inode *inode; fl_owner_t id = current->files; @@ -378,7 +378,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) /* if (f != filp) means that we lost a race and another task/thread * actually closed the fd we are still playing with before we grabbed * the dnotify_mark_mutex and entry->lock. Since closing the fd is the - * only time we clean up the mark entries we need to get our mark off + * only time we clean up the marks we need to get our mark off * the list. */ if (f != filp) { /* if we added ourselves, shoot ourselves, it's possible that diff --git a/fs/notify/group.c b/fs/notify/group.c index aa4654fe6ec..b70e7d21dfd 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c @@ -74,10 +74,10 @@ void fsnotify_recalc_group_mask(struct fsnotify_group *group) { __u32 mask = 0; __u32 old_mask = group->mask; - struct fsnotify_mark_entry *entry; + struct fsnotify_mark *entry; spin_lock(&group->mark_lock); - list_for_each_entry(entry, &group->mark_entries, g_list) + list_for_each_entry(entry, &group->marks_list, g_list) mask |= entry->mask; spin_unlock(&group->mark_lock); @@ -133,7 +133,7 @@ void fsnotify_final_destroy_group(struct fsnotify_group *group) */ static void fsnotify_destroy_group(struct fsnotify_group *group) { - /* clear all inode mark entries for this group */ + /* clear all inode marks for this group */ fsnotify_clear_marks_by_group(group); /* past the point of no return, matches the initial value of 1 */ @@ -224,7 +224,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) INIT_LIST_HEAD(&group->vfsmount_group_list); spin_lock_init(&group->mark_lock); - INIT_LIST_HEAD(&group->mark_entries); + INIT_LIST_HEAD(&group->marks_list); group->ops = ops; diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index b00065842b3..7e69f6b08d4 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -38,12 +38,12 @@ * that lock to dereference either of these things (they could be NULL even with * the lock) * - * group->mark_lock protects the mark_entries list anchored inside a given group + * group->mark_lock protects the marks_list anchored inside a given group * and each entry is hooked via the g_list. It also sorta protects the * free_g_list, which when used is anchored by a private list on the stack of the * task which held the group->mark_lock. * - * inode->i_lock protects the i_fsnotify_mark_entries list anchored inside a + * inode->i_lock protects the i_fsnotify_marks list anchored inside a * given inode and each entry is hooked via the i_list. (and sorta the * free_i_list) * @@ -61,7 +61,7 @@ * need to be cleaned up. (fsnotify_clear_marks_by_group) * * Worst case we are given an inode and need to clean up all the marks on that - * inode. We take i_lock and walk the i_fsnotify_mark_entries safely. For each + * inode. We take i_lock and walk the i_fsnotify_marks safely. For each * mark on the list we take a reference (so the mark can't disappear under us). * We remove that mark form the inode's list of marks and we add this mark to a * private list anchored on the stack using i_free_list; At this point we no @@ -95,12 +95,12 @@ #include #include "fsnotify.h" -void fsnotify_get_mark(struct fsnotify_mark_entry *entry) +void fsnotify_get_mark(struct fsnotify_mark *entry) { atomic_inc(&entry->refcnt); } -void fsnotify_put_mark(struct fsnotify_mark_entry *entry) +void fsnotify_put_mark(struct fsnotify_mark *entry) { if (atomic_dec_and_test(&entry->refcnt)) entry->free_mark(entry); @@ -111,13 +111,13 @@ void fsnotify_put_mark(struct fsnotify_mark_entry *entry) */ static void fsnotify_recalc_inode_mask_locked(struct inode *inode) { - struct fsnotify_mark_entry *entry; + struct fsnotify_mark *entry; struct hlist_node *pos; __u32 new_mask = 0; assert_spin_locked(&inode->i_lock); - hlist_for_each_entry(entry, pos, &inode->i_fsnotify_mark_entries, i.i_list) + hlist_for_each_entry(entry, pos, &inode->i_fsnotify_marks, i.i_list) new_mask |= entry->mask; inode->i_fsnotify_mask = new_mask; } @@ -140,7 +140,7 @@ void fsnotify_recalc_inode_mask(struct inode *inode) * The caller had better be holding a reference to this mark so we don't actually * do the final put under the entry->lock */ -void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry) +void fsnotify_destroy_mark_by_entry(struct fsnotify_mark *entry) { struct fsnotify_group *group; struct inode *inode; @@ -174,7 +174,7 @@ void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry) fsnotify_put_mark(entry); /* for i_list and g_list */ /* - * this mark is now off the inode->i_fsnotify_mark_entries list and we + * this mark is now off the inode->i_fsnotify_marks list and we * hold the inode->i_lock, so this is the perfect time to update the * inode->i_fsnotify_mask */ @@ -221,11 +221,11 @@ void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry) */ void fsnotify_clear_marks_by_group(struct fsnotify_group *group) { - struct fsnotify_mark_entry *lentry, *entry; + struct fsnotify_mark *lentry, *entry; LIST_HEAD(free_list); spin_lock(&group->mark_lock); - list_for_each_entry_safe(entry, lentry, &group->mark_entries, g_list) { + list_for_each_entry_safe(entry, lentry, &group->marks_list, g_list) { list_add(&entry->free_g_list, &free_list); list_del_init(&entry->g_list); fsnotify_get_mark(entry); @@ -243,12 +243,12 @@ void fsnotify_clear_marks_by_group(struct fsnotify_group *group) */ void fsnotify_clear_marks_by_inode(struct inode *inode) { - struct fsnotify_mark_entry *entry, *lentry; + struct fsnotify_mark *entry, *lentry; struct hlist_node *pos, *n; LIST_HEAD(free_list); spin_lock(&inode->i_lock); - hlist_for_each_entry_safe(entry, pos, n, &inode->i_fsnotify_mark_entries, i.i_list) { + hlist_for_each_entry_safe(entry, pos, n, &inode->i_fsnotify_marks, i.i_list) { list_add(&entry->i.free_i_list, &free_list); hlist_del_init(&entry->i.i_list); fsnotify_get_mark(entry); @@ -265,15 +265,15 @@ void fsnotify_clear_marks_by_inode(struct inode *inode) * given a group and inode, find the mark associated with that combination. * if found take a reference to that mark and return it, else return NULL */ -struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_group *group, - struct inode *inode) +struct fsnotify_mark *fsnotify_find_mark_entry(struct fsnotify_group *group, + struct inode *inode) { - struct fsnotify_mark_entry *entry; + struct fsnotify_mark *entry; struct hlist_node *pos; assert_spin_locked(&inode->i_lock); - hlist_for_each_entry(entry, pos, &inode->i_fsnotify_mark_entries, i.i_list) { + hlist_for_each_entry(entry, pos, &inode->i_fsnotify_marks, i.i_list) { if (entry->group == group) { fsnotify_get_mark(entry); return entry; @@ -282,7 +282,7 @@ struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_group *grou return NULL; } -void fsnotify_duplicate_mark(struct fsnotify_mark_entry *new, struct fsnotify_mark_entry *old) +void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old) { assert_spin_locked(&old->lock); new->i.inode = old->i.inode; @@ -294,8 +294,8 @@ void fsnotify_duplicate_mark(struct fsnotify_mark_entry *new, struct fsnotify_ma /* * Nothing fancy, just initialize lists and locks and counters. */ -void fsnotify_init_mark(struct fsnotify_mark_entry *entry, - void (*free_mark)(struct fsnotify_mark_entry *entry)) +void fsnotify_init_mark(struct fsnotify_mark *entry, + void (*free_mark)(struct fsnotify_mark *entry)) { spin_lock_init(&entry->lock); atomic_set(&entry->refcnt, 1); @@ -311,11 +311,11 @@ void fsnotify_init_mark(struct fsnotify_mark_entry *entry, * These marks may be used for the fsnotify backend to determine which * event types should be delivered to which group and for which inodes. */ -int fsnotify_add_mark(struct fsnotify_mark_entry *entry, +int fsnotify_add_mark(struct fsnotify_mark *entry, struct fsnotify_group *group, struct inode *inode, int allow_dups) { - struct fsnotify_mark_entry *lentry = NULL; + struct fsnotify_mark *lentry = NULL; int ret = 0; inode = igrab(inode); @@ -354,8 +354,8 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry, entry->group = group; entry->i.inode = inode; - hlist_add_head(&entry->i.i_list, &inode->i_fsnotify_mark_entries); - list_add(&entry->g_list, &group->mark_entries); + hlist_add_head(&entry->i.i_list, &inode->i_fsnotify_marks); + list_add(&entry->g_list, &group->marks_list); fsnotify_get_mark(entry); /* for i_list and g_list */ diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h index f234f3a4c8c..07be6df2428 100644 --- a/fs/notify/inotify/inotify.h +++ b/fs/notify/inotify/inotify.h @@ -10,12 +10,12 @@ struct inotify_event_private_data { }; struct inotify_inode_mark_entry { - /* fsnotify_mark_entry MUST be the first thing */ - struct fsnotify_mark_entry fsn_entry; + /* fsnotify_mark MUST be the first thing */ + struct fsnotify_mark fsn_entry; int wd; }; -extern void inotify_ignored_and_remove_idr(struct fsnotify_mark_entry *entry, +extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *entry, struct fsnotify_group *group); extern void inotify_free_event_priv(struct fsnotify_event_private_data *event_priv); diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 3edb51cfcfb..f33a9bd32e5 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -88,7 +88,7 @@ static int inotify_merge(struct list_head *list, struct fsnotify_event *event) static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) { - struct fsnotify_mark_entry *entry; + struct fsnotify_mark *entry; struct inotify_inode_mark_entry *ientry; struct inode *to_tell; struct inotify_event_private_data *event_priv; @@ -135,7 +135,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev return ret; } -static void inotify_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group) +static void inotify_freeing_mark(struct fsnotify_mark *entry, struct fsnotify_group *group) { inotify_ignored_and_remove_idr(entry, group); } @@ -144,7 +144,7 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode struct vfsmount *mnt, __u32 mask, void *data, int data_type) { - struct fsnotify_mark_entry *entry; + struct fsnotify_mark *entry; bool send; spin_lock(&inode->i_lock); @@ -171,7 +171,7 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode */ static int idr_callback(int id, void *p, void *data) { - struct fsnotify_mark_entry *entry; + struct fsnotify_mark *entry; struct inotify_inode_mark_entry *ientry; static bool warned = false; diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 4b1587f9df3..7be5dcf07ac 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -386,7 +386,7 @@ static struct inotify_inode_mark_entry *inotify_idr_find_locked(struct fsnotify_ ientry = idr_find(idr, wd); if (ientry) { - struct fsnotify_mark_entry *fsn_entry = &ientry->fsn_entry; + struct fsnotify_mark *fsn_entry = &ientry->fsn_entry; fsnotify_get_mark(fsn_entry); /* One ref for being in the idr, one ref we just took */ @@ -499,7 +499,7 @@ out: /* * Send IN_IGNORED for this wd, remove this wd from the idr. */ -void inotify_ignored_and_remove_idr(struct fsnotify_mark_entry *entry, +void inotify_ignored_and_remove_idr(struct fsnotify_mark *entry, struct fsnotify_group *group) { struct inotify_inode_mark_entry *ientry; @@ -541,7 +541,7 @@ skip_send_ignore: } /* ding dong the mark is dead */ -static void inotify_free_mark(struct fsnotify_mark_entry *entry) +static void inotify_free_mark(struct fsnotify_mark *entry) { struct inotify_inode_mark_entry *ientry; @@ -554,7 +554,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group, struct inode *inode, u32 arg) { - struct fsnotify_mark_entry *entry; + struct fsnotify_mark *entry; struct inotify_inode_mark_entry *ientry; __u32 old_mask, new_mask; __u32 mask; diff --git a/include/linux/fs.h b/include/linux/fs.h index e5598d2f99b..85fe89c4348 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -768,7 +768,7 @@ struct inode { #ifdef CONFIG_FSNOTIFY __u32 i_fsnotify_mask; /* all events this inode cares about */ - struct hlist_head i_fsnotify_mark_entries; /* fsnotify mark entries */ + struct hlist_head i_fsnotify_marks; #endif unsigned long i_state; diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 06d296d85eb..62e93a9dd11 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -19,10 +19,10 @@ * fsnotify_d_instantiate - instantiate a dentry for inode * Called with dcache_lock held. */ -static inline void fsnotify_d_instantiate(struct dentry *entry, - struct inode *inode) +static inline void fsnotify_d_instantiate(struct dentry *dentry, + struct inode *inode) { - __fsnotify_d_instantiate(entry, inode); + __fsnotify_d_instantiate(dentry, inode); } /* Notify this dentry's parent about a child's events. */ @@ -35,16 +35,16 @@ static inline void fsnotify_parent(struct path *path, struct dentry *dentry, __u } /* - * fsnotify_d_move - entry has been moved - * Called with dcache_lock and entry->d_lock held. + * fsnotify_d_move - dentry has been moved + * Called with dcache_lock and dentry->d_lock held. */ -static inline void fsnotify_d_move(struct dentry *entry) +static inline void fsnotify_d_move(struct dentry *dentry) { /* - * On move we need to update entry->d_flags to indicate if the new parent - * cares about events from this entry. + * On move we need to update dentry->d_flags to indicate if the new parent + * cares about events from this dentry. */ - __fsnotify_update_dcache_flags(entry); + __fsnotify_update_dcache_flags(dentry); } /* diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 7a6ba755acc..59c072e8fdd 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -62,7 +62,7 @@ struct fsnotify_group; struct fsnotify_event; -struct fsnotify_mark_entry; +struct fsnotify_mark; struct fsnotify_event_private_data; /* @@ -83,7 +83,7 @@ struct fsnotify_ops { int data_type); int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event); void (*free_group_priv)(struct fsnotify_group *group); - void (*freeing_mark)(struct fsnotify_mark_entry *entry, struct fsnotify_group *group); + void (*freeing_mark)(struct fsnotify_mark *entry, struct fsnotify_group *group); void (*free_event_priv)(struct fsnotify_event_private_data *priv); }; @@ -133,12 +133,12 @@ struct fsnotify_group { unsigned int q_len; /* events on the queue */ unsigned int max_events; /* maximum events allowed on the list */ - /* stores all fastapth entries assoc with this group so they can be cleaned on unregister */ - spinlock_t mark_lock; /* protect mark_entries list */ + /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */ + spinlock_t mark_lock; /* protect marks_list */ atomic_t num_marks; /* 1 for each mark entry and 1 for not being * past the point of no return when freeing * a group */ - struct list_head mark_entries; /* all inode mark entries for this group */ + struct list_head marks_list; /* all inode marks for this group */ /* prevents double list_del of group_list. protected by global fsnotify_grp_mutex */ bool on_inode_group_list; @@ -226,20 +226,20 @@ struct fsnotify_event { }; /* - * Inode specific fields in an fsnotify_mark_entry + * Inode specific fields in an fsnotify_mark */ struct fsnotify_inode_mark { struct inode *inode; /* inode this entry is associated with */ - struct hlist_node i_list; /* list of mark_entries by inode->i_fsnotify_mark_entries */ + struct hlist_node i_list; /* list of marks by inode->i_fsnotify_marks */ struct list_head free_i_list; /* tmp list used when freeing this mark */ }; /* - * Mount point specific fields in an fsnotify_mark_entry + * Mount point specific fields in an fsnotify_mark */ struct fsnotify_vfsmount_mark { struct vfsmount *mnt; /* inode this entry is associated with */ - struct hlist_node m_list; /* list of mark_entries by inode->i_fsnotify_mark_entries */ + struct hlist_node m_list; /* list of marks by inode->i_fsnotify_marks */ struct list_head free_m_list; /* tmp list used when freeing this mark */ }; @@ -253,13 +253,13 @@ struct fsnotify_vfsmount_mark { * (such as dnotify) will flush these when the open fd is closed and not at * inode eviction or modification. */ -struct fsnotify_mark_entry { +struct fsnotify_mark { __u32 mask; /* mask this mark entry is for */ /* we hold ref for each i_list and g_list. also one ref for each 'thing' * in kernel that found and may be using this mark. */ atomic_t refcnt; /* active things looking at this mark */ struct fsnotify_group *group; /* group this mark entry is for */ - struct list_head g_list; /* list of mark_entries by group->i_fsnotify_mark_entries */ + struct list_head g_list; /* list of marks by group->i_fsnotify_marks */ spinlock_t lock; /* protect group and inode */ union { struct fsnotify_inode_mark i; @@ -269,7 +269,7 @@ struct fsnotify_mark_entry { #define FSNOTIFY_MARK_FLAG_INODE 0x01 #define FSNOTIFY_MARK_FLAG_VFSMOUNT 0x02 unsigned int flags; /* vfsmount or inode mark? */ - void (*free_mark)(struct fsnotify_mark_entry *entry); /* called on final put+free */ + void (*free_mark)(struct fsnotify_mark *entry); /* called on final put+free */ }; #ifdef CONFIG_FSNOTIFY @@ -361,19 +361,19 @@ extern struct fsnotify_event *fsnotify_remove_notify_event(struct fsnotify_group /* run all marks associated with an inode and update inode->i_fsnotify_mask */ extern void fsnotify_recalc_inode_mask(struct inode *inode); -extern void fsnotify_init_mark(struct fsnotify_mark_entry *entry, void (*free_mark)(struct fsnotify_mark_entry *entry)); +extern void fsnotify_init_mark(struct fsnotify_mark *entry, void (*free_mark)(struct fsnotify_mark *entry)); /* find (and take a reference) to a mark associated with group and inode */ -extern struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_group *group, struct inode *inode); +extern struct fsnotify_mark *fsnotify_find_mark_entry(struct fsnotify_group *group, struct inode *inode); /* copy the values from old into new */ -extern void fsnotify_duplicate_mark(struct fsnotify_mark_entry *new, struct fsnotify_mark_entry *old); +extern void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old); /* attach the mark to both the group and the inode */ -extern int fsnotify_add_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group, struct inode *inode, int allow_dups); +extern int fsnotify_add_mark(struct fsnotify_mark *entry, struct fsnotify_group *group, struct inode *inode, int allow_dups); /* given a mark, flag it to be freed when all references are dropped */ -extern void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry); +extern void fsnotify_destroy_mark_by_entry(struct fsnotify_mark *entry); /* run all the marks in a group, and flag them to be freed */ extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group); -extern void fsnotify_get_mark(struct fsnotify_mark_entry *entry); -extern void fsnotify_put_mark(struct fsnotify_mark_entry *entry); +extern void fsnotify_get_mark(struct fsnotify_mark *entry); +extern void fsnotify_put_mark(struct fsnotify_mark *entry); extern void fsnotify_unmount_inodes(struct list_head *list); /* put here because inotify does some weird stuff when destroying watches */ diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index c21b05d2522..f16f909fbbc 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -22,7 +22,7 @@ struct audit_tree { struct audit_chunk { struct list_head hash; - struct fsnotify_mark_entry mark; + struct fsnotify_mark mark; struct list_head trees; /* with root here */ int dead; int count; @@ -134,7 +134,7 @@ static void __put_chunk(struct rcu_head *rcu) audit_put_chunk(chunk); } -static void audit_tree_destroy_watch(struct fsnotify_mark_entry *entry) +static void audit_tree_destroy_watch(struct fsnotify_mark *entry) { struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark); call_rcu(&chunk->head, __put_chunk); @@ -176,7 +176,7 @@ static inline struct list_head *chunk_hash(const struct inode *inode) /* hash_lock & entry->lock is held by caller */ static void insert_hash(struct audit_chunk *chunk) { - struct fsnotify_mark_entry *entry = &chunk->mark; + struct fsnotify_mark *entry = &chunk->mark; struct list_head *list; if (!entry->i.inode) @@ -222,7 +222,7 @@ static struct audit_chunk *find_chunk(struct node *p) static void untag_chunk(struct node *p) { struct audit_chunk *chunk = find_chunk(p); - struct fsnotify_mark_entry *entry = &chunk->mark; + struct fsnotify_mark *entry = &chunk->mark; struct audit_chunk *new; struct audit_tree *owner; int size = chunk->count - 1; @@ -316,7 +316,7 @@ out: static int create_chunk(struct inode *inode, struct audit_tree *tree) { - struct fsnotify_mark_entry *entry; + struct fsnotify_mark *entry; struct audit_chunk *chunk = alloc_chunk(1); if (!chunk) return -ENOMEM; @@ -354,7 +354,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) /* the first tagged inode becomes root of tree */ static int tag_chunk(struct inode *inode, struct audit_tree *tree) { - struct fsnotify_mark_entry *old_entry, *chunk_entry; + struct fsnotify_mark *old_entry, *chunk_entry; struct audit_tree *owner; struct audit_chunk *chunk, *old; struct node *p; @@ -911,7 +911,7 @@ static int audit_tree_handle_event(struct fsnotify_group *group, struct fsnotify return -EOPNOTSUPP; } -static void audit_tree_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group) +static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify_group *group) { struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark); diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 6304ee5d764..d8cb55a5c05 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -56,7 +56,7 @@ struct audit_watch { struct audit_parent { struct list_head watches; /* anchor for audit_watch->wlist */ - struct fsnotify_mark_entry mark; /* fsnotify mark on the inode */ + struct fsnotify_mark mark; /* fsnotify mark on the inode */ }; /* fsnotify handle. */ @@ -72,7 +72,7 @@ static void audit_free_parent(struct audit_parent *parent) kfree(parent); } -static void audit_watch_free_mark(struct fsnotify_mark_entry *entry) +static void audit_watch_free_mark(struct fsnotify_mark *entry) { struct audit_parent *parent; @@ -99,7 +99,7 @@ static void audit_put_parent(struct audit_parent *parent) static inline struct audit_parent *audit_find_parent(struct inode *inode) { struct audit_parent *parent = NULL; - struct fsnotify_mark_entry *entry; + struct fsnotify_mark *entry; spin_lock(&inode->i_lock); entry = fsnotify_find_mark_entry(audit_watch_group, inode); @@ -517,7 +517,7 @@ static bool audit_watch_should_send_event(struct fsnotify_group *group, struct i struct vfsmount *mnt, __u32 mask, void *data, int data_type) { - struct fsnotify_mark_entry *entry; + struct fsnotify_mark *entry; bool send; spin_lock(&inode->i_lock); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 853185f7ba7..b87a63beb66 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1724,7 +1724,7 @@ static inline void handle_one(const struct inode *inode) struct audit_tree_refs *p; struct audit_chunk *chunk; int count; - if (likely(hlist_empty(&inode->i_fsnotify_mark_entries))) + if (likely(hlist_empty(&inode->i_fsnotify_marks))) return; context = current->audit_context; p = context->trees; @@ -1767,7 +1767,7 @@ retry: seq = read_seqbegin(&rename_lock); for(;;) { struct inode *inode = d->d_inode; - if (inode && unlikely(!hlist_empty(&inode->i_fsnotify_mark_entries))) { + if (inode && unlikely(!hlist_empty(&inode->i_fsnotify_marks))) { struct audit_chunk *chunk; chunk = audit_tree_lookup(inode); if (chunk) { -- cgit v1.2.3 From d07754412f9cdc2f4a99318d5ee81ace6715ea99 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 21:24:24 -0500 Subject: fsnotify: rename fsnotify_find_mark_entry to fsnotify_find_mark the _entry portion of fsnotify functions is useless. Drop it. Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 14 +++++++------- fs/notify/inode_mark.c | 14 +++++++------- fs/notify/inotify/inotify_fsnotify.c | 4 ++-- fs/notify/inotify/inotify_user.c | 6 +++--- include/linux/fsnotify_backend.h | 4 ++-- kernel/audit_tree.c | 12 ++++++------ kernel/audit_watch.c | 8 ++++---- 7 files changed, 31 insertions(+), 31 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index e6edae60894..b202bc590c6 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -96,7 +96,7 @@ static int dnotify_handle_event(struct fsnotify_group *group, to_tell = event->to_tell; spin_lock(&to_tell->i_lock); - entry = fsnotify_find_mark_entry(group, to_tell); + entry = fsnotify_find_mark(group, to_tell); spin_unlock(&to_tell->i_lock); /* unlikely since we alreay passed dnotify_should_send_event() */ @@ -148,7 +148,7 @@ static bool dnotify_should_send_event(struct fsnotify_group *group, return false; spin_lock(&inode->i_lock); - entry = fsnotify_find_mark_entry(group, inode); + entry = fsnotify_find_mark(group, inode); spin_unlock(&inode->i_lock); /* no mark means no dnotify watch */ @@ -158,7 +158,7 @@ static bool dnotify_should_send_event(struct fsnotify_group *group, mask = (mask & ~FS_EVENT_ON_CHILD); send = (mask & entry->mask); - fsnotify_put_mark(entry); /* matches fsnotify_find_mark_entry */ + fsnotify_put_mark(entry); /* matches fsnotify_find_mark */ return send; } @@ -202,7 +202,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id) return; spin_lock(&inode->i_lock); - entry = fsnotify_find_mark_entry(dnotify_group, inode); + entry = fsnotify_find_mark(dnotify_group, inode); spin_unlock(&inode->i_lock); if (!entry) return; @@ -226,7 +226,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id) /* nothing else could have found us thanks to the dnotify_mark_mutex */ if (dnentry->dn == NULL) - fsnotify_destroy_mark_by_entry(entry); + fsnotify_destroy_mark(entry); fsnotify_recalc_group_mask(dnotify_group); @@ -357,7 +357,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) /* add the new_entry or find an old one. */ spin_lock(&inode->i_lock); - entry = fsnotify_find_mark_entry(dnotify_group, inode); + entry = fsnotify_find_mark(dnotify_group, inode); spin_unlock(&inode->i_lock); if (entry) { dnentry = container_of(entry, struct dnotify_mark_entry, fsn_entry); @@ -414,7 +414,7 @@ out: spin_unlock(&entry->lock); if (destroy) - fsnotify_destroy_mark_by_entry(entry); + fsnotify_destroy_mark(entry); fsnotify_recalc_group_mask(dnotify_group); diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 7e69f6b08d4..01c42632eb2 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -56,7 +56,7 @@ * - The inode is unlinked for the last time. (fsnotify_inode_remove) * - The inode is being evicted from cache. (fsnotify_inode_delete) * - The fs the inode is on is unmounted. (fsnotify_inode_delete/fsnotify_unmount_inodes) - * - Something explicitly requests that it be removed. (fsnotify_destroy_mark_by_entry) + * - Something explicitly requests that it be removed. (fsnotify_destroy_mark) * - The fsnotify_group associated with the mark is going away and all such marks * need to be cleaned up. (fsnotify_clear_marks_by_group) * @@ -140,7 +140,7 @@ void fsnotify_recalc_inode_mask(struct inode *inode) * The caller had better be holding a reference to this mark so we don't actually * do the final put under the entry->lock */ -void fsnotify_destroy_mark_by_entry(struct fsnotify_mark *entry) +void fsnotify_destroy_mark(struct fsnotify_mark *entry) { struct fsnotify_group *group; struct inode *inode; @@ -233,7 +233,7 @@ void fsnotify_clear_marks_by_group(struct fsnotify_group *group) spin_unlock(&group->mark_lock); list_for_each_entry_safe(entry, lentry, &free_list, free_g_list) { - fsnotify_destroy_mark_by_entry(entry); + fsnotify_destroy_mark(entry); fsnotify_put_mark(entry); } } @@ -256,7 +256,7 @@ void fsnotify_clear_marks_by_inode(struct inode *inode) spin_unlock(&inode->i_lock); list_for_each_entry_safe(entry, lentry, &free_list, i.free_i_list) { - fsnotify_destroy_mark_by_entry(entry); + fsnotify_destroy_mark(entry); fsnotify_put_mark(entry); } } @@ -265,8 +265,8 @@ void fsnotify_clear_marks_by_inode(struct inode *inode) * given a group and inode, find the mark associated with that combination. * if found take a reference to that mark and return it, else return NULL */ -struct fsnotify_mark *fsnotify_find_mark_entry(struct fsnotify_group *group, - struct inode *inode) +struct fsnotify_mark *fsnotify_find_mark(struct fsnotify_group *group, + struct inode *inode) { struct fsnotify_mark *entry; struct hlist_node *pos; @@ -349,7 +349,7 @@ int fsnotify_add_mark(struct fsnotify_mark *entry, spin_lock(&inode->i_lock); if (!allow_dups) - lentry = fsnotify_find_mark_entry(group, inode); + lentry = fsnotify_find_mark(group, inode); if (!lentry) { entry->group = group; entry->i.inode = inode; diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index f33a9bd32e5..f8a2a6eda13 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -98,7 +98,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev to_tell = event->to_tell; spin_lock(&to_tell->i_lock); - entry = fsnotify_find_mark_entry(group, to_tell); + entry = fsnotify_find_mark(group, to_tell); spin_unlock(&to_tell->i_lock); /* race with watch removal? We already passes should_send */ if (unlikely(!entry)) @@ -148,7 +148,7 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode bool send; spin_lock(&inode->i_lock); - entry = fsnotify_find_mark_entry(group, inode); + entry = fsnotify_find_mark(group, inode); spin_unlock(&inode->i_lock); if (!entry) return false; diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 7be5dcf07ac..118085c9d2d 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -567,7 +567,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group, return -EINVAL; spin_lock(&inode->i_lock); - entry = fsnotify_find_mark_entry(group, inode); + entry = fsnotify_find_mark(group, inode); spin_unlock(&inode->i_lock); if (!entry) return -ENOENT; @@ -607,7 +607,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group, /* return the wd */ ret = ientry->wd; - /* match the get from fsnotify_find_mark_entry() */ + /* match the get from fsnotify_find_mark() */ fsnotify_put_mark(entry); return ret; @@ -823,7 +823,7 @@ SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd) ret = 0; - fsnotify_destroy_mark_by_entry(&ientry->fsn_entry); + fsnotify_destroy_mark(&ientry->fsn_entry); /* match ref taken by inotify_idr_find */ fsnotify_put_mark(&ientry->fsn_entry); diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 59c072e8fdd..83b6bfeb2d6 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -363,13 +363,13 @@ extern struct fsnotify_event *fsnotify_remove_notify_event(struct fsnotify_group extern void fsnotify_recalc_inode_mask(struct inode *inode); extern void fsnotify_init_mark(struct fsnotify_mark *entry, void (*free_mark)(struct fsnotify_mark *entry)); /* find (and take a reference) to a mark associated with group and inode */ -extern struct fsnotify_mark *fsnotify_find_mark_entry(struct fsnotify_group *group, struct inode *inode); +extern struct fsnotify_mark *fsnotify_find_mark(struct fsnotify_group *group, struct inode *inode); /* copy the values from old into new */ extern void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old); /* attach the mark to both the group and the inode */ extern int fsnotify_add_mark(struct fsnotify_mark *entry, struct fsnotify_group *group, struct inode *inode, int allow_dups); /* given a mark, flag it to be freed when all references are dropped */ -extern void fsnotify_destroy_mark_by_entry(struct fsnotify_mark *entry); +extern void fsnotify_destroy_mark(struct fsnotify_mark *entry); /* run all the marks in a group, and flag them to be freed */ extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group); extern void fsnotify_get_mark(struct fsnotify_mark *entry); diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index f16f909fbbc..b20fb055d71 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -250,7 +250,7 @@ static void untag_chunk(struct node *p) list_del_rcu(&chunk->hash); spin_unlock(&hash_lock); spin_unlock(&entry->lock); - fsnotify_destroy_mark_by_entry(entry); + fsnotify_destroy_mark(entry); fsnotify_put_mark(entry); goto out; } @@ -293,7 +293,7 @@ static void untag_chunk(struct node *p) owner->root = new; spin_unlock(&hash_lock); spin_unlock(&entry->lock); - fsnotify_destroy_mark_by_entry(entry); + fsnotify_destroy_mark(entry); fsnotify_put_mark(entry); goto out; @@ -333,7 +333,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&hash_lock); chunk->dead = 1; spin_unlock(&entry->lock); - fsnotify_destroy_mark_by_entry(entry); + fsnotify_destroy_mark(entry); fsnotify_put_mark(entry); return 0; } @@ -361,7 +361,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) int n; spin_lock(&inode->i_lock); - old_entry = fsnotify_find_mark_entry(audit_tree_group, inode); + old_entry = fsnotify_find_mark(audit_tree_group, inode); spin_unlock(&inode->i_lock); if (!old_entry) return create_chunk(inode, tree); @@ -415,7 +415,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&chunk_entry->lock); spin_unlock(&old_entry->lock); - fsnotify_destroy_mark_by_entry(chunk_entry); + fsnotify_destroy_mark(chunk_entry); fsnotify_put_mark(chunk_entry); fsnotify_put_mark(old_entry); @@ -446,7 +446,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&hash_lock); spin_unlock(&chunk_entry->lock); spin_unlock(&old_entry->lock); - fsnotify_destroy_mark_by_entry(old_entry); + fsnotify_destroy_mark(old_entry); fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */ fsnotify_put_mark(old_entry); /* and kill it */ return 0; diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index d8cb55a5c05..24ecbebf435 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -102,7 +102,7 @@ static inline struct audit_parent *audit_find_parent(struct inode *inode) struct fsnotify_mark *entry; spin_lock(&inode->i_lock); - entry = fsnotify_find_mark_entry(audit_watch_group, inode); + entry = fsnotify_find_mark(audit_watch_group, inode); spin_unlock(&inode->i_lock); if (entry) @@ -354,7 +354,7 @@ static void audit_remove_parent_watches(struct audit_parent *parent) } mutex_unlock(&audit_filter_mutex); - fsnotify_destroy_mark_by_entry(&parent->mark); + fsnotify_destroy_mark(&parent->mark); fsnotify_recalc_group_mask(audit_watch_group); @@ -504,7 +504,7 @@ void audit_remove_watch_rule(struct audit_krule *krule) if (list_empty(&parent->watches)) { audit_get_parent(parent); - fsnotify_destroy_mark_by_entry(&parent->mark); + fsnotify_destroy_mark(&parent->mark); audit_put_parent(parent); } } @@ -521,7 +521,7 @@ static bool audit_watch_should_send_event(struct fsnotify_group *group, struct i bool send; spin_lock(&inode->i_lock); - entry = fsnotify_find_mark_entry(group, inode); + entry = fsnotify_find_mark(group, inode); spin_unlock(&inode->i_lock); if (!entry) return false; -- cgit v1.2.3 From 35566087099c3ff8901d65ee98af56347ee66e5a Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 17 Dec 2009 21:24:25 -0500 Subject: fsnotify: take inode->i_lock inside fsnotify_find_mark_entry() All callers to fsnotify_find_mark_entry() except one take and release inode->i_lock around the call. Take the lock inside fsnotify_find_mark_entry() instead. Signed-off-by: Andreas Gruenbacher Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 12 ------------ fs/notify/inode_mark.c | 26 +++++++++++++++++++------- fs/notify/inotify/inotify_fsnotify.c | 4 ---- fs/notify/inotify/inotify_user.c | 2 -- kernel/audit_tree.c | 2 -- kernel/audit_watch.c | 5 ----- 6 files changed, 19 insertions(+), 32 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 3efb8b9a572..cac2eb89663 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -95,11 +95,7 @@ static int dnotify_handle_event(struct fsnotify_group *group, to_tell = event->to_tell; - spin_lock(&to_tell->i_lock); fsn_mark = fsnotify_find_mark(group, to_tell); - spin_unlock(&to_tell->i_lock); - - /* unlikely since we alreay passed dnotify_should_send_event() */ if (unlikely(!fsn_mark)) return 0; dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark); @@ -147,11 +143,7 @@ static bool dnotify_should_send_event(struct fsnotify_group *group, if (!S_ISDIR(inode->i_mode)) return false; - spin_lock(&inode->i_lock); fsn_mark = fsnotify_find_mark(group, inode); - spin_unlock(&inode->i_lock); - - /* no mark means no dnotify watch */ if (!fsn_mark) return false; @@ -201,9 +193,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id) if (!S_ISDIR(inode->i_mode)) return; - spin_lock(&inode->i_lock); fsn_mark = fsnotify_find_mark(dnotify_group, inode); - spin_unlock(&inode->i_lock); if (!fsn_mark) return; dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark); @@ -356,9 +346,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) mutex_lock(&dnotify_mark_mutex); /* add the new_fsn_mark or find an old one. */ - spin_lock(&inode->i_lock); fsn_mark = fsnotify_find_mark(dnotify_group, inode); - spin_unlock(&inode->i_lock); if (fsn_mark) { dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark); spin_lock(&fsn_mark->lock); diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 27c1b43ad73..ba6f9833561 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -261,12 +261,8 @@ void fsnotify_clear_marks_by_inode(struct inode *inode) } } -/* - * given a group and inode, find the mark associated with that combination. - * if found take a reference to that mark and return it, else return NULL - */ -struct fsnotify_mark *fsnotify_find_mark(struct fsnotify_group *group, - struct inode *inode) +static struct fsnotify_mark *fsnotify_find_mark_locked(struct fsnotify_group *group, + struct inode *inode) { struct fsnotify_mark *mark; struct hlist_node *pos; @@ -282,6 +278,22 @@ struct fsnotify_mark *fsnotify_find_mark(struct fsnotify_group *group, return NULL; } +/* + * given a group and inode, find the mark associated with that combination. + * if found take a reference to that mark and return it, else return NULL + */ +struct fsnotify_mark *fsnotify_find_mark(struct fsnotify_group *group, + struct inode *inode) +{ + struct fsnotify_mark *mark; + + spin_lock(&inode->i_lock); + mark = fsnotify_find_mark_locked(group, inode); + spin_unlock(&inode->i_lock); + + return mark; +} + void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old) { assert_spin_locked(&old->lock); @@ -349,7 +361,7 @@ int fsnotify_add_mark(struct fsnotify_mark *mark, spin_lock(&inode->i_lock); if (!allow_dups) - lmark = fsnotify_find_mark(group, inode); + lmark = fsnotify_find_mark_locked(group, inode); if (!lmark) { mark->group = group; mark->i.inode = inode; diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 12dc72be992..cc8f6bcbb4a 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -97,9 +97,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev to_tell = event->to_tell; - spin_lock(&to_tell->i_lock); fsn_mark = fsnotify_find_mark(group, to_tell); - spin_unlock(&to_tell->i_lock); /* race with watch removal? We already passes should_send */ if (unlikely(!fsn_mark)) return 0; @@ -147,9 +145,7 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode struct fsnotify_mark *fsn_mark; bool send; - spin_lock(&inode->i_lock); fsn_mark = fsnotify_find_mark(group, inode); - spin_unlock(&inode->i_lock); if (!fsn_mark) return false; diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 80d102acb86..ad5a1ea7827 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -566,9 +566,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group, if (unlikely(!mask)) return -EINVAL; - spin_lock(&inode->i_lock); fsn_mark = fsnotify_find_mark(group, inode); - spin_unlock(&inode->i_lock); if (!fsn_mark) return -ENOENT; diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index b20fb055d71..80f8ac328aa 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -360,9 +360,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) struct node *p; int n; - spin_lock(&inode->i_lock); old_entry = fsnotify_find_mark(audit_tree_group, inode); - spin_unlock(&inode->i_lock); if (!old_entry) return create_chunk(inode, tree); diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 24ecbebf435..d85fa538a72 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -101,10 +101,7 @@ static inline struct audit_parent *audit_find_parent(struct inode *inode) struct audit_parent *parent = NULL; struct fsnotify_mark *entry; - spin_lock(&inode->i_lock); entry = fsnotify_find_mark(audit_watch_group, inode); - spin_unlock(&inode->i_lock); - if (entry) parent = container_of(entry, struct audit_parent, mark); @@ -520,9 +517,7 @@ static bool audit_watch_should_send_event(struct fsnotify_group *group, struct i struct fsnotify_mark *entry; bool send; - spin_lock(&inode->i_lock); entry = fsnotify_find_mark(group, inode); - spin_unlock(&inode->i_lock); if (!entry) return false; -- cgit v1.2.3 From 5444e2981c31d0ed7465475e451b8437084337e5 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 21:24:27 -0500 Subject: fsnotify: split generic and inode specific mark code currently all marking is done by functions in inode-mark.c. Some of this is pretty generic and should be instead done in a generic function and we should only put the inode specific code in inode-mark.c Signed-off-by: Eric Paris --- fs/notify/Makefile | 3 +- fs/notify/dnotify/dnotify.c | 12 +- fs/notify/fanotify/fanotify.c | 2 +- fs/notify/fanotify/fanotify_user.c | 8 +- fs/notify/fsnotify.h | 7 + fs/notify/inode_mark.c | 246 +++-------------------------- fs/notify/inotify/inotify_fsnotify.c | 4 +- fs/notify/inotify/inotify_user.c | 4 +- fs/notify/mark.c | 294 +++++++++++++++++++++++++++++++++++ include/linux/fsnotify_backend.h | 5 +- kernel/audit_tree.c | 8 +- kernel/audit_watch.c | 6 +- 12 files changed, 347 insertions(+), 252 deletions(-) create mode 100644 fs/notify/mark.c (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/Makefile b/fs/notify/Makefile index 396a3877937..8f7f3b024a2 100644 --- a/fs/notify/Makefile +++ b/fs/notify/Makefile @@ -1,4 +1,5 @@ -obj-$(CONFIG_FSNOTIFY) += fsnotify.o notification.o group.o inode_mark.o +obj-$(CONFIG_FSNOTIFY) += fsnotify.o notification.o group.o inode_mark.o \ + mark.o obj-y += dnotify/ obj-y += inotify/ diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index cac2eb89663..69f42df9ba4 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -95,7 +95,7 @@ static int dnotify_handle_event(struct fsnotify_group *group, to_tell = event->to_tell; - fsn_mark = fsnotify_find_mark(group, to_tell); + fsn_mark = fsnotify_find_inode_mark(group, to_tell); if (unlikely(!fsn_mark)) return 0; dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark); @@ -143,14 +143,14 @@ static bool dnotify_should_send_event(struct fsnotify_group *group, if (!S_ISDIR(inode->i_mode)) return false; - fsn_mark = fsnotify_find_mark(group, inode); + fsn_mark = fsnotify_find_inode_mark(group, inode); if (!fsn_mark) return false; mask = (mask & ~FS_EVENT_ON_CHILD); send = (mask & fsn_mark->mask); - fsnotify_put_mark(fsn_mark); /* matches fsnotify_find_mark */ + fsnotify_put_mark(fsn_mark); /* matches fsnotify_find_inode_mark */ return send; } @@ -193,7 +193,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id) if (!S_ISDIR(inode->i_mode)) return; - fsn_mark = fsnotify_find_mark(dnotify_group, inode); + fsn_mark = fsnotify_find_inode_mark(dnotify_group, inode); if (!fsn_mark) return; dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark); @@ -346,12 +346,12 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) mutex_lock(&dnotify_mark_mutex); /* add the new_fsn_mark or find an old one. */ - fsn_mark = fsnotify_find_mark(dnotify_group, inode); + fsn_mark = fsnotify_find_inode_mark(dnotify_group, inode); if (fsn_mark) { dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark); spin_lock(&fsn_mark->lock); } else { - fsnotify_add_mark(new_fsn_mark, dnotify_group, inode, 0); + fsnotify_add_mark(new_fsn_mark, dnotify_group, inode, NULL, 0); spin_lock(&new_fsn_mark->lock); fsn_mark = new_fsn_mark; dn_mark = new_dn_mark; diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 881067dc792..aa5e9266114 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -118,7 +118,7 @@ static bool fanotify_should_send_event(struct fsnotify_group *group, struct inod if (data_type != FSNOTIFY_EVENT_PATH) return false; - fsn_mark = fsnotify_find_mark(group, inode); + fsn_mark = fsnotify_find_inode_mark(group, inode); if (!fsn_mark) return false; diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 66e38fc052b..05351936a72 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -305,7 +305,7 @@ static int fanotify_remove_mark(struct fsnotify_group *group, pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode, mask); - fsn_mark = fsnotify_find_mark(group, inode); + fsn_mark = fsnotify_find_inode_mark(group, inode); if (!fsn_mark) return -ENOENT; @@ -321,7 +321,7 @@ static int fanotify_remove_mark(struct fsnotify_group *group, fsnotify_recalc_group_mask(group); - /* matches the fsnotify_find_mark() */ + /* matches the fsnotify_find_inode_mark() */ fsnotify_put_mark(fsn_mark); return 0; @@ -338,7 +338,7 @@ static int fanotify_add_mark(struct fsnotify_group *group, pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode, mask); - fsn_mark = fsnotify_find_mark(group, inode); + fsn_mark = fsnotify_find_inode_mark(group, inode); if (!fsn_mark) { struct fsnotify_mark *new_fsn_mark; @@ -348,7 +348,7 @@ static int fanotify_add_mark(struct fsnotify_group *group, goto out; fsnotify_init_mark(new_fsn_mark, fanotify_free_mark); - ret = fsnotify_add_mark(new_fsn_mark, group, inode, 0); + ret = fsnotify_add_mark(new_fsn_mark, group, inode, NULL, 0); if (ret) { fanotify_free_mark(new_fsn_mark); goto out; diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h index 2ba59158969..7c7a904b802 100644 --- a/fs/notify/fsnotify.h +++ b/fs/notify/fsnotify.h @@ -20,6 +20,11 @@ extern __u32 fsnotify_vfsmount_mask; /* destroy all events sitting in this groups notification queue */ extern void fsnotify_flush_notify(struct fsnotify_group *group); +/* add a mark to an inode */ +extern int fsnotify_add_inode_mark(struct fsnotify_mark *mark, + struct fsnotify_group *group, struct inode *inode, + int allow_dups); + /* add a group to the inode group list */ extern void fsnotify_add_inode_group(struct fsnotify_group *group); /* add a group to the vfsmount group list */ @@ -27,6 +32,8 @@ extern void fsnotify_add_vfsmount_group(struct fsnotify_group *group); /* final kfree of a group */ extern void fsnotify_final_destroy_group(struct fsnotify_group *group); +/* inode specific destruction of a mark */ +extern void fsnotify_destroy_inode_mark(struct fsnotify_mark *mark); /* run the list of all marks associated with inode and flag them to be freed */ extern void fsnotify_clear_marks_by_inode(struct inode *inode); /* diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index ba6f9833561..c925579ba01 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -16,72 +16,6 @@ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - * fsnotify inode mark locking/lifetime/and refcnting - * - * REFCNT: - * The mark->refcnt tells how many "things" in the kernel currently are - * referencing this object. The object typically will live inside the kernel - * with a refcnt of 2, one for each list it is on (i_list, g_list). Any task - * which can find this object holding the appropriete locks, can take a reference - * and the object itself is guarenteed to survive until the reference is dropped. - * - * LOCKING: - * There are 3 spinlocks involved with fsnotify inode marks and they MUST - * be taken in order as follows: - * - * mark->lock - * group->mark_lock - * inode->i_lock - * - * mark->lock protects 2 things, mark->group and mark->inode. You must hold - * that lock to dereference either of these things (they could be NULL even with - * the lock) - * - * group->mark_lock protects the marks_list anchored inside a given group - * and each mark is hooked via the g_list. It also sorta protects the - * free_g_list, which when used is anchored by a private list on the stack of the - * task which held the group->mark_lock. - * - * inode->i_lock protects the i_fsnotify_marks list anchored inside a - * given inode and each mark is hooked via the i_list. (and sorta the - * free_i_list) - * - * - * LIFETIME: - * Inode marks survive between when they are added to an inode and when their - * refcnt==0. - * - * The inode mark can be cleared for a number of different reasons including: - * - The inode is unlinked for the last time. (fsnotify_inode_remove) - * - The inode is being evicted from cache. (fsnotify_inode_delete) - * - The fs the inode is on is unmounted. (fsnotify_inode_delete/fsnotify_unmount_inodes) - * - Something explicitly requests that it be removed. (fsnotify_destroy_mark) - * - The fsnotify_group associated with the mark is going away and all such marks - * need to be cleaned up. (fsnotify_clear_marks_by_group) - * - * Worst case we are given an inode and need to clean up all the marks on that - * inode. We take i_lock and walk the i_fsnotify_marks safely. For each - * mark on the list we take a reference (so the mark can't disappear under us). - * We remove that mark form the inode's list of marks and we add this mark to a - * private list anchored on the stack using i_free_list; At this point we no - * longer fear anything finding the mark using the inode's list of marks. - * - * We can safely and locklessly run the private list on the stack of everything - * we just unattached from the original inode. For each mark on the private list - * we grab the mark-> and can thus dereference mark->group and mark->inode. If - * we see the group and inode are not NULL we take those locks. Now holding all - * 3 locks we can completely remove the mark from other tasks finding it in the - * future. Remember, 10 things might already be referencing this mark, but they - * better be holding a ref. We drop our reference we took before we unhooked it - * from the inode. When the ref hits 0 we can free the mark. - * - * Very similarly for freeing by group, except we use free_g_list. - * - * This has the very interesting property of being able to run concurrently with - * any (or all) other directions. - */ - #include #include #include @@ -95,17 +29,6 @@ #include #include "fsnotify.h" -void fsnotify_get_mark(struct fsnotify_mark *mark) -{ - atomic_inc(&mark->refcnt); -} - -void fsnotify_put_mark(struct fsnotify_mark *mark) -{ - if (atomic_dec_and_test(&mark->refcnt)) - mark->free_mark(mark); -} - /* * Recalculate the mask of events relevant to a given inode locked. */ @@ -135,44 +58,18 @@ void fsnotify_recalc_inode_mask(struct inode *inode) __fsnotify_update_child_dentry_flags(inode); } -/* - * Any time a mark is getting freed we end up here. - * The caller had better be holding a reference to this mark so we don't actually - * do the final put under the mark->lock - */ -void fsnotify_destroy_mark(struct fsnotify_mark *mark) +void fsnotify_destroy_inode_mark(struct fsnotify_mark *mark) { - struct fsnotify_group *group; - struct inode *inode; - - spin_lock(&mark->lock); + struct inode *inode = mark->i.inode; - group = mark->group; - inode = mark->i.inode; + assert_spin_locked(&mark->lock); + assert_spin_locked(&mark->group->mark_lock); - BUG_ON(group && !inode); - BUG_ON(!group && inode); - - /* if !group something else already marked this to die */ - if (!group) { - spin_unlock(&mark->lock); - return; - } - - /* 1 from caller and 1 for being on i_list/g_list */ - BUG_ON(atomic_read(&mark->refcnt) < 2); - - spin_lock(&group->mark_lock); spin_lock(&inode->i_lock); hlist_del_init(&mark->i.i_list); mark->i.inode = NULL; - list_del_init(&mark->g_list); - mark->group = NULL; - - fsnotify_put_mark(mark); /* for i_list and g_list */ - /* * this mark is now off the inode->i_fsnotify_marks list and we * hold the inode->i_lock, so this is the perfect time to update the @@ -181,61 +78,6 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark) fsnotify_recalc_inode_mask_locked(inode); spin_unlock(&inode->i_lock); - spin_unlock(&group->mark_lock); - spin_unlock(&mark->lock); - - /* - * Some groups like to know that marks are being freed. This is a - * callback to the group function to let it know that this mark - * is being freed. - */ - if (group->ops->freeing_mark) - group->ops->freeing_mark(mark, group); - - /* - * __fsnotify_update_child_dentry_flags(inode); - * - * I really want to call that, but we can't, we have no idea if the inode - * still exists the second we drop the mark->lock. - * - * The next time an event arrive to this inode from one of it's children - * __fsnotify_parent will see that the inode doesn't care about it's - * children and will update all of these flags then. So really this - * is just a lazy update (and could be a perf win...) - */ - - - iput(inode); - - /* - * it's possible that this group tried to destroy itself, but this - * this mark was simultaneously being freed by inode. If that's the - * case, we finish freeing the group here. - */ - if (unlikely(atomic_dec_and_test(&group->num_marks))) - fsnotify_final_destroy_group(group); -} - -/* - * Given a group, destroy all of the marks associated with that group. - */ -void fsnotify_clear_marks_by_group(struct fsnotify_group *group) -{ - struct fsnotify_mark *lmark, *mark; - LIST_HEAD(free_list); - - spin_lock(&group->mark_lock); - list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { - list_add(&mark->free_g_list, &free_list); - list_del_init(&mark->g_list); - fsnotify_get_mark(mark); - } - spin_unlock(&group->mark_lock); - - list_for_each_entry_safe(mark, lmark, &free_list, free_g_list) { - fsnotify_destroy_mark(mark); - fsnotify_put_mark(mark); - } } /* @@ -261,8 +103,12 @@ void fsnotify_clear_marks_by_inode(struct inode *inode) } } -static struct fsnotify_mark *fsnotify_find_mark_locked(struct fsnotify_group *group, - struct inode *inode) +/* + * given a group and inode, find the mark associated with that combination. + * if found take a reference to that mark and return it, else return NULL + */ +struct fsnotify_mark *fsnotify_find_inode_mark_locked(struct fsnotify_group *group, + struct inode *inode) { struct fsnotify_mark *mark; struct hlist_node *pos; @@ -282,50 +128,26 @@ static struct fsnotify_mark *fsnotify_find_mark_locked(struct fsnotify_group *gr * given a group and inode, find the mark associated with that combination. * if found take a reference to that mark and return it, else return NULL */ -struct fsnotify_mark *fsnotify_find_mark(struct fsnotify_group *group, - struct inode *inode) +struct fsnotify_mark *fsnotify_find_inode_mark(struct fsnotify_group *group, + struct inode *inode) { struct fsnotify_mark *mark; spin_lock(&inode->i_lock); - mark = fsnotify_find_mark_locked(group, inode); + mark = fsnotify_find_inode_mark_locked(group, inode); spin_unlock(&inode->i_lock); return mark; } -void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old) -{ - assert_spin_locked(&old->lock); - new->i.inode = old->i.inode; - new->group = old->group; - new->mask = old->mask; - new->free_mark = old->free_mark; -} - -/* - * Nothing fancy, just initialize lists and locks and counters. - */ -void fsnotify_init_mark(struct fsnotify_mark *mark, - void (*free_mark)(struct fsnotify_mark *mark)) -{ - spin_lock_init(&mark->lock); - atomic_set(&mark->refcnt, 1); - INIT_HLIST_NODE(&mark->i.i_list); - mark->group = NULL; - mark->mask = 0; - mark->i.inode = NULL; - mark->free_mark = free_mark; -} - /* * Attach an initialized mark mark to a given group and inode. * These marks may be used for the fsnotify backend to determine which * event types should be delivered to which group and for which inodes. */ -int fsnotify_add_mark(struct fsnotify_mark *mark, - struct fsnotify_group *group, struct inode *inode, - int allow_dups) +int fsnotify_add_inode_mark(struct fsnotify_mark *mark, + struct fsnotify_group *group, struct inode *inode, + int allow_dups) { struct fsnotify_mark *lmark = NULL; int ret = 0; @@ -336,56 +158,26 @@ int fsnotify_add_mark(struct fsnotify_mark *mark, mark->flags = FSNOTIFY_MARK_FLAG_INODE; - /* - * if this group isn't being testing for inode type events we need - * to start testing - */ - if (unlikely(list_empty(&group->inode_group_list))) - fsnotify_add_inode_group(group); - /* - * XXX This is where we could also do the fsnotify_add_vfsmount_group - * if we are setting and vfsmount mark.... - - if (unlikely(list_empty(&group->vfsmount_group_list))) - fsnotify_add_vfsmount_group(group); - */ + assert_spin_locked(&mark->lock); + assert_spin_locked(&group->mark_lock); - /* - * LOCKING ORDER!!!! - * mark->lock - * group->mark_lock - * inode->i_lock - */ - spin_lock(&mark->lock); - spin_lock(&group->mark_lock); spin_lock(&inode->i_lock); if (!allow_dups) - lmark = fsnotify_find_mark_locked(group, inode); + lmark = fsnotify_find_inode_mark_locked(group, inode); if (!lmark) { - mark->group = group; mark->i.inode = inode; hlist_add_head(&mark->i.i_list, &inode->i_fsnotify_marks); - list_add(&mark->g_list, &group->marks_list); - - fsnotify_get_mark(mark); /* for i_list and g_list */ - - atomic_inc(&group->num_marks); fsnotify_recalc_inode_mask_locked(inode); } spin_unlock(&inode->i_lock); - spin_unlock(&group->mark_lock); - spin_unlock(&mark->lock); if (lmark) { ret = -EEXIST; iput(inode); - fsnotify_put_mark(lmark); - } else { - __fsnotify_update_child_dentry_flags(inode); } return ret; diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index cc8f6bcbb4a..1d237e1bf7b 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -97,7 +97,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev to_tell = event->to_tell; - fsn_mark = fsnotify_find_mark(group, to_tell); + fsn_mark = fsnotify_find_inode_mark(group, to_tell); /* race with watch removal? We already passes should_send */ if (unlikely(!fsn_mark)) return 0; @@ -145,7 +145,7 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode struct fsnotify_mark *fsn_mark; bool send; - fsn_mark = fsnotify_find_mark(group, inode); + fsn_mark = fsnotify_find_inode_mark(group, inode); if (!fsn_mark) return false; diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index ad5a1ea7827..a12315a7553 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -566,7 +566,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group, if (unlikely(!mask)) return -EINVAL; - fsn_mark = fsnotify_find_mark(group, inode); + fsn_mark = fsnotify_find_inode_mark(group, inode); if (!fsn_mark) return -ENOENT; @@ -644,7 +644,7 @@ static int inotify_new_watch(struct fsnotify_group *group, goto out_err; /* we are on the idr, now get on the inode */ - ret = fsnotify_add_mark(&tmp_i_mark->fsn_mark, group, inode, 0); + ret = fsnotify_add_mark(&tmp_i_mark->fsn_mark, group, inode, NULL, 0); if (ret) { /* we failed to get on the inode, get off the idr */ inotify_remove_from_idr(group, tmp_i_mark); diff --git a/fs/notify/mark.c b/fs/notify/mark.c new file mode 100644 index 00000000000..e56e8768d67 --- /dev/null +++ b/fs/notify/mark.c @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2008 Red Hat, Inc., Eric Paris + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * fsnotify inode mark locking/lifetime/and refcnting + * + * REFCNT: + * The mark->refcnt tells how many "things" in the kernel currently are + * referencing this object. The object typically will live inside the kernel + * with a refcnt of 2, one for each list it is on (i_list, g_list). Any task + * which can find this object holding the appropriete locks, can take a reference + * and the object itself is guarenteed to survive until the reference is dropped. + * + * LOCKING: + * There are 3 spinlocks involved with fsnotify inode marks and they MUST + * be taken in order as follows: + * + * mark->lock + * group->mark_lock + * inode->i_lock + * + * mark->lock protects 2 things, mark->group and mark->inode. You must hold + * that lock to dereference either of these things (they could be NULL even with + * the lock) + * + * group->mark_lock protects the marks_list anchored inside a given group + * and each mark is hooked via the g_list. It also sorta protects the + * free_g_list, which when used is anchored by a private list on the stack of the + * task which held the group->mark_lock. + * + * inode->i_lock protects the i_fsnotify_marks list anchored inside a + * given inode and each mark is hooked via the i_list. (and sorta the + * free_i_list) + * + * + * LIFETIME: + * Inode marks survive between when they are added to an inode and when their + * refcnt==0. + * + * The inode mark can be cleared for a number of different reasons including: + * - The inode is unlinked for the last time. (fsnotify_inode_remove) + * - The inode is being evicted from cache. (fsnotify_inode_delete) + * - The fs the inode is on is unmounted. (fsnotify_inode_delete/fsnotify_unmount_inodes) + * - Something explicitly requests that it be removed. (fsnotify_destroy_mark) + * - The fsnotify_group associated with the mark is going away and all such marks + * need to be cleaned up. (fsnotify_clear_marks_by_group) + * + * Worst case we are given an inode and need to clean up all the marks on that + * inode. We take i_lock and walk the i_fsnotify_marks safely. For each + * mark on the list we take a reference (so the mark can't disappear under us). + * We remove that mark form the inode's list of marks and we add this mark to a + * private list anchored on the stack using i_free_list; At this point we no + * longer fear anything finding the mark using the inode's list of marks. + * + * We can safely and locklessly run the private list on the stack of everything + * we just unattached from the original inode. For each mark on the private list + * we grab the mark-> and can thus dereference mark->group and mark->inode. If + * we see the group and inode are not NULL we take those locks. Now holding all + * 3 locks we can completely remove the mark from other tasks finding it in the + * future. Remember, 10 things might already be referencing this mark, but they + * better be holding a ref. We drop our reference we took before we unhooked it + * from the inode. When the ref hits 0 we can free the mark. + * + * Very similarly for freeing by group, except we use free_g_list. + * + * This has the very interesting property of being able to run concurrently with + * any (or all) other directions. + */ + +#include +#include +#include +#include +#include +#include +#include +#include /* for inode_lock */ + +#include + +#include +#include "fsnotify.h" + +void fsnotify_get_mark(struct fsnotify_mark *mark) +{ + atomic_inc(&mark->refcnt); +} + +void fsnotify_put_mark(struct fsnotify_mark *mark) +{ + if (atomic_dec_and_test(&mark->refcnt)) + mark->free_mark(mark); +} + +/* + * Any time a mark is getting freed we end up here. + * The caller had better be holding a reference to this mark so we don't actually + * do the final put under the mark->lock + */ +void fsnotify_destroy_mark(struct fsnotify_mark *mark) +{ + struct fsnotify_group *group; + struct inode *inode; + + spin_lock(&mark->lock); + + group = mark->group; + inode = mark->i.inode; + + BUG_ON(group && !inode); + BUG_ON(!group && inode); + + /* if !group something else already marked this to die */ + if (!group) { + spin_unlock(&mark->lock); + return; + } + + /* 1 from caller and 1 for being on i_list/g_list */ + BUG_ON(atomic_read(&mark->refcnt) < 2); + + spin_lock(&group->mark_lock); + + if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) + fsnotify_destroy_inode_mark(mark); + else + BUG(); + + list_del_init(&mark->g_list); + mark->group = NULL; + + fsnotify_put_mark(mark); /* for i_list and g_list */ + + spin_unlock(&group->mark_lock); + spin_unlock(&mark->lock); + + /* + * Some groups like to know that marks are being freed. This is a + * callback to the group function to let it know that this mark + * is being freed. + */ + if (group->ops->freeing_mark) + group->ops->freeing_mark(mark, group); + + /* + * __fsnotify_update_child_dentry_flags(inode); + * + * I really want to call that, but we can't, we have no idea if the inode + * still exists the second we drop the mark->lock. + * + * The next time an event arrive to this inode from one of it's children + * __fsnotify_parent will see that the inode doesn't care about it's + * children and will update all of these flags then. So really this + * is just a lazy update (and could be a perf win...) + */ + + + iput(inode); + + /* + * it's possible that this group tried to destroy itself, but this + * this mark was simultaneously being freed by inode. If that's the + * case, we finish freeing the group here. + */ + if (unlikely(atomic_dec_and_test(&group->num_marks))) + fsnotify_final_destroy_group(group); +} + +/* + * Attach an initialized mark to a given group and fs object. + * These marks may be used for the fsnotify backend to determine which + * event types should be delivered to which group. + */ +int fsnotify_add_mark(struct fsnotify_mark *mark, + struct fsnotify_group *group, struct inode *inode, + struct vfsmount *mnt, int allow_dups) +{ + int ret = 0; + + BUG_ON(mnt); + BUG_ON(inode && mnt); + BUG_ON(!inode && !mnt); + + /* + * if this group isn't being testing for inode type events we need + * to start testing + */ + if (inode && unlikely(list_empty(&group->inode_group_list))) + fsnotify_add_inode_group(group); + else if (mnt && unlikely(list_empty(&group->vfsmount_group_list))) + fsnotify_add_vfsmount_group(group); + + /* + * LOCKING ORDER!!!! + * mark->lock + * group->mark_lock + * inode->i_lock + */ + spin_lock(&mark->lock); + spin_lock(&group->mark_lock); + + mark->group = group; + list_add(&mark->g_list, &group->marks_list); + atomic_inc(&group->num_marks); + fsnotify_get_mark(mark); /* for i_list and g_list */ + + if (inode) { + ret = fsnotify_add_inode_mark(mark, group, inode, allow_dups); + if (ret) + goto err; + } else { + BUG(); + } + + spin_unlock(&group->mark_lock); + spin_unlock(&mark->lock); + + if (inode) + __fsnotify_update_child_dentry_flags(inode); + + return ret; +err: + mark->group = NULL; + list_del_init(&mark->g_list); + atomic_dec(&group->num_marks); + fsnotify_put_mark(mark); + + spin_unlock(&group->mark_lock); + spin_unlock(&mark->lock); + + return ret; +} + +/* + * Given a group, destroy all of the marks associated with that group. + */ +void fsnotify_clear_marks_by_group(struct fsnotify_group *group) +{ + struct fsnotify_mark *lmark, *mark; + LIST_HEAD(free_list); + + spin_lock(&group->mark_lock); + list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { + list_add(&mark->free_g_list, &free_list); + list_del_init(&mark->g_list); + fsnotify_get_mark(mark); + } + spin_unlock(&group->mark_lock); + + list_for_each_entry_safe(mark, lmark, &free_list, free_g_list) { + fsnotify_destroy_mark(mark); + fsnotify_put_mark(mark); + } +} + +void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old) +{ + assert_spin_locked(&old->lock); + new->i.inode = old->i.inode; + new->m.mnt = old->m.mnt; + new->group = old->group; + new->mask = old->mask; + new->free_mark = old->free_mark; +} + +/* + * Nothing fancy, just initialize lists and locks and counters. + */ +void fsnotify_init_mark(struct fsnotify_mark *mark, + void (*free_mark)(struct fsnotify_mark *mark)) +{ + spin_lock_init(&mark->lock); + atomic_set(&mark->refcnt, 1); + INIT_HLIST_NODE(&mark->i.i_list); + mark->group = NULL; + mark->mask = 0; + mark->i.inode = NULL; + mark->free_mark = free_mark; +} diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 7d93572ec56..27cccbecbf2 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -364,11 +364,12 @@ extern struct fsnotify_event *fsnotify_remove_notify_event(struct fsnotify_group extern void fsnotify_recalc_inode_mask(struct inode *inode); extern void fsnotify_init_mark(struct fsnotify_mark *mark, void (*free_mark)(struct fsnotify_mark *mark)); /* find (and take a reference) to a mark associated with group and inode */ -extern struct fsnotify_mark *fsnotify_find_mark(struct fsnotify_group *group, struct inode *inode); +extern struct fsnotify_mark *fsnotify_find_inode_mark(struct fsnotify_group *group, struct inode *inode); /* copy the values from old into new */ extern void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old); /* attach the mark to both the group and the inode */ -extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group, struct inode *inode, int allow_dups); +extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group, + struct inode *inode, struct vfsmount *mnt, int allow_dups); /* given a mark, flag it to be freed when all references are dropped */ extern void fsnotify_destroy_mark(struct fsnotify_mark *mark); /* run all the marks in a group, and flag them to be freed */ diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 80f8ac328aa..cfb97d752a6 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -259,7 +259,7 @@ static void untag_chunk(struct node *p) if (!new) goto Fallback; fsnotify_duplicate_mark(&new->mark, entry); - if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, 1)) { + if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) { free_chunk(new); goto Fallback; } @@ -322,7 +322,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) return -ENOMEM; entry = &chunk->mark; - if (fsnotify_add_mark(entry, audit_tree_group, inode, 0)) { + if (fsnotify_add_mark(entry, audit_tree_group, inode, NULL, 0)) { free_chunk(chunk); return -ENOSPC; } @@ -360,7 +360,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) struct node *p; int n; - old_entry = fsnotify_find_mark(audit_tree_group, inode); + old_entry = fsnotify_find_inode_mark(audit_tree_group, inode); if (!old_entry) return create_chunk(inode, tree); @@ -395,7 +395,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) } fsnotify_duplicate_mark(chunk_entry, old_entry); - if (fsnotify_add_mark(chunk_entry, chunk_entry->group, chunk_entry->i.inode, 1)) { + if (fsnotify_add_mark(chunk_entry, chunk_entry->group, chunk_entry->i.inode, NULL, 1)) { spin_unlock(&old_entry->lock); free_chunk(chunk); fsnotify_put_mark(old_entry); diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index d85fa538a72..7499397a610 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -101,7 +101,7 @@ static inline struct audit_parent *audit_find_parent(struct inode *inode) struct audit_parent *parent = NULL; struct fsnotify_mark *entry; - entry = fsnotify_find_mark(audit_watch_group, inode); + entry = fsnotify_find_inode_mark(audit_watch_group, inode); if (entry) parent = container_of(entry, struct audit_parent, mark); @@ -158,7 +158,7 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp) fsnotify_init_mark(&parent->mark, audit_watch_free_mark); parent->mark.mask = AUDIT_FS_WATCH; - ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode, 0); + ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode, NULL, 0); if (ret < 0) { audit_free_parent(parent); return ERR_PTR(ret); @@ -517,7 +517,7 @@ static bool audit_watch_should_send_event(struct fsnotify_group *group, struct i struct fsnotify_mark *entry; bool send; - entry = fsnotify_find_mark(group, inode); + entry = fsnotify_find_inode_mark(group, inode); if (!entry) return false; -- cgit v1.2.3 From 3bcf3860a4ff9bbc522820b4b765e65e4deceb3e Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 28 Jul 2010 10:18:37 -0400 Subject: fsnotify: store struct file not struct path Al explains that calling dentry_open() with a mnt/dentry pair is only garunteed to be safe if they are already used in an open struct file. To make sure this is the case don't store and use a struct path in fsnotify, always use a struct file. Signed-off-by: Eric Paris --- fs/notify/fanotify/fanotify.c | 8 ++++---- fs/notify/fanotify/fanotify_user.c | 6 +++--- fs/notify/fsnotify.c | 16 ++++++++-------- fs/notify/inotify/inotify_fsnotify.c | 12 ++++++------ fs/notify/notification.c | 20 +++++++++---------- include/linux/fsnotify.h | 37 ++++++++++++++++-------------------- include/linux/fsnotify_backend.h | 16 ++++++++-------- kernel/audit_watch.c | 4 ++-- 8 files changed, 56 insertions(+), 63 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index f3c40c0e2b8..c2a3029052b 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -17,9 +17,9 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) old->data_type == new->data_type && old->tgid == new->tgid) { switch (old->data_type) { - case (FSNOTIFY_EVENT_PATH): - if ((old->path.mnt == new->path.mnt) && - (old->path.dentry == new->path.dentry)) + case (FSNOTIFY_EVENT_FILE): + if ((old->file->f_path.mnt == new->file->f_path.mnt) && + (old->file->f_path.dentry == new->file->f_path.dentry)) return true; case (FSNOTIFY_EVENT_NONE): return true; @@ -226,7 +226,7 @@ static bool fanotify_should_send_event(struct fsnotify_group *group, struct inod return false; /* if we don't have enough info to send an event to userspace say no */ - if (data_type != FSNOTIFY_EVENT_PATH) + if (data_type != FSNOTIFY_EVENT_FILE) return false; if (mnt) diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 7182c83be90..50cea74bf1c 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -65,7 +65,7 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) if (client_fd < 0) return client_fd; - if (event->data_type != FSNOTIFY_EVENT_PATH) { + if (event->data_type != FSNOTIFY_EVENT_FILE) { WARN_ON(1); put_unused_fd(client_fd); return -EINVAL; @@ -75,8 +75,8 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) * we need a new file handle for the userspace program so it can read even if it was * originally opened O_WRONLY. */ - dentry = dget(event->path.dentry); - mnt = mntget(event->path.mnt); + dentry = dget(event->file->f_path.dentry); + mnt = mntget(event->file->f_path.mnt); /* it's possible this event was an overflow event. in that case dentry and mnt * are NULL; That's fine, just don't call dentry open */ if (dentry && mnt) diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 72aae404531..4788c866473 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -84,7 +84,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) } /* Notify this dentry's parent about a child's events. */ -void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) +void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) { struct dentry *parent; struct inode *p_inode; @@ -92,7 +92,7 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) bool should_update_children = false; if (!dentry) - dentry = path->dentry; + dentry = file->f_path.dentry; if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) return; @@ -124,8 +124,8 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) * specifies these are events which came from a child. */ mask |= FS_EVENT_ON_CHILD; - if (path) - fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH, + if (file) + fsnotify(p_inode, mask, file, FSNOTIFY_EVENT_FILE, dentry->d_name.name, 0); else fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, @@ -154,10 +154,10 @@ void __fsnotify_flush_ignored_mask(struct inode *inode, void *data, int data_is) spin_unlock(&inode->i_lock); } - if (data_is == FSNOTIFY_EVENT_PATH) { + if (data_is == FSNOTIFY_EVENT_FILE) { struct vfsmount *mnt; - mnt = ((struct path *)data)->mnt; + mnt = ((struct file *)data)->f_path.mnt; if (mnt && !hlist_empty(&mnt->mnt_fsnotify_marks)) { spin_lock(&mnt->mnt_root->d_lock); hlist_for_each_entry(mark, node, &mnt->mnt_fsnotify_marks, m.m_list) { @@ -228,8 +228,8 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, !(test_mask & fsnotify_vfsmount_mask)) return 0; - if (data_is == FSNOTIFY_EVENT_PATH) - mnt = ((struct path *)data)->mnt; + if (data_is == FSNOTIFY_EVENT_FILE) + mnt = ((struct file *)data)->f_path.mnt; /* if this inode's directed listeners don't care and nothing on the vfsmount * listeners list cares, nothing to do */ diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 73a1106b354..3c506e0364c 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -52,9 +52,9 @@ static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new !strcmp(old->file_name, new->file_name)) return true; break; - case (FSNOTIFY_EVENT_PATH): - if ((old->path.mnt == new->path.mnt) && - (old->path.dentry == new->path.dentry)) + case (FSNOTIFY_EVENT_FILE): + if ((old->file->f_path.mnt == new->file->f_path.mnt) && + (old->file->f_path.dentry == new->file->f_path.dentry)) return true; break; case (FSNOTIFY_EVENT_NONE): @@ -165,10 +165,10 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode send = (fsn_mark->mask & mask); if (send && (fsn_mark->mask & FS_EXCL_UNLINK) && - (data_type == FSNOTIFY_EVENT_PATH)) { - struct path *path = data; + (data_type == FSNOTIFY_EVENT_FILE)) { + struct file *file = data; - if (d_unlinked(path->dentry)) + if (d_unlinked(file->f_path.dentry)) send = false; } diff --git a/fs/notify/notification.c b/fs/notify/notification.c index f39260f8f86..c106cdd7ff5 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c @@ -31,6 +31,7 @@ * allocated and used. */ +#include #include #include #include @@ -89,8 +90,8 @@ void fsnotify_put_event(struct fsnotify_event *event) if (atomic_dec_and_test(&event->refcnt)) { pr_debug("%s: event=%p\n", __func__, event); - if (event->data_type == FSNOTIFY_EVENT_PATH) - path_put(&event->path); + if (event->data_type == FSNOTIFY_EVENT_FILE) + fput(event->file); BUG_ON(!list_empty(&event->private_data_list)); @@ -375,8 +376,8 @@ struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event) } } event->tgid = get_pid(old_event->tgid); - if (event->data_type == FSNOTIFY_EVENT_PATH) - path_get(&event->path); + if (event->data_type == FSNOTIFY_EVENT_FILE) + get_file(event->file); return event; } @@ -423,11 +424,9 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, event->data_type = data_type; switch (data_type) { - case FSNOTIFY_EVENT_PATH: { - struct path *path = data; - event->path.dentry = path->dentry; - event->path.mnt = path->mnt; - path_get(&event->path); + case FSNOTIFY_EVENT_FILE: { + event->file = data; + get_file(event->file); break; } case FSNOTIFY_EVENT_INODE: @@ -435,8 +434,7 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, break; case FSNOTIFY_EVENT_NONE: event->inode = NULL; - event->path.dentry = NULL; - event->path.mnt = NULL; + event->file = NULL; break; default: BUG(); diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 59d0df43ff9..e4e2204187e 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -26,19 +26,18 @@ static inline void fsnotify_d_instantiate(struct dentry *dentry, } /* Notify this dentry's parent about a child's events. */ -static inline void fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) +static inline void fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) { if (!dentry) - dentry = path->dentry; + dentry = file->f_path.dentry; - __fsnotify_parent(path, dentry, mask); + __fsnotify_parent(file, dentry, mask); } /* simple call site for access decisions */ static inline int fsnotify_perm(struct file *file, int mask) { - struct path *path = &file->f_path; - struct inode *inode = path->dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; __u32 fsnotify_mask = 0; if (file->f_mode & FMODE_NONOTIFY) @@ -52,7 +51,7 @@ static inline int fsnotify_perm(struct file *file, int mask) else BUG(); - return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); + return fsnotify(inode, fsnotify_mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); } /* @@ -187,16 +186,15 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) */ static inline void fsnotify_access(struct file *file) { - struct path *path = &file->f_path; - struct inode *inode = path->dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; __u32 mask = FS_ACCESS; if (S_ISDIR(inode->i_mode)) mask |= FS_IN_ISDIR; if (!(file->f_mode & FMODE_NONOTIFY)) { - fsnotify_parent(path, NULL, mask); - fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); + fsnotify_parent(file, NULL, mask); + fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); } } @@ -205,16 +203,15 @@ static inline void fsnotify_access(struct file *file) */ static inline void fsnotify_modify(struct file *file) { - struct path *path = &file->f_path; - struct inode *inode = path->dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; __u32 mask = FS_MODIFY; if (S_ISDIR(inode->i_mode)) mask |= FS_IN_ISDIR; if (!(file->f_mode & FMODE_NONOTIFY)) { - fsnotify_parent(path, NULL, mask); - fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); + fsnotify_parent(file, NULL, mask); + fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); } } @@ -223,16 +220,15 @@ static inline void fsnotify_modify(struct file *file) */ static inline void fsnotify_open(struct file *file) { - struct path *path = &file->f_path; - struct inode *inode = path->dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; __u32 mask = FS_OPEN; if (S_ISDIR(inode->i_mode)) mask |= FS_IN_ISDIR; if (!(file->f_mode & FMODE_NONOTIFY)) { - fsnotify_parent(path, NULL, mask); - fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); + fsnotify_parent(file, NULL, mask); + fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); } } @@ -241,7 +237,6 @@ static inline void fsnotify_open(struct file *file) */ static inline void fsnotify_close(struct file *file) { - struct path *path = &file->f_path; struct inode *inode = file->f_path.dentry->d_inode; fmode_t mode = file->f_mode; __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE; @@ -250,8 +245,8 @@ static inline void fsnotify_close(struct file *file) mask |= FS_IN_ISDIR; if (!(file->f_mode & FMODE_NONOTIFY)) { - fsnotify_parent(path, NULL, mask); - fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); + fsnotify_parent(file, NULL, mask); + fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); } } diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 564b5ea4a83..3410d388163 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -223,20 +223,20 @@ struct fsnotify_event { /* to_tell may ONLY be dereferenced during handle_event(). */ struct inode *to_tell; /* either the inode the event happened to or its parent */ /* - * depending on the event type we should have either a path or inode - * We hold a reference on path, but NOT on inode. Since we have the ref on - * the path, it may be dereferenced at any point during this object's + * depending on the event type we should have either a file or inode + * We hold a reference on file, but NOT on inode. Since we have the ref on + * the file, it may be dereferenced at any point during this object's * lifetime. That reference is dropped when this object's refcnt hits - * 0. If this event contains an inode instead of a path, the inode may + * 0. If this event contains an inode instead of a file, the inode may * ONLY be used during handle_event(). */ union { - struct path path; + struct file *file; struct inode *inode; }; /* when calling fsnotify tell it if the data is a path or inode */ #define FSNOTIFY_EVENT_NONE 0 -#define FSNOTIFY_EVENT_PATH 1 +#define FSNOTIFY_EVENT_FILE 1 #define FSNOTIFY_EVENT_INODE 2 int data_type; /* which of the above union we have */ atomic_t refcnt; /* how many groups still are using/need to send this event */ @@ -311,7 +311,7 @@ struct fsnotify_mark { /* main fsnotify call to send events */ extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const unsigned char *name, u32 cookie); -extern void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask); +extern void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask); extern void __fsnotify_inode_delete(struct inode *inode); extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); extern u32 fsnotify_get_cookie(void); @@ -444,7 +444,7 @@ static inline int fsnotify(struct inode *to_tell, __u32 mask, void *data, int da return 0; } -static inline void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) +static inline void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) {} static inline void __fsnotify_inode_delete(struct inode *inode) diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 7499397a610..b955a22d8ff 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -545,8 +545,8 @@ static int audit_watch_handle_event(struct fsnotify_group *group, struct fsnotif return 0; switch (event->data_type) { - case (FSNOTIFY_EVENT_PATH): - inode = event->path.dentry->d_inode; + case (FSNOTIFY_EVENT_FILE): + inode = event->file->f_path.dentry->d_inode; break; case (FSNOTIFY_EVENT_INODE): inode = event->inode; -- cgit v1.2.3 From 3a9b16b407f10b2a771bcae13fb5791e527d6bcf Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 28 Jul 2010 10:18:38 -0400 Subject: fsnotify: send fsnotify_mark to groups in event handling functions With the change of fsnotify to use srcu walking the marks list instead of walking the global groups list we now know the mark in question. The code can send the mark to the group's handling functions and the groups won't have to find those marks themselves. Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 4 +++- fs/notify/fanotify/fanotify.c | 8 +++++--- fs/notify/fsnotify.c | 19 ++++++++++--------- fs/notify/inotify/inotify_fsnotify.c | 8 +++++--- include/linux/fsnotify_backend.h | 7 ++++--- kernel/audit_tree.c | 8 +++++--- kernel/audit_watch.c | 8 +++++--- 7 files changed, 37 insertions(+), 25 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 6624c2ee878..2cae9be120d 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -83,6 +83,7 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark) * events. */ static int dnotify_handle_event(struct fsnotify_group *group, + struct fsnotify_mark *mark, struct fsnotify_event *event) { struct fsnotify_mark *fsn_mark = NULL; @@ -130,7 +131,8 @@ static int dnotify_handle_event(struct fsnotify_group *group, */ static bool dnotify_should_send_event(struct fsnotify_group *group, struct inode *inode, struct vfsmount *mnt, - __u32 mask, void *data, int data_type) + struct fsnotify_mark *mark, __u32 mask, + void *data, int data_type) { struct fsnotify_mark *fsn_mark; bool send; diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index c2a3029052b..abfba45abe2 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -114,7 +114,9 @@ static int fanotify_get_response_from_access(struct fsnotify_group *group, } #endif -static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) +static int fanotify_handle_event(struct fsnotify_group *group, + struct fsnotify_mark *mark, + struct fsnotify_event *event) { int ret = 0; struct fsnotify_event *notify_event = NULL; @@ -214,8 +216,8 @@ static bool should_send_inode_event(struct fsnotify_group *group, struct inode * } static bool fanotify_should_send_event(struct fsnotify_group *group, struct inode *to_tell, - struct vfsmount *mnt, __u32 mask, void *data, - int data_type) + struct vfsmount *mnt, struct fsnotify_mark *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); diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 4678b416241..59d639996ca 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -171,15 +171,16 @@ void __fsnotify_flush_ignored_mask(struct inode *inode, void *data, int data_is) } static int send_to_group(struct fsnotify_group *group, struct inode *to_tell, - struct vfsmount *mnt, __u32 mask, void *data, - int data_is, u32 cookie, const unsigned char *file_name, + struct vfsmount *mnt, struct fsnotify_mark *mark, + __u32 mask, void *data, int data_is, u32 cookie, + const unsigned char *file_name, struct fsnotify_event **event) { - pr_debug("%s: group=%p to_tell=%p mnt=%p mask=%x data=%p data_is=%d" - " cookie=%d event=%p\n", __func__, group, to_tell, mnt, - mask, data, data_is, cookie, *event); + pr_debug("%s: group=%p to_tell=%p mnt=%p mark=%p mask=%x data=%p" + " data_is=%d cookie=%d event=%p\n", __func__, group, to_tell, + mnt, mark, mask, data, data_is, cookie, *event); - if (!group->ops->should_send_event(group, to_tell, mnt, mask, + if (!group->ops->should_send_event(group, to_tell, mnt, mark, mask, data, data_is)) return 0; if (!*event) { @@ -189,7 +190,7 @@ static int send_to_group(struct fsnotify_group *group, struct inode *to_tell, if (!*event) return -ENOMEM; } - return group->ops->handle_event(group, *event); + return group->ops->handle_event(group, mark, *event); } static bool needed_by_vfsmount(__u32 test_mask, struct vfsmount *mnt) @@ -252,7 +253,7 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, group = mark->group; if (!group) continue; - ret = send_to_group(group, to_tell, NULL, mask, + ret = send_to_group(group, to_tell, NULL, mark, mask, data, data_is, cookie, file_name, &event); if (ret) @@ -271,7 +272,7 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, group = mark->group; if (!group) continue; - ret = send_to_group(group, to_tell, mnt, mask, + ret = send_to_group(group, to_tell, mnt, mark, mask, data, data_is, cookie, file_name, &event); if (ret) diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 3c506e0364c..dbd76bbb3e2 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -89,7 +89,9 @@ static struct fsnotify_event *inotify_merge(struct list_head *list, return last_event; } -static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) +static int inotify_handle_event(struct fsnotify_group *group, + struct fsnotify_mark *mark, + struct fsnotify_event *event) { struct fsnotify_mark *fsn_mark; struct inotify_inode_mark *i_mark; @@ -148,8 +150,8 @@ 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, __u32 mask, void *data, - int data_type) + struct vfsmount *mnt, struct fsnotify_mark *mark, + __u32 mask, void *data, int data_type) { struct fsnotify_mark *fsn_mark; bool send; diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 84159390969..225dc0c3a48 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -92,9 +92,10 @@ struct fsnotify_event_private_data; */ struct fsnotify_ops { bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode, - struct vfsmount *mnt, __u32 mask, void *data, - int data_type); - int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event); + struct vfsmount *mnt, struct fsnotify_mark *mark, + __u32 mask, void *data, int data_type); + int (*handle_event)(struct fsnotify_group *group, struct fsnotify_mark *mark, + struct fsnotify_event *event); void (*free_group_priv)(struct fsnotify_group *group); void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group); void (*free_event_priv)(struct fsnotify_event_private_data *priv); diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index cfb97d752a6..584b9436021 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -903,7 +903,9 @@ static void evict_chunk(struct audit_chunk *chunk) mutex_unlock(&audit_filter_mutex); } -static int audit_tree_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) +static int audit_tree_handle_event(struct fsnotify_group *group, + struct fsnotify_mark *mark, + struct fsnotify_event *event) { BUG(); return -EOPNOTSUPP; @@ -918,8 +920,8 @@ static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify } static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode, - struct vfsmount *mnt, __u32 mask, void *data, - int data_type) + struct vfsmount *mnt, struct fsnotify_mark *mark, + __u32 mask, void *data, int data_type) { return 0; } diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index b955a22d8ff..4d5ea0319a6 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -511,8 +511,8 @@ void audit_remove_watch_rule(struct audit_krule *krule) } static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode, - struct vfsmount *mnt, __u32 mask, void *data, - int data_type) + struct vfsmount *mnt, struct fsnotify_mark *mark, + __u32 mask, void *data, int data_type) { struct fsnotify_mark *entry; bool send; @@ -531,7 +531,9 @@ 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 fsnotify_event *event) +static int audit_watch_handle_event(struct fsnotify_group *group, + struct fsnotify_mark *mark, + struct fsnotify_event *event) { struct inode *inode; __u32 mask = event->mask; -- cgit v1.2.3 From 4cd76a47924cd966799402d0f2bba356cde5c1b3 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 28 Jul 2010 10:18:38 -0400 Subject: audit: use the mark in handler functions audit now gets a mark in the should_send_event and handle_event functions. Rather than look up the mark themselves audit should just use the mark it was handed. Signed-off-by: Eric Paris --- kernel/audit_watch.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 4d5ea0319a6..9173bcf3376 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -514,18 +514,10 @@ static bool audit_watch_should_send_event(struct fsnotify_group *group, struct i struct vfsmount *mnt, struct fsnotify_mark *mark, __u32 mask, void *data, int data_type) { - struct fsnotify_mark *entry; bool send; - entry = fsnotify_find_inode_mark(group, inode); - if (!entry) - return false; - mask = (mask & ~FS_EVENT_ON_CHILD); - send = (entry->mask & mask); - - /* find took a reference */ - fsnotify_put_mark(entry); + send = (mark->mask & mask); return send; } @@ -540,11 +532,9 @@ static int audit_watch_handle_event(struct fsnotify_group *group, const char *dname = event->file_name; struct audit_parent *parent; - BUG_ON(group != audit_watch_group); + parent = container_of(mark, struct audit_parent, mark); - parent = audit_find_parent(event->to_tell); - if (unlikely(!parent)) - return 0; + BUG_ON(group != audit_watch_group); switch (event->data_type) { case (FSNOTIFY_EVENT_FILE): @@ -565,10 +555,6 @@ static int audit_watch_handle_event(struct fsnotify_group *group, audit_update_watch(parent, dname, (dev_t)-1, (unsigned long)-1, 1); else if (mask & (FS_DELETE_SELF|FS_UNMOUNT|FS_MOVE_SELF)) audit_remove_parent_watches(parent); - /* moved put_inotify_watch to freeing mark */ - - /* matched the ref taken by audit_find_parent */ - audit_put_parent(parent); return 0; } -- cgit v1.2.3 From 2612abb51b11ffd2d75c472b11178115f5808909 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 28 Jul 2010 10:18:39 -0400 Subject: fsnotify: cleanup should_send_event The change to use srcu and walk the object list rather than the global fsnotify_group list means that should_send_event is no longer needed for a number of groups and can be simplified for others. Do that. Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 11 +---------- fs/notify/fanotify/fanotify.c | 23 ++++++++--------------- fs/notify/fsnotify.c | 4 ++-- fs/notify/inotify/inotify_fsnotify.c | 14 +++----------- kernel/audit_tree.c | 2 +- kernel/audit_watch.c | 7 +------ 6 files changed, 16 insertions(+), 45 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index e3e855ff0dd..c3dc15879a5 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -129,20 +129,11 @@ static bool dnotify_should_send_event(struct fsnotify_group *group, struct fsnotify_mark *mark, __u32 mask, void *data, int data_type) { - bool send; - - /* !dir_notify_enable should never get here, don't waste time checking - if (!dir_notify_enable) - return 0; */ - /* not a dir, dnotify doesn't care */ if (!S_ISDIR(inode->i_mode)) return false; - mask = (mask & ~FS_EVENT_ON_CHILD); - send = (mask & mark->mask); - - return send; + return true; } static void dnotify_free_mark(struct fsnotify_mark *fsn_mark) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 666ccb73306..fbd7f35c613 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -185,22 +185,15 @@ static bool should_send_inode_event(struct fsnotify_group *group, pr_debug("%s: group=%p inode=%p mark=%p mask=%x\n", __func__, group, inode, mark, mask); - /* if the event is for a child and this inode doesn't care about - * events on the child, don't send it! */ + /* + * 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)) { - mask = 0; - } else { - /* - * We care about children, but do we care about this particular - * type of event? - */ - mask &= ~FS_EVENT_ON_CHILD; - mask &= mark->mask; - mask &= ~mark->ignored_mask; - } - - return mask; + !(mark->mask & FS_EVENT_ON_CHILD)) + return false; + else + return true; } static bool fanotify_should_send_event(struct fsnotify_group *group, struct inode *to_tell, diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 59d639996ca..53b31f46d69 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -180,8 +180,8 @@ static int send_to_group(struct fsnotify_group *group, struct inode *to_tell, " data_is=%d cookie=%d event=%p\n", __func__, group, to_tell, mnt, mark, mask, data, data_is, cookie, *event); - if (!group->ops->should_send_event(group, to_tell, mnt, mark, mask, - data, data_is)) + if (group->ops->should_send_event(group, to_tell, mnt, mark, mask, + data, data_is) == false) return 0; if (!*event) { *event = fsnotify_create_event(to_tell, mask, data, diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index aa3f93c03e0..7cf518b25da 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -142,23 +142,15 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode struct vfsmount *mnt, struct fsnotify_mark *mark, __u32 mask, void *data, int data_type) { - bool send; - - pr_debug("%s: group=%p inode=%p mask=%x data=%p data_type=%d\n", - __func__, group, inode, mask, data, data_type); - - mask = (mask & ~FS_EVENT_ON_CHILD); - send = (mark->mask & mask); - - if (send && (mark->mask & FS_EXCL_UNLINK) && + if ((mark->mask & FS_EXCL_UNLINK) && (data_type == FSNOTIFY_EVENT_FILE)) { struct file *file = data; if (d_unlinked(file->f_path.dentry)) - send = false; + return false; } - return send; + return true; } /* diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 584b9436021..2abb99f3459 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -923,7 +923,7 @@ static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *in struct vfsmount *mnt, struct fsnotify_mark *mark, __u32 mask, void *data, int data_type) { - return 0; + return false; } static const struct fsnotify_ops audit_tree_ops = { diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 9173bcf3376..097a61c65fe 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -514,12 +514,7 @@ static bool audit_watch_should_send_event(struct fsnotify_group *group, struct i struct vfsmount *mnt, struct fsnotify_mark *mark, __u32 mask, void *data, int data_type) { - bool send; - - mask = (mask & ~FS_EVENT_ON_CHILD); - send = (mark->mask & mask); - - return send; + return true; } /* Update watch data in audit rules based on fsnotify events. */ -- cgit v1.2.3 From 43709a288ed03aa0e2979ab63dd089b3889645c4 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 28 Jul 2010 10:18:39 -0400 Subject: fsnotify: remove group->mask group->mask is now useless. It was originally a shortcut for fsnotify to save on performance. These checks are now redundant, so we remove them. Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 4 ---- fs/notify/fanotify/fanotify_user.c | 23 +++++------------------ fs/notify/group.c | 16 ---------------- fs/notify/inotify/inotify_user.c | 9 --------- include/linux/fsnotify_backend.h | 11 ----------- kernel/audit_watch.c | 8 -------- 6 files changed, 5 insertions(+), 66 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index c3dc15879a5..e92b2c87ae9 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -199,8 +199,6 @@ void dnotify_flush(struct file *filp, fl_owner_t id) if (dn_mark->dn == NULL) fsnotify_destroy_mark(fsn_mark); - fsnotify_recalc_group_mask(dnotify_group); - mutex_unlock(&dnotify_mark_mutex); fsnotify_put_mark(fsn_mark); @@ -385,8 +383,6 @@ out: if (destroy) fsnotify_destroy_mark(fsn_mark); - fsnotify_recalc_group_mask(dnotify_group); - mutex_unlock(&dnotify_mark_mutex); fsnotify_put_mark(fsn_mark); out_err: diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 50cea74bf1c..25a3b4dfcf6 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -496,8 +496,6 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags); fsnotify_put_mark(fsn_mark); - if (removed & group->mask) - fsnotify_recalc_group_mask(group); if (removed & mnt->mnt_fsnotify_mask) fsnotify_recalc_vfsmount_mask(mnt); @@ -518,9 +516,6 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group, removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags); /* matches the fsnotify_find_inode_mark() */ fsnotify_put_mark(fsn_mark); - - if (removed & group->mask) - fsnotify_recalc_group_mask(group); if (removed & inode->i_fsnotify_mask) fsnotify_recalc_inode_mask(inode); @@ -572,12 +567,9 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group, } added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); fsnotify_put_mark(fsn_mark); - if (added) { - if (added & ~group->mask) - fsnotify_recalc_group_mask(group); - if (added & ~mnt->mnt_fsnotify_mask) - fsnotify_recalc_vfsmount_mask(mnt); - } + if (added & ~mnt->mnt_fsnotify_mask) + fsnotify_recalc_vfsmount_mask(mnt); + return 0; } @@ -607,12 +599,8 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group, } added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); fsnotify_put_mark(fsn_mark); - if (added) { - if (added & ~group->mask) - fsnotify_recalc_group_mask(group); - if (added & ~inode->i_fsnotify_mask) - fsnotify_recalc_inode_mask(inode); - } + if (added & ~inode->i_fsnotify_mask) + fsnotify_recalc_inode_mask(inode); return 0; } @@ -734,7 +722,6 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags, fsnotify_clear_vfsmount_marks_by_group(group); else fsnotify_clear_inode_marks_by_group(group); - fsnotify_recalc_group_mask(group); break; default: ret = -EINVAL; diff --git a/fs/notify/group.c b/fs/notify/group.c index 8da532dd602..fc0d966b270 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c @@ -35,22 +35,6 @@ LIST_HEAD(fsnotify_inode_groups); /* all groups registered to receive mount point filesystem notifications */ LIST_HEAD(fsnotify_vfsmount_groups); -/* - * Update the group->mask by running all of the marks associated with this - * group and finding the bitwise | of all of the mark->mask. - */ -void fsnotify_recalc_group_mask(struct fsnotify_group *group) -{ - __u32 mask = 0; - struct fsnotify_mark *mark; - - spin_lock(&group->mark_lock); - list_for_each_entry(mark, &group->marks_list, g_list) - mask |= mark->mask; - group->mask = mask; - spin_unlock(&group->mark_lock); -} - void fsnotify_add_vfsmount_group(struct fsnotify_group *group) { struct fsnotify_group *group_iter; diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index a4cd227c4c7..bf7f6d776c3 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -606,16 +606,11 @@ static int inotify_update_existing_watch(struct fsnotify_group *group, int dropped = (old_mask & ~new_mask); /* more bits in this fsn_mark than the inode's mask? */ int do_inode = (new_mask & ~inode->i_fsnotify_mask); - /* more bits in this fsn_mark than the group? */ - int do_group = (new_mask & ~group->mask); /* update the inode with this new fsn_mark */ if (dropped || do_inode) fsnotify_recalc_inode_mask(inode); - /* update the group mask with the new mask */ - if (dropped || do_group) - fsnotify_recalc_group_mask(group); } /* return the wd */ @@ -673,10 +668,6 @@ static int inotify_new_watch(struct fsnotify_group *group, /* return the watch descriptor for this new mark */ ret = tmp_i_mark->wd; - /* if this mark added a new event update the group mask */ - if (mask & ~group->mask) - fsnotify_recalc_group_mask(group); - out_err: /* match the ref from fsnotify_init_mark() */ fsnotify_put_mark(&tmp_i_mark->fsn_mark); diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 07d3c895472..c4e7aab8746 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -119,15 +119,6 @@ struct fsnotify_group { */ struct list_head vfsmount_group_list; - /* - * Defines all of the event types in which this group is interested. - * This mask is a bitwise OR of the FS_* events from above. Each time - * this mask changes for a group (if it changes) the correct functions - * must be called to update the global structures which indicate global - * interest in event types. - */ - __u32 mask; - /* * How the refcnt is used is up to each group. When the refcnt hits 0 * fsnotify will clean up all of the resources associated with this group. @@ -367,8 +358,6 @@ static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode /* get a reference to an existing or create a new group */ extern struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops); -/* run all marks associated with this group and update group->mask */ -extern void fsnotify_recalc_group_mask(struct fsnotify_group *group); /* drop reference on a group from fsnotify_alloc_group */ extern void fsnotify_put_group(struct fsnotify_group *group); diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 097a61c65fe..1b87e757845 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -164,8 +164,6 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp) return ERR_PTR(ret); } - fsnotify_recalc_group_mask(audit_watch_group); - return parent; } @@ -352,9 +350,6 @@ static void audit_remove_parent_watches(struct audit_parent *parent) mutex_unlock(&audit_filter_mutex); fsnotify_destroy_mark(&parent->mark); - - fsnotify_recalc_group_mask(audit_watch_group); - } /* Get path information necessary for adding watches. */ @@ -505,9 +500,6 @@ void audit_remove_watch_rule(struct audit_krule *krule) audit_put_parent(parent); } } - - fsnotify_recalc_group_mask(audit_watch_group); - } static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode, -- cgit v1.2.3 From ce8f76fb7320297ccbe7c950fd9a2d727dd6a5a0 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 28 Jul 2010 10:18:39 -0400 Subject: fsnotify: pass both the vfsmount mark and inode mark should_send_event() and handle_event() will both need to look up the inode event if they get a vfsmount event. Lets just pass both at the same time since we have them both after walking the lists in lockstep. Signed-off-by: Eric Paris --- fs/notify/dnotify/dnotify.c | 18 ++++++---- fs/notify/fanotify/fanotify.c | 15 +++++--- fs/notify/fsnotify.c | 70 ++++++++++++++++++++++++------------ fs/notify/inotify/inotify_fsnotify.c | 12 ++++--- include/linux/fsnotify_backend.h | 7 ++-- kernel/audit_tree.c | 6 ++-- kernel/audit_watch.c | 8 +++-- 7 files changed, 91 insertions(+), 45 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index e92b2c87ae9..bda588b831a 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -83,7 +83,8 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark) * events. */ static int dnotify_handle_event(struct fsnotify_group *group, - struct fsnotify_mark *mark, + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, struct fsnotify_event *event) { struct dnotify_mark *dn_mark; @@ -93,11 +94,13 @@ static int dnotify_handle_event(struct fsnotify_group *group, struct fown_struct *fown; __u32 test_mask = event->mask & ~FS_EVENT_ON_CHILD; + BUG_ON(vfsmount_mark); + to_tell = event->to_tell; - dn_mark = container_of(mark, struct dnotify_mark, fsn_mark); + dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark); - spin_lock(&mark->lock); + spin_lock(&inode_mark->lock); prev = &dn_mark->dn; while ((dn = *prev) != NULL) { if ((dn->dn_mask & test_mask) == 0) { @@ -111,11 +114,11 @@ static int dnotify_handle_event(struct fsnotify_group *group, else { *prev = dn->dn_next; kmem_cache_free(dnotify_struct_cache, dn); - dnotify_recalc_inode_mask(mark); + dnotify_recalc_inode_mask(inode_mark); } } - spin_unlock(&mark->lock); + spin_unlock(&inode_mark->lock); return 0; } @@ -126,8 +129,9 @@ static int dnotify_handle_event(struct fsnotify_group *group, */ static bool dnotify_should_send_event(struct fsnotify_group *group, struct inode *inode, struct vfsmount *mnt, - struct fsnotify_mark *mark, __u32 mask, - void *data, int data_type) + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, + __u32 mask, void *data, int data_type) { /* not a dir, dnotify doesn't care */ if (!S_ISDIR(inode->i_mode)) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index fbd7f35c613..ef4fa4a45c9 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -115,7 +115,8 @@ static int fanotify_get_response_from_access(struct fsnotify_group *group, #endif static int fanotify_handle_event(struct fsnotify_group *group, - struct fsnotify_mark *mark, + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *fanotify_mark, struct fsnotify_event *event) { int ret = 0; @@ -196,8 +197,11 @@ static bool should_send_inode_event(struct fsnotify_group *group, return true; } -static bool fanotify_should_send_event(struct fsnotify_group *group, struct inode *to_tell, - struct vfsmount *mnt, struct fsnotify_mark *mark, +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", @@ -213,9 +217,10 @@ static bool fanotify_should_send_event(struct fsnotify_group *group, struct inod return false; if (mnt) - return should_send_vfsmount_event(group, mnt, to_tell, mark, mask); + return should_send_vfsmount_event(group, mnt, to_tell, + vfsmount_mark, mask); else - return should_send_inode_event(group, to_tell, mark, mask); + return should_send_inode_event(group, to_tell, inode_mark, mask); } const struct fsnotify_ops fanotify_fsnotify_ops = { diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index cdaa51cb698..090b64c3b4f 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -141,28 +141,51 @@ void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) EXPORT_SYMBOL_GPL(__fsnotify_parent); static int send_to_group(struct inode *to_tell, struct vfsmount *mnt, - struct fsnotify_mark *mark, - __u32 mask, void *data, + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, + __u32 mask, void *data, int data_is, u32 cookie, const unsigned char *file_name, struct fsnotify_event **event) { - struct fsnotify_group *group = mark->group; - __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); + struct fsnotify_group *group = inode_mark->group; + __u32 inode_test_mask = (mask & ~FS_EVENT_ON_CHILD); + __u32 vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD); pr_debug("%s: group=%p to_tell=%p mnt=%p mark=%p mask=%x data=%p" " data_is=%d cookie=%d event=%p\n", __func__, group, to_tell, - mnt, mark, mask, data, data_is, cookie, *event); + mnt, inode_mark, mask, data, data_is, cookie, *event); + + /* clear ignored on inode modification */ + if (mask & FS_MODIFY) { + if (inode_mark && + !(inode_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) + inode_mark->ignored_mask = 0; + if (vfsmount_mark && + !(vfsmount_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) + vfsmount_mark->ignored_mask = 0; + } - if ((mask & FS_MODIFY) && - !(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) - mark->ignored_mask = 0; + /* does the inode mark tell us to do something? */ + if (inode_mark) { + inode_test_mask &= inode_mark->mask; + inode_test_mask &= ~inode_mark->ignored_mask; + } - if (!(test_mask & mark->mask & ~mark->ignored_mask)) + /* does the vfsmount_mark tell us to do something? */ + if (vfsmount_mark) { + vfsmount_test_mask &= vfsmount_mark->mask; + vfsmount_test_mask &= ~vfsmount_mark->ignored_mask; + if (inode_mark) + vfsmount_test_mask &= ~inode_mark->ignored_mask; + } + + if (!inode_test_mask && !vfsmount_test_mask) return 0; - if (group->ops->should_send_event(group, to_tell, mnt, mark, mask, - data, data_is) == false) + if (group->ops->should_send_event(group, to_tell, mnt, inode_mark, + vfsmount_mark, mask, data, + data_is) == false) return 0; if (!*event) { @@ -172,7 +195,7 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt, if (!*event) return -ENOMEM; } - return group->ops->handle_event(group, mark, *event); + return group->ops->handle_event(group, inode_mark, vfsmount_mark, *event); } /* @@ -213,14 +236,16 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, if ((mask & FS_MODIFY) || (test_mask & to_tell->i_fsnotify_mask)) - inode_node = to_tell->i_fsnotify_marks.first; + inode_node = srcu_dereference(to_tell->i_fsnotify_marks.first, + &fsnotify_mark_srcu); else inode_node = NULL; if (mnt) { if ((mask & FS_MODIFY) || (test_mask & mnt->mnt_fsnotify_mask)) - vfsmount_node = mnt->mnt_fsnotify_marks.first; + vfsmount_node = srcu_dereference(mnt->mnt_fsnotify_marks.first, + &fsnotify_mark_srcu); else vfsmount_node = NULL; } else { @@ -245,26 +270,27 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, if (inode_group < vfsmount_group) { /* handle inode */ - send_to_group(to_tell, NULL, inode_mark, mask, data, + send_to_group(to_tell, NULL, inode_mark, NULL, mask, data, data_is, cookie, file_name, &event); used_inode = true; } else if (vfsmount_group < inode_group) { - send_to_group(to_tell, mnt, vfsmount_mark, mask, data, + send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data, data_is, cookie, file_name, &event); used_vfsmount = true; } else { - send_to_group(to_tell, mnt, vfsmount_mark, mask, data, - data_is, cookie, file_name, &event); + send_to_group(to_tell, mnt, inode_mark, vfsmount_mark, + mask, data, data_is, cookie, file_name, + &event); used_vfsmount = true; - send_to_group(to_tell, NULL, inode_mark, mask, data, - data_is, cookie, file_name, &event); used_inode = true; } if (used_inode) - inode_node = inode_node->next; + inode_node = srcu_dereference(inode_node->next, + &fsnotify_mark_srcu); if (used_vfsmount) - vfsmount_node = vfsmount_node->next; + vfsmount_node = srcu_dereference(vfsmount_node->next, + &fsnotify_mark_srcu); } srcu_read_unlock(&fsnotify_mark_srcu, idx); diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 7cf518b25da..e53f49731b6 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -90,7 +90,8 @@ static struct fsnotify_event *inotify_merge(struct list_head *list, } static int inotify_handle_event(struct fsnotify_group *group, - struct fsnotify_mark *mark, + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, struct fsnotify_event *event) { struct inotify_inode_mark *i_mark; @@ -100,12 +101,14 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *added_event; int wd, ret = 0; + BUG_ON(vfsmount_mark); + pr_debug("%s: group=%p event=%p to_tell=%p mask=%x\n", __func__, group, event, event->to_tell, event->mask); to_tell = event->to_tell; - i_mark = container_of(mark, struct inotify_inode_mark, + i_mark = container_of(inode_mark, struct inotify_inode_mark, fsn_mark); wd = i_mark->wd; @@ -127,8 +130,8 @@ static int inotify_handle_event(struct fsnotify_group *group, ret = PTR_ERR(added_event); } - if (mark->mask & IN_ONESHOT) - fsnotify_destroy_mark(mark); + if (inode_mark->mask & IN_ONESHOT) + fsnotify_destroy_mark(inode_mark); return ret; } @@ -140,6 +143,7 @@ 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 *vfsmount_mark, __u32 mask, void *data, int data_type) { if ((mark->mask & FS_EXCL_UNLINK) && diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 2e7cc8c2a15..d38f922977f 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -92,9 +92,12 @@ 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 *mark, + struct vfsmount *mnt, struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, __u32 mask, void *data, int data_type); - int (*handle_event)(struct fsnotify_group *group, struct fsnotify_mark *mark, + int (*handle_event)(struct fsnotify_group *group, + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, struct fsnotify_event *event); void (*free_group_priv)(struct fsnotify_group *group); void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group); diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 2abb99f3459..781ab7f4e35 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -904,7 +904,8 @@ static void evict_chunk(struct audit_chunk *chunk) } static int audit_tree_handle_event(struct fsnotify_group *group, - struct fsnotify_mark *mark, + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmonut_mark, struct fsnotify_event *event) { BUG(); @@ -920,7 +921,8 @@ static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify } static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode, - struct vfsmount *mnt, struct fsnotify_mark *mark, + struct vfsmount *mnt, struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, __u32 mask, void *data, int data_type) { return false; diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 1b87e757845..a273cf34052 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -503,7 +503,8 @@ void audit_remove_watch_rule(struct audit_krule *krule) } static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode, - struct vfsmount *mnt, struct fsnotify_mark *mark, + struct vfsmount *mnt, struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, __u32 mask, void *data, int data_type) { return true; @@ -511,7 +512,8 @@ 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 fsnotify_mark *mark, + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, struct fsnotify_event *event) { struct inode *inode; @@ -519,7 +521,7 @@ static int audit_watch_handle_event(struct fsnotify_group *group, const char *dname = event->file_name; struct audit_parent *parent; - parent = container_of(mark, struct audit_parent, mark); + parent = container_of(inode_mark, struct audit_parent, mark); BUG_ON(group != audit_watch_group); -- cgit v1.2.3 From 1968f5eed54ce47bde488fd9a450912e4a2d7138 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 28 Jul 2010 10:18:39 -0400 Subject: 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: Eric Paris --- fs/notify/dnotify/dnotify.c | 2 +- fs/notify/fanotify/fanotify.c | 88 ++++++++++++++---------------------- fs/notify/fsnotify.c | 2 +- fs/notify/inotify/inotify_fsnotify.c | 4 +- include/linux/fsnotify_backend.h | 2 +- kernel/audit_tree.c | 2 +- kernel/audit_watch.c | 2 +- 7 files changed, 41 insertions(+), 61 deletions(-) (limited to 'kernel/audit_watch.c') diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index bda588b831a..3344bdd5506 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -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) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index ef4fa4a45c9..eb8f73c9c13 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -153,59 +153,20 @@ 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) -{ - struct fsnotify_mark *inode_mark; - - pr_debug("%s: group=%p vfsmount=%p mark=%p mask=%x\n", - __func__, group, mnt, mnt_mark, mask); - - mask &= mnt_mark->mask; - mask &= ~mnt_mark->ignored_mask; - - if (mask) { - inode_mark = fsnotify_find_inode_mark(group, inode); - if (inode_mark) { - mask &= ~inode_mark->ignored_mask; - fsnotify_put_mark(inode_mark); - } - } - - return mask; -} - -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 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)) - return false; - else - return true; -} - 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) + struct fsnotify_mark *vfsmnt_mark, + __u32 event_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); + __u32 marks_mask, marks_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); + + pr_debug("%s: group=%p vfsmount_mark=%p inode_mark=%p mask=%x\n", + __func__, group, vfsmnt_mark, inode_mark, event_mask); /* sorry, fanotify only gives a damn about files and dirs */ if (!S_ISREG(to_tell->i_mode) && @@ -216,11 +177,30 @@ static bool fanotify_should_send_event(struct fsnotify_group *group, 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); + 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 ((event_mask & FS_EVENT_ON_CHILD) && + !(inode_mark->mask & FS_EVENT_ON_CHILD)) + return false; + 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(); + } + + if (event_mask & marks_mask & ~marks_ignored_mask) + return true; + + return false; } const struct fsnotify_ops fanotify_fsnotify_ops = { diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 090b64c3b4f..4d2a82c1ceb 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -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; diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index e53f49731b6..5e73eeb2c69 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -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; diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index d38f922977f..9bbfd7204b0 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -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, diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 781ab7f4e35..7f18d3a4527 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -921,7 +921,7 @@ static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify } static bool audit_tree_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) { diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index a273cf34052..6bf2306be7d 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -503,7 +503,7 @@ void audit_remove_watch_rule(struct audit_krule *krule) } static bool audit_watch_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) { -- cgit v1.2.3