summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-07-28 10:18:39 -0400
committerEric Paris <eparis@redhat.com>2010-07-28 10:18:55 -0400
commit1968f5eed54ce47bde488fd9a450912e4a2d7138 (patch)
treebcf13b98fda519c240e89cae3de95fc7d9ece715
parentce8f76fb7320297ccbe7c950fd9a2d727dd6a5a0 (diff)
downloadkernel-common-1968f5eed54ce47bde488fd9a450912e4a2d7138.tar.gz
kernel-common-1968f5eed54ce47bde488fd9a450912e4a2d7138.tar.bz2
kernel-common-1968f5eed54ce47bde488fd9a450912e4a2d7138.zip
fanotify: use both marks when possible
fanotify currently, when given a vfsmount_mark will look up (if it exists) the corresponding inode mark. This patch drops that lookup and uses the mark provided. Signed-off-by: Eric Paris <eparis@redhat.com>
-rw-r--r--fs/notify/dnotify/dnotify.c2
-rw-r--r--fs/notify/fanotify/fanotify.c88
-rw-r--r--fs/notify/fsnotify.c2
-rw-r--r--fs/notify/inotify/inotify_fsnotify.c4
-rw-r--r--include/linux/fsnotify_backend.h2
-rw-r--r--kernel/audit_tree.c2
-rw-r--r--kernel/audit_watch.c2
7 files changed, 41 insertions, 61 deletions
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index bda588b831ad..3344bdd5506e 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -128,7 +128,7 @@ static int dnotify_handle_event(struct fsnotify_group *group,
* userspace notification for that pair.
*/
static bool dnotify_should_send_event(struct fsnotify_group *group,
- struct inode *inode, struct vfsmount *mnt,
+ struct inode *inode,
struct fsnotify_mark *inode_mark,
struct fsnotify_mark *vfsmount_mark,
__u32 mask, void *data, int data_type)
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index ef4fa4a45c94..eb8f73c9c131 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -153,59 +153,20 @@ static int fanotify_handle_event(struct fsnotify_group *group,
return ret;
}
-static bool should_send_vfsmount_event(struct fsnotify_group *group,
- struct vfsmount *mnt,
- struct inode *inode,
- struct fsnotify_mark *mnt_mark,
- __u32 mask)
-{
- struct fsnotify_mark *inode_mark;
-
- pr_debug("%s: group=%p vfsmount=%p mark=%p mask=%x\n",
- __func__, group, mnt, mnt_mark, mask);
-
- mask &= mnt_mark->mask;
- mask &= ~mnt_mark->ignored_mask;
-
- if (mask) {
- inode_mark = fsnotify_find_inode_mark(group, inode);
- if (inode_mark) {
- mask &= ~inode_mark->ignored_mask;
- fsnotify_put_mark(inode_mark);
- }
- }
-
- return mask;
-}
-
-static bool should_send_inode_event(struct fsnotify_group *group,
- struct inode *inode,
- struct fsnotify_mark *mark,
- __u32 mask)
-{
- pr_debug("%s: group=%p inode=%p mark=%p mask=%x\n",
- __func__, group, inode, mark, mask);
-
- /*
- * if the event is for a child and this inode doesn't care about
- * events on the child, don't send it!
- */
- if ((mask & FS_EVENT_ON_CHILD) &&
- !(mark->mask & FS_EVENT_ON_CHILD))
- return false;
- else
- return true;
-}
-
static bool fanotify_should_send_event(struct fsnotify_group *group,
struct inode *to_tell,
- struct vfsmount *mnt,
struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
- __u32 mask, void *data, int data_type)
+ struct fsnotify_mark *vfsmnt_mark,
+ __u32 event_mask, void *data, int data_type)
{
- pr_debug("%s: group=%p to_tell=%p mnt=%p mask=%x data=%p data_type=%d\n",
- __func__, group, to_tell, mnt, mask, data, data_type);
+ __u32 marks_mask, marks_ignored_mask;
+
+ pr_debug("%s: group=%p to_tell=%p inode_mark=%p vfsmnt_mark=%p "
+ "mask=%x data=%p data_type=%d\n", __func__, group, to_tell,
+ inode_mark, vfsmnt_mark, event_mask, data, data_type);
+
+ pr_debug("%s: group=%p vfsmount_mark=%p inode_mark=%p mask=%x\n",
+ __func__, group, vfsmnt_mark, inode_mark, event_mask);
/* sorry, fanotify only gives a damn about files and dirs */
if (!S_ISREG(to_tell->i_mode) &&
@@ -216,11 +177,30 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
if (data_type != FSNOTIFY_EVENT_FILE)
return false;
- if (mnt)
- return should_send_vfsmount_event(group, mnt, to_tell,
- vfsmount_mark, mask);
- else
- return should_send_inode_event(group, to_tell, inode_mark, mask);
+ if (inode_mark && vfsmnt_mark) {
+ marks_mask = (vfsmnt_mark->mask | inode_mark->mask);
+ marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask);
+ } else if (inode_mark) {
+ /*
+ * if the event is for a child and this inode doesn't care about
+ * events on the child, don't send it!
+ */
+ if ((event_mask & FS_EVENT_ON_CHILD) &&
+ !(inode_mark->mask & FS_EVENT_ON_CHILD))
+ return false;
+ marks_mask = inode_mark->mask;
+ marks_ignored_mask = inode_mark->ignored_mask;
+ } else if (vfsmnt_mark) {
+ marks_mask = vfsmnt_mark->mask;
+ marks_ignored_mask = vfsmnt_mark->ignored_mask;
+ } else {
+ BUG();
+ }
+
+ if (event_mask & marks_mask & ~marks_ignored_mask)
+ return true;
+
+ return false;
}
const struct fsnotify_ops fanotify_fsnotify_ops = {
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 090b64c3b4f9..4d2a82c1ceb1 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -183,7 +183,7 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
if (!inode_test_mask && !vfsmount_test_mask)
return 0;
- if (group->ops->should_send_event(group, to_tell, mnt, inode_mark,
+ if (group->ops->should_send_event(group, to_tell, inode_mark,
vfsmount_mark, mask, data,
data_is) == false)
return 0;
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index e53f49731b6e..5e73eeb2c697 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -142,11 +142,11 @@ static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify
}
static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode,
- struct vfsmount *mnt, struct fsnotify_mark *mark,
+ struct fsnotify_mark *inode_mark,
struct fsnotify_mark *vfsmount_mark,
__u32 mask, void *data, int data_type)
{
- if ((mark->mask & FS_EXCL_UNLINK) &&
+ if ((inode_mark->mask & FS_EXCL_UNLINK) &&
(data_type == FSNOTIFY_EVENT_FILE)) {
struct file *file = data;
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index d38f922977f9..9bbfd7204b04 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -92,7 +92,7 @@ struct fsnotify_event_private_data;
*/
struct fsnotify_ops {
bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,
- struct vfsmount *mnt, struct fsnotify_mark *inode_mark,
+ struct fsnotify_mark *inode_mark,
struct fsnotify_mark *vfsmount_mark,
__u32 mask, void *data, int data_type);
int (*handle_event)(struct fsnotify_group *group,
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 781ab7f4e35c..7f18d3a4527e 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -921,7 +921,7 @@ static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify
}
static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode,
- struct vfsmount *mnt, struct fsnotify_mark *inode_mark,
+ struct fsnotify_mark *inode_mark,
struct fsnotify_mark *vfsmount_mark,
__u32 mask, void *data, int data_type)
{
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index a273cf340527..6bf2306be7d6 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -503,7 +503,7 @@ void audit_remove_watch_rule(struct audit_krule *krule)
}
static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode,
- struct vfsmount *mnt, struct fsnotify_mark *inode_mark,
+ struct fsnotify_mark *inode_mark,
struct fsnotify_mark *vfsmount_mark,
__u32 mask, void *data, int data_type)
{