|
@@ -229,8 +229,16 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
|
|
&fsnotify_mark_srcu);
|
|
&fsnotify_mark_srcu);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * We need to merge inode & vfsmount mark lists so that inode mark
|
|
|
|
+ * ignore masks are properly reflected for mount mark notifications.
|
|
|
|
+ * That's why this traversal is so complicated...
|
|
|
|
+ */
|
|
while (inode_node || vfsmount_node) {
|
|
while (inode_node || vfsmount_node) {
|
|
- inode_group = vfsmount_group = NULL;
|
|
|
|
|
|
+ inode_group = NULL;
|
|
|
|
+ inode_mark = NULL;
|
|
|
|
+ vfsmount_group = NULL;
|
|
|
|
+ vfsmount_mark = NULL;
|
|
|
|
|
|
if (inode_node) {
|
|
if (inode_node) {
|
|
inode_mark = hlist_entry(srcu_dereference(inode_node, &fsnotify_mark_srcu),
|
|
inode_mark = hlist_entry(srcu_dereference(inode_node, &fsnotify_mark_srcu),
|
|
@@ -244,21 +252,19 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
|
|
vfsmount_group = vfsmount_mark->group;
|
|
vfsmount_group = vfsmount_mark->group;
|
|
}
|
|
}
|
|
|
|
|
|
- if (inode_group > vfsmount_group) {
|
|
|
|
- /* handle inode */
|
|
|
|
- ret = send_to_group(to_tell, inode_mark, NULL, mask,
|
|
|
|
- data, data_is, cookie, file_name);
|
|
|
|
- /* we didn't use the vfsmount_mark */
|
|
|
|
- vfsmount_group = NULL;
|
|
|
|
- } else if (vfsmount_group > inode_group) {
|
|
|
|
- ret = send_to_group(to_tell, NULL, vfsmount_mark, mask,
|
|
|
|
- data, data_is, cookie, file_name);
|
|
|
|
- inode_group = NULL;
|
|
|
|
- } else {
|
|
|
|
- ret = send_to_group(to_tell, inode_mark, vfsmount_mark,
|
|
|
|
- mask, data, data_is, cookie,
|
|
|
|
- file_name);
|
|
|
|
|
|
+ if (inode_group && vfsmount_group) {
|
|
|
|
+ int cmp = fsnotify_compare_groups(inode_group,
|
|
|
|
+ vfsmount_group);
|
|
|
|
+ if (cmp > 0) {
|
|
|
|
+ inode_group = NULL;
|
|
|
|
+ inode_mark = NULL;
|
|
|
|
+ } else if (cmp < 0) {
|
|
|
|
+ vfsmount_group = NULL;
|
|
|
|
+ vfsmount_mark = NULL;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
|
|
|
|
+ data, data_is, cookie, file_name);
|
|
|
|
|
|
if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
|
|
if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
|
|
goto out;
|
|
goto out;
|