fsnotify: take inode->i_lock inside fsnotify_find_mark_entry()
authorAndreas Gruenbacher <agruen@suse.de>
Fri, 18 Dec 2009 02:24:25 +0000 (21:24 -0500)
committerEric Paris <eparis@redhat.com>
Wed, 28 Jul 2010 13:58:54 +0000 (09:58 -0400)
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 <agruen@suse.de>
Signed-off-by: Eric Paris <eparis@redhat.com>
fs/notify/dnotify/dnotify.c
fs/notify/inode_mark.c
fs/notify/inotify/inotify_fsnotify.c
fs/notify/inotify/inotify_user.c
kernel/audit_tree.c
kernel/audit_watch.c

index 3efb8b9..cac2eb8 100644 (file)
@@ -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);
index 27c1b43..ba6f983 100644 (file)
@@ -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;
index 12dc72b..cc8f6bc 100644 (file)
@@ -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;
 
index 80d102a..ad5a1ea 100644 (file)
@@ -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;
 
index b20fb05..80f8ac3 100644 (file)
@@ -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);
 
index 24ecbeb..d85fa53 100644 (file)
@@ -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;