summaryrefslogtreecommitdiffstats
path: root/fs/notify/mark.c
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2012-01-12 17:59:46 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-15 03:01:42 +0100
commitfed474857efbed79cd390d0aee224231ca718f63 (patch)
tree8935acfe89c87fe63f72bb114fa17f97f7c26564 /fs/notify/mark.c
parentMerge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ros... (diff)
downloadlinux-fed474857efbed79cd390d0aee224231ca718f63.tar.xz
linux-fed474857efbed79cd390d0aee224231ca718f63.zip
fsnotify: don't BUG in fsnotify_destroy_mark()
Removing the parent of a watched file results in "kernel BUG at fs/notify/mark.c:139". To reproduce add "-w /tmp/audit/dir/watched_file" to audit.rules rm -rf /tmp/audit/dir This is caused by fsnotify_destroy_mark() being called without an extra reference taken by the caller. Reported by Francesco Cosoleto here: https://bugzilla.novell.com/show_bug.cgi?id=689860 Fix by removing the BUG_ON and adding a comment about not accessing mark after the iput. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> CC: stable@vger.kernel.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/notify/mark.c')
-rw-r--r--fs/notify/mark.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index e14587d55689..f104d565b682 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -135,9 +135,6 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
- /* 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) {
@@ -182,6 +179,11 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
iput(inode);
/*
+ * We don't necessarily have a ref on mark from caller so the above iput
+ * may have already destroyed it. Don't touch from now on.
+ */
+
+ /*
* 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.