summaryrefslogtreecommitdiffstats
path: root/fs/notify
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-04-21 16:49:38 -0400
committerEric Paris <eparis@redhat.com>2010-07-28 09:59:02 -0400
commitb31d397e430a90cbe9d3656929a7d5f96e986666 (patch)
treebafe176811479d922e2f19f4386f34a11a30c39f /fs/notify
parent98b5c10d320adfa250c1c18f3ccaec2f78e5e11d (diff)
downloadlinux-b31d397e430a90cbe9d3656929a7d5f96e986666.tar.gz
linux-b31d397e430a90cbe9d3656929a7d5f96e986666.tar.bz2
linux-b31d397e430a90cbe9d3656929a7d5f96e986666.zip
fsnotify: call iput on inodes when no longer marked
fsnotify takes an igrab on an inode when it adds a mark. The code was supposed to drop the reference when the mark was removed but didn't. This caused problems when an fs was unmounted because those inodes would clearly not be gone. Thus resulting in the most devistating of messages: VFS: Busy inodes after unmount of loop0. Self-destruct in 5 seconds. >>> Have a nice day... Jiri Slaby bisected the problem to a patch in the fsnotify tree. The code snippets below show my stupidity quite clearly. void fsnotify_destroy_inode_mark(struct fsnotify_mark *mark) { ... mark->inode = NULL; ... } void fsnotify_destroy_mark(struct fsnotify_mark *mark) { struct inode *inode = NULL; ... if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) { fsnotify_destroy_inode_mark(mark); inode = mark->i.inode; } ... if (inode) iput(inode); ... } Obviously the intent was to capture the inode before it was set to NULL in fsnotify_destory_inode_mark() so we wouldn't be leaking inodes forever. Instead we leaked them (and exploded on umount) Reported-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs/notify')
-rw-r--r--fs/notify/mark.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index 1e824e64441d..8f3b0e7a543d 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -133,8 +133,8 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
spin_lock(&group->mark_lock);
if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) {
- fsnotify_destroy_inode_mark(mark);
inode = mark->i.inode;
+ fsnotify_destroy_inode_mark(mark);
} else if (mark->flags & FSNOTIFY_MARK_FLAG_VFSMOUNT)
fsnotify_destroy_vfsmount_mark(mark);
else