Add tree-watching support to inotify.
In userspace, you have to add an IN_TREE flag to mask.
Signed-off-by: Joris Dolderer <[email protected]>
---
fs/notify/inotify/inotify_fsnotify.c | 6 ++++--
fs/notify/inotify/inotify_user.c | 11 ++++++++---
include/linux/inotify.h | 2 +-
3 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index 1afb0a1..d42a8cd 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -89,6 +89,7 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode
{
struct fsnotify_mark_entry *entry;
bool send;
+ __u32 test_mask;
spin_lock(&inode->i_lock);
entry = fsnotify_find_mark_entry(group, inode);
@@ -96,8 +97,9 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode
if (!entry)
return false;
- mask = (mask & ~FS_EVENT_ON_CHILD);
- send = (entry->mask & mask);
+ test_mask = mask & ~FS_EVENT_ON_TREE;
+ send = entry->mask & test_mask;
+ send = send && ((mask & FS_EVENT_ON_TREE) ? ((entry->mask & mask) & FS_EVENT_ON_TREE) : true);
/* find took a reference */
fsnotify_put_mark(entry);
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index a94e8bd..575bbf8 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -11,6 +11,8 @@
* Copyright (C) 2009 Eric Paris <Red Hat Inc>
* inotify was largely rewriten to make use of the fsnotify infrastructure
*
+ * Tree-watching support (C) 2010 Joris Dolderer <[email protected]>
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
@@ -100,12 +102,15 @@ static inline __u32 inotify_arg_to_mask(u32 arg)
{
__u32 mask;
- /* everything should accept their own ignored and cares about children */
- mask = (FS_IN_IGNORED | FS_EVENT_ON_CHILD);
+ /* everything should accept their own ignored*/
+ mask = FS_IN_IGNORED;
/* mask off the flags used to open the fd */
mask |= (arg & (IN_ALL_EVENTS | IN_ONESHOT));
+ /* care about children or descents */
+ mask |= (arg & IN_TREE) ? FS_EVENT_ON_DESCENT : FS_EVENT_ON_CHILD;
+
return mask;
}
@@ -505,7 +510,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group,
/* update the inode with this new entry */
if (dropped || do_inode)
- fsnotify_recalc_inode_mask(inode);
+ fsnotify_recalc_inode_mask(inode, (old_mask ^ new_mask) & IN_TREE);
/* update the group mask with the new mask */
if (dropped || do_group)
diff --git a/include/linux/inotify.h b/include/linux/inotify.h
index 37ea289..b5bef0b 100644
--- a/include/linux/inotify.h
+++ b/include/linux/inotify.h
@@ -49,12 +49,12 @@ struct inotify_event {
#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves */
/* special flags */
+#define IN_TREE 0x00800000 /* watch the whole directory tree */
#define IN_ONLYDIR 0x01000000 /* only watch the path if it is a directory */
#define IN_DONT_FOLLOW 0x02000000 /* don't follow a sym link */
#define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */
#define IN_ISDIR 0x40000000 /* event occurred against dir */
#define IN_ONESHOT 0x80000000 /* only send event once */
-
/*
* All of the events - we build the list by hand so that we can add flags in
* the future and not break backward compatibility. Apps will get only the