summaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorNick Piggin <nickpiggin@yahoo.com.au>2006-03-25 03:07:09 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-25 08:22:53 -0800
commitc32ccd87bfd1414b0aabfcd8dbc7539ad23bcbaa (patch)
tree612dc637976cbe36e8b72924a1f7bd76e75463fd /include/linux
parentbf36b9011e3c5b2739f9da2f6de8a6fa3edded32 (diff)
[PATCH] inotify: lock avoidance with parent watch status in dentry
Previous inotify work avoidance is good when inotify is completely unused, but it breaks down if even a single watch is in place anywhere in the system. Robin Holt notices that udev is one such culprit - it slows down a 512-thread application on a 512 CPU system from 6 seconds to 22 minutes. Solve this by adding a flag in the dentry that tells inotify whether or not its parent inode has a watch on it. Event queueing to parent will skip taking locks if this flag is cleared. Setting and clearing of this flag on all child dentries versus event delivery: this is no in terms of race cases, and that was shown to be equivalent to always performing the check. The essential behaviour is that activity occuring _after_ a watch has been added and _before_ it has been removed, will generate events. Signed-off-by: Nick Piggin <npiggin@suse.de> Cc: Robert Love <rml@novell.com> Cc: John McCutchan <ttb@tentacle.dhs.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/dcache.h2
-rw-r--r--include/linux/fsnotify.h19
-rw-r--r--include/linux/inotify.h11
3 files changed, 32 insertions, 0 deletions
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 4361f378997..d10bd30c337 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -162,6 +162,8 @@ d_iput: no no no yes
#define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
#define DCACHE_UNHASHED 0x0010
+#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched */
+
extern spinlock_t dcache_lock;
/**
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 03b8e7932b8..f7e517c1f1b 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -17,6 +17,25 @@
#include <linux/inotify.h>
/*
+ * fsnotify_d_instantiate - instantiate a dentry for inode
+ * Called with dcache_lock held.
+ */
+static inline void fsnotify_d_instantiate(struct dentry *entry,
+ struct inode *inode)
+{
+ inotify_d_instantiate(entry, inode);
+}
+
+/*
+ * fsnotify_d_move - entry has been moved
+ * Called with dcache_lock and entry->d_lock held.
+ */
+static inline void fsnotify_d_move(struct dentry *entry)
+{
+ inotify_d_move(entry);
+}
+
+/*
* fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
*/
static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
diff --git a/include/linux/inotify.h b/include/linux/inotify.h
index 267c88b5f74..09e00433c78 100644
--- a/include/linux/inotify.h
+++ b/include/linux/inotify.h
@@ -71,6 +71,8 @@ struct inotify_event {
#ifdef CONFIG_INOTIFY
+extern void inotify_d_instantiate(struct dentry *, struct inode *);
+extern void inotify_d_move(struct dentry *);
extern void inotify_inode_queue_event(struct inode *, __u32, __u32,
const char *);
extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32,
@@ -81,6 +83,15 @@ extern u32 inotify_get_cookie(void);
#else
+static inline void inotify_d_instantiate(struct dentry *dentry,
+ struct inode *inode)
+{
+}
+
+static inline void inotify_d_move(struct dentry *dentry)
+{
+}
+
static inline void inotify_inode_queue_event(struct inode *inode,
__u32 mask, __u32 cookie,
const char *filename)