fsnotify: allow addition of duplicate fsnotify marks
authorEric Paris <eparis@redhat.com>
Fri, 18 Dec 2009 01:12:05 +0000 (20:12 -0500)
committerEric Paris <eparis@redhat.com>
Wed, 28 Jul 2010 13:58:17 +0000 (09:58 -0400)
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 <eparis@redhat.com>
fs/notify/dnotify/dnotify.c
fs/notify/inode_mark.c
fs/notify/inotify/inotify_user.c
include/linux/fsnotify_backend.h
kernel/audit_watch.c

index 7e54e52964dd7e7b0a7de23ca682b33b9f8f8e62..85b97fca14de31e45068d6c4a09a72866212085e 100644 (file)
@@ -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;
index a13cf9e9233af34c1c6af8ccb853eae6c7959025..7d2962e5328ee5c0575ae02fd43e250ccdb85daa 100644 (file)
@@ -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;
index 653c507b1bb372a928f67fc94eaeb3d13fc83c3a..f22a04005db21145add6647352ff6b3e3848078b 100644 (file)
@@ -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);
index 390516732956b10db6d30417d16b2a5ece331c22..1679f250d59ea116b1af533d47629f4001592939 100644 (file)
@@ -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 */
index 75ab53987ece1e82df31370b3d4b6b302d425594..c44de0c4fc474e0723e078826231225be2aeb2fd 100644 (file)
@@ -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);