summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-10-28 23:21:56 +0200
committerEric Paris <eparis@redhat.com>2010-10-28 23:22:13 +0200
commitff8bcbd03da881bf1171910c6c07d44bd3c0a234 (patch)
treeec7ad24bf2923bc19c48f1160a05328299193a8d
parentfanotify: use __aligned_u64 in fanotify userspace metadata (diff)
downloadlinux-ff8bcbd03da881bf1171910c6c07d44bd3c0a234.tar.xz
linux-ff8bcbd03da881bf1171910c6c07d44bd3c0a234.zip
fsnotify: correctly handle return codes from listeners
When fsnotify groups return errors they are ignored. For permissions events these should be passed back up the stack, but for most events these should continue to be ignored. Signed-off-by: Eric Paris <eparis@redhat.com>
-rw-r--r--fs/notify/fsnotify.c20
-rw-r--r--include/linux/fsnotify_backend.h2
2 files changed, 14 insertions, 8 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 4498a208df94..57ecadd85abf 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -252,20 +252,23 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
if (inode_group > vfsmount_group) {
/* handle inode */
- send_to_group(to_tell, NULL, inode_mark, NULL, mask, data,
- data_is, cookie, file_name, &event);
+ ret = send_to_group(to_tell, NULL, inode_mark, NULL, mask, data,
+ data_is, cookie, file_name, &event);
/* we didn't use the vfsmount_mark */
vfsmount_group = NULL;
} else if (vfsmount_group > inode_group) {
- send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data,
- data_is, cookie, file_name, &event);
+ ret = send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data,
+ data_is, cookie, file_name, &event);
inode_group = NULL;
} else {
- send_to_group(to_tell, mnt, inode_mark, vfsmount_mark,
- mask, data, data_is, cookie, file_name,
- &event);
+ ret = send_to_group(to_tell, mnt, inode_mark, vfsmount_mark,
+ mask, data, data_is, cookie, file_name,
+ &event);
}
+ if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
+ goto out;
+
if (inode_group)
inode_node = srcu_dereference(inode_node->next,
&fsnotify_mark_srcu);
@@ -273,7 +276,8 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
vfsmount_node = srcu_dereference(vfsmount_node->next,
&fsnotify_mark_srcu);
}
-
+ ret = 0;
+out:
srcu_read_unlock(&fsnotify_mark_srcu, idx);
/*
* fsnotify_create_event() took a reference so the event can't be cleaned
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 825329534162..026892187c83 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -64,6 +64,8 @@
#define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO)
+#define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM)
+
#define ALL_FSNOTIFY_EVENTS (FS_ACCESS | FS_MODIFY | FS_ATTRIB | \
FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN | \
FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE | \