From: Chris Wright Date: Wed, 26 Mar 2008 16:09:06 +0000 (-0700) Subject: inotify fixes queued for 2.6.24-stable X-Git-Tag: v2.6.24.5~12 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bf1120c5a8a75601de99db8eaa43b4d48ef38c06;p=thirdparty%2Fkernel%2Fstable-queue.git inotify fixes queued for 2.6.24-stable --- diff --git a/queue-2.6.24/inotify-fix-race.patch b/queue-2.6.24/inotify-fix-race.patch new file mode 100644 index 00000000000..05cddb8af64 --- /dev/null +++ b/queue-2.6.24/inotify-fix-race.patch @@ -0,0 +1,67 @@ +From stable-bounces@linux.kernel.org Wed Mar 26 09:02:24 2008 +To: stable@kernel.org +Message-Id: +From: Christian Lamparter +Date: Tue, 25 Mar 2008 13:48:15 +0100 +Cc: nickpiggin@yahoo.com.au +Subject: inotify: fix race + +From: Nick Piggin + +upstream commit: d599e36a9ea85432587f4550acc113cd7549d12a + +There is a race between setting an inode's children's "parent watched" flag +when placing the first watch on a parent, and instantiating new children of +that parent: a child could miss having its flags set by +set_dentry_child_flags, but then inotify_d_instantiate might still see +!inotify_inode_watched. + +The solution is to set_dentry_child_flags after adding the watch. Locking is +taken care of, because both set_dentry_child_flags and inotify_d_instantiate +hold dcache_lock and child->d_locks. + +Signed-off-by: Nick Piggin +Cc: Robert Love +Cc: John McCutchan +Cc: Jan Kara +Cc: Yan Zheng +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Christian Lamparter +Signed-off-by: Chris Wright +--- + fs/inotify.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/fs/inotify.c ++++ b/fs/inotify.c +@@ -627,6 +627,7 @@ s32 inotify_add_watch(struct inotify_han + struct inode *inode, u32 mask) + { + int ret = 0; ++ int newly_watched; + + /* don't allow invalid bits: we don't want flags set */ + mask &= IN_ALL_EVENTS | IN_ONESHOT; +@@ -653,12 +654,18 @@ s32 inotify_add_watch(struct inotify_han + */ + watch->inode = igrab(inode); + +- if (!inotify_inode_watched(inode)) +- set_dentry_child_flags(inode, 1); +- + /* Add the watch to the handle's and the inode's list */ ++ newly_watched = !inotify_inode_watched(inode); + list_add(&watch->h_list, &ih->watches); + list_add(&watch->i_list, &inode->inotify_watches); ++ /* ++ * Set child flags _after_ adding the watch, so there is no race ++ * windows where newly instantiated children could miss their parent's ++ * watched flag. ++ */ ++ if (newly_watched) ++ set_dentry_child_flags(inode, 1); ++ + out: + mutex_unlock(&ih->mutex); + mutex_unlock(&inode->inotify_mutex); diff --git a/queue-2.6.24/inotify-remove-debug-code.patch b/queue-2.6.24/inotify-remove-debug-code.patch new file mode 100644 index 00000000000..f79202897ca --- /dev/null +++ b/queue-2.6.24/inotify-remove-debug-code.patch @@ -0,0 +1,81 @@ +From stable-bounces@linux.kernel.org Wed Mar 26 09:04:06 2008 +To: stable@kernel.org +Message-Id: +From: Christian Lamparter +Date: Tue, 25 Mar 2008 13:48:18 +0100 +Cc: nickpiggin@yahoo.com.au +Subject: inotify: remove debug code + +From: Nick Piggin + +upstream commit: 0d71bd5993b630a989d15adc2562a9ffe41cd26d + +The inotify debugging code is supposed to verify that the +DCACHE_INOTIFY_PARENT_WATCHED scalability optimisation does not result in +notifications getting lost nor extra needless locking generated. + +Unfortunately there are also some races in the debugging code. And it isn't +very good at finding problems anyway. So remove it for now. + +Signed-off-by: Nick Piggin +Cc: Robert Love +Cc: John McCutchan +Cc: Jan Kara +Cc: Yan Zheng +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Christian Lamparter +Signed-off-by: Chris Wright +--- + fs/dcache.c | 3 --- + fs/inotify.c | 17 +++++------------ + 2 files changed, 5 insertions(+), 15 deletions(-) + +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -1408,9 +1408,6 @@ void d_delete(struct dentry * dentry) + if (atomic_read(&dentry->d_count) == 1) { + dentry_iput(dentry); + fsnotify_nameremove(dentry, isdir); +- +- /* remove this and other inotify debug checks after 2.6.18 */ +- dentry->d_flags &= ~DCACHE_INOTIFY_PARENT_WATCHED; + return; + } + +--- a/fs/inotify.c ++++ b/fs/inotify.c +@@ -168,20 +168,14 @@ static void set_dentry_child_flags(struc + struct dentry *child; + + list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) { +- if (!child->d_inode) { +- WARN_ON(child->d_flags & DCACHE_INOTIFY_PARENT_WATCHED); ++ if (!child->d_inode) + continue; +- } ++ + spin_lock(&child->d_lock); +- if (watched) { +- WARN_ON(child->d_flags & +- DCACHE_INOTIFY_PARENT_WATCHED); ++ if (watched) + child->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED; +- } else { +- WARN_ON(!(child->d_flags & +- DCACHE_INOTIFY_PARENT_WATCHED)); +- child->d_flags&=~DCACHE_INOTIFY_PARENT_WATCHED; +- } ++ else ++ child->d_flags &=~DCACHE_INOTIFY_PARENT_WATCHED; + spin_unlock(&child->d_lock); + } + } +@@ -253,7 +247,6 @@ void inotify_d_instantiate(struct dentry + if (!inode) + return; + +- WARN_ON(entry->d_flags & DCACHE_INOTIFY_PARENT_WATCHED); + spin_lock(&entry->d_lock); + parent = entry->d_parent; + if (parent->d_inode && inotify_inode_watched(parent->d_inode)) diff --git a/queue-2.6.24/series b/queue-2.6.24/series index 6ec465708ee..dfee4f3cc18 100644 --- a/queue-2.6.24/series +++ b/queue-2.6.24/series @@ -6,3 +6,5 @@ v4l-ivtv-add-missing-sg_init_table.patch uio-add-pgprot_noncached-to-uio-mmap-code.patch usb-add-support-for-motorola-rokr-z6-cellphone-in-mass-storage-mode.patch usb-new-quirk-flag-to-avoid-set-interface.patch +inotify-fix-race.patch +inotify-remove-debug-code.patch