aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,
128 * userspace notification for that pair. 128 * userspace notification for that pair.
129 */ 129 */
130static bool dnotify_should_send_event(struct fsnotify_group *group, 130static bool dnotify_should_send_event(struct fsnotify_group *group,
131 struct inode *inode, struct vfsmount *mnt, 131 struct inode *inode,
132 struct fsnotify_mark *inode_mark, 132 struct fsnotify_mark *inode_mark,
133 struct fsnotify_mark *vfsmount_mark, 133 struct fsnotify_mark *vfsmount_mark,
134 __u32 mask, void *data, int data_type) 134 __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,
153 return ret; 153 return ret;
154} 154}
155 155
156static bool should_send_vfsmount_event(struct fsnotify_group *group,
157 struct vfsmount *mnt,
158 struct inode *inode,
159 struct fsnotify_mark *mnt_mark,
160 __u32 mask)
161{
162 struct fsnotify_mark *inode_mark;
163
164 pr_debug("%s: group=%p vfsmount=%p mark=%p mask=%x\n",
165 __func__, group, mnt, mnt_mark, mask);
166
167 mask &= mnt_mark->mask;
168 mask &= ~mnt_mark->ignored_mask;
169
170 if (mask) {
171 inode_mark = fsnotify_find_inode_mark(group, inode);
172 if (inode_mark) {
173 mask &= ~inode_mark->ignored_mask;
174 fsnotify_put_mark(inode_mark);
175 }
176 }
177
178 return mask;
179}
180
181static bool should_send_inode_event(struct fsnotify_group *group,
182 struct inode *inode,
183 struct fsnotify_mark *mark,
184 __u32 mask)
185{
186 pr_debug("%s: group=%p inode=%p mark=%p mask=%x\n",
187 __func__, group, inode, mark, mask);
188
189 /*
190 * if the event is for a child and this inode doesn't care about
191 * events on the child, don't send it!
192 */
193 if ((mask & FS_EVENT_ON_CHILD) &&
194 !(mark->mask & FS_EVENT_ON_CHILD))
195 return false;
196 else
197 return true;
198}
199
200static bool fanotify_should_send_event(struct fsnotify_group *group, 156static bool fanotify_should_send_event(struct fsnotify_group *group,
201 struct inode *to_tell, 157 struct inode *to_tell,
202 struct vfsmount *mnt,
203 struct fsnotify_mark *inode_mark, 158 struct fsnotify_mark *inode_mark,
204 struct fsnotify_mark *vfsmount_mark, 159 struct fsnotify_mark *vfsmnt_mark,
205 __u32 mask, void *data, int data_type) 160 __u32 event_mask, void *data, int data_type)
206{ 161{
207 pr_debug("%s: group=%p to_tell=%p mnt=%p mask=%x data=%p data_type=%d\n", 162 __u32 marks_mask, marks_ignored_mask;
208 __func__, group, to_tell, mnt, mask, data, data_type); 163
164 pr_debug("%s: group=%p to_tell=%p inode_mark=%p vfsmnt_mark=%p "
165 "mask=%x data=%p data_type=%d\n", __func__, group, to_tell,
166 inode_mark, vfsmnt_mark, event_mask, data, data_type);
167
168 pr_debug("%s: group=%p vfsmount_mark=%p inode_mark=%p mask=%x\n",
169 __func__, group, vfsmnt_mark, inode_mark, event_mask);
209 170
210 /* sorry, fanotify only gives a damn about files and dirs */ 171 /* sorry, fanotify only gives a damn about files and dirs */
211 if (!S_ISREG(to_tell->i_mode) && 172 if (!S_ISREG(to_tell->i_mode) &&
@@ -216,11 +177,30 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
216 if (data_type != FSNOTIFY_EVENT_FILE) 177 if (data_type != FSNOTIFY_EVENT_FILE)
217 return false; 178 return false;
218 179
219 if (mnt) 180 if (inode_mark && vfsmnt_mark) {
220 return should_send_vfsmount_event(group, mnt, to_tell, 181 marks_mask = (vfsmnt_mark->mask | inode_mark->mask);
221 vfsmount_mark, mask); 182 marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask);
222 else 183 } else if (inode_mark) {
223 return should_send_inode_event(group, to_tell, inode_mark, mask); 184 /*
185 * if the event is for a child and this inode doesn't care about
186 * events on the child, don't send it!
187 */
188 if ((event_mask & FS_EVENT_ON_CHILD) &&
189 !(inode_mark->mask & FS_EVENT_ON_CHILD))
190 return false;
191 marks_mask = inode_mark->mask;
192 marks_ignored_mask = inode_mark->ignored_mask;
193 } else if (vfsmnt_mark) {
194 marks_mask = vfsmnt_mark->mask;
195 marks_ignored_mask = vfsmnt_mark->ignored_mask;
196 } else {
197 BUG();
198 }
199
200 if (event_mask & marks_mask & ~marks_ignored_mask)
201 return true;
202
203 return false;
224} 204}
225 205
226const struct fsnotify_ops fanotify_fsnotify_ops = { 206const 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,
183 if (!inode_test_mask && !vfsmount_test_mask) 183 if (!inode_test_mask && !vfsmount_test_mask)
184 return 0; 184 return 0;
185 185
186 if (group->ops->should_send_event(group, to_tell, mnt, inode_mark, 186 if (group->ops->should_send_event(group, to_tell, inode_mark,
187 vfsmount_mark, mask, data, 187 vfsmount_mark, mask, data,
188 data_is) == false) 188 data_is) == false)
189 return 0; 189 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
142} 142}
143 143
144static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode, 144static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode,
145 struct vfsmount *mnt, struct fsnotify_mark *mark, 145 struct fsnotify_mark *inode_mark,
146 struct fsnotify_mark *vfsmount_mark, 146 struct fsnotify_mark *vfsmount_mark,
147 __u32 mask, void *data, int data_type) 147 __u32 mask, void *data, int data_type)
148{ 148{
149 if ((mark->mask & FS_EXCL_UNLINK) && 149 if ((inode_mark->mask & FS_EXCL_UNLINK) &&
150 (data_type == FSNOTIFY_EVENT_FILE)) { 150 (data_type == FSNOTIFY_EVENT_FILE)) {
151 struct file *file = data; 151 struct file *file = data;
152 152
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;
92 */ 92 */
93struct fsnotify_ops { 93struct fsnotify_ops {
94 bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode, 94 bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,
95 struct vfsmount *mnt, struct fsnotify_mark *inode_mark, 95 struct fsnotify_mark *inode_mark,
96 struct fsnotify_mark *vfsmount_mark, 96 struct fsnotify_mark *vfsmount_mark,
97 __u32 mask, void *data, int data_type); 97 __u32 mask, void *data, int data_type);
98 int (*handle_event)(struct fsnotify_group *group, 98 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
921} 921}
922 922
923static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode, 923static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode,
924 struct vfsmount *mnt, struct fsnotify_mark *inode_mark, 924 struct fsnotify_mark *inode_mark,
925 struct fsnotify_mark *vfsmount_mark, 925 struct fsnotify_mark *vfsmount_mark,
926 __u32 mask, void *data, int data_type) 926 __u32 mask, void *data, int data_type)
927{ 927{
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)
503} 503}
504 504
505static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode, 505static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode,
506 struct vfsmount *mnt, struct fsnotify_mark *inode_mark, 506 struct fsnotify_mark *inode_mark,
507 struct fsnotify_mark *vfsmount_mark, 507 struct fsnotify_mark *vfsmount_mark,
508 __u32 mask, void *data, int data_type) 508 __u32 mask, void *data, int data_type)
509{ 509{