summaryrefslogtreecommitdiff
path: root/fs/notify/fsnotify.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/notify/fsnotify.c')
-rw-r--r--fs/notify/fsnotify.c47
1 files changed, 24 insertions, 23 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index c5adf833bf6a..668268627894 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -169,27 +169,22 @@ void __fsnotify_flush_ignored_mask(struct inode *inode, void *data, int data_is)
}
}
-static void send_to_group(struct fsnotify_group *group, struct inode *to_tell,
- struct vfsmount *mnt, __u32 mask, void *data,
- int data_is, u32 cookie, const unsigned char *file_name,
- struct fsnotify_event **event)
+static int send_to_group(struct fsnotify_group *group, struct inode *to_tell,
+ struct vfsmount *mnt, __u32 mask, void *data,
+ int data_is, u32 cookie, const unsigned char *file_name,
+ struct fsnotify_event **event)
{
if (!group->ops->should_send_event(group, to_tell, mnt, mask,
data, data_is))
- return;
+ return 0;
if (!*event) {
*event = fsnotify_create_event(to_tell, mask, data,
data_is, file_name,
cookie, GFP_KERNEL);
- /*
- * shit, we OOM'd and now we can't tell, maybe
- * someday someone else will want to do something
- * here
- */
if (!*event)
- return;
+ return -ENOMEM;
}
- group->ops->handle_event(group, *event);
+ return group->ops->handle_event(group, *event);
}
static bool needed_by_vfsmount(__u32 test_mask, struct vfsmount *mnt)
@@ -206,20 +201,20 @@ static bool needed_by_vfsmount(__u32 test_mask, struct vfsmount *mnt)
* out to all of the registered fsnotify_group. Those groups can then use the
* notification event in whatever means they feel necessary.
*/
-void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
- const unsigned char *file_name, u32 cookie)
+int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
+ const unsigned char *file_name, u32 cookie)
{
struct fsnotify_group *group;
struct fsnotify_event *event = NULL;
struct vfsmount *mnt = NULL;
- int idx;
+ int idx, ret = 0;
/* global tests shouldn't care about events on child only the specific event */
__u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
/* if no fsnotify listeners, nothing to do */
if (list_empty(&fsnotify_inode_groups) &&
list_empty(&fsnotify_vfsmount_groups))
- return;
+ return 0;
if (mask & FS_MODIFY)
__fsnotify_flush_ignored_mask(to_tell, data, data_is);
@@ -227,7 +222,7 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
/* if none of the directed listeners or vfsmount listeners care */
if (!(test_mask & fsnotify_inode_mask) &&
!(test_mask & fsnotify_vfsmount_mask))
- return;
+ return 0;
if (data_is == FSNOTIFY_EVENT_PATH)
mnt = ((struct path *)data)->mnt;
@@ -236,7 +231,7 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
* listeners list cares, nothing to do */
if (!(test_mask & to_tell->i_fsnotify_mask) &&
!needed_by_vfsmount(test_mask, mnt))
- return;
+ return 0;
/*
* SRCU!! the groups list is very very much read only and the path is
@@ -248,20 +243,24 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
if (test_mask & to_tell->i_fsnotify_mask) {
list_for_each_entry_rcu(group, &fsnotify_inode_groups, inode_group_list) {
if (test_mask & group->mask) {
- send_to_group(group, to_tell, NULL, mask, data, data_is,
- cookie, file_name, &event);
+ ret = send_to_group(group, to_tell, NULL, mask, data, data_is,
+ cookie, file_name, &event);
+ if (ret)
+ goto out;
}
}
}
if (needed_by_vfsmount(test_mask, mnt)) {
list_for_each_entry_rcu(group, &fsnotify_vfsmount_groups, vfsmount_group_list) {
if (test_mask & group->mask) {
- send_to_group(group, to_tell, mnt, mask, data, data_is,
- cookie, file_name, &event);
+ ret = send_to_group(group, to_tell, mnt, mask, data, data_is,
+ cookie, file_name, &event);
+ if (ret)
+ goto out;
}
}
}
-
+out:
srcu_read_unlock(&fsnotify_grp_srcu, idx);
/*
* fsnotify_create_event() took a reference so the event can't be cleaned
@@ -269,6 +268,8 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
*/
if (event)
fsnotify_put_event(event);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(fsnotify);