aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/notify/fanotify/fanotify.c9
-rw-r--r--fs/notify/inotify/inotify_fsnotify.c8
-rw-r--r--fs/notify/notification.c3
-rw-r--r--include/linux/fsnotify_backend.h6
4 files changed, 23 insertions, 3 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 928f2a5eedb7..d51e1bb781cf 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -221,8 +221,15 @@ static int fanotify_handle_event(struct fsnotify_group *group,
221 221
222 event = fanotify_alloc_event(group, inode, mask, data); 222 event = fanotify_alloc_event(group, inode, mask, data);
223 ret = -ENOMEM; 223 ret = -ENOMEM;
224 if (unlikely(!event)) 224 if (unlikely(!event)) {
225 /*
226 * We don't queue overflow events for permission events as
227 * there the access is denied and so no event is in fact lost.
228 */
229 if (!fanotify_is_perm_event(mask))
230 fsnotify_queue_overflow(group);
225 goto finish; 231 goto finish;
232 }
226 233
227 fsn_event = &event->fse; 234 fsn_event = &event->fse;
228 ret = fsnotify_add_event(group, fsn_event, fanotify_merge); 235 ret = fsnotify_add_event(group, fsn_event, fanotify_merge);
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index 8b73332735ba..40dedb37a1f3 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -99,8 +99,14 @@ int inotify_handle_event(struct fsnotify_group *group,
99 fsn_mark); 99 fsn_mark);
100 100
101 event = kmalloc(alloc_len, GFP_KERNEL); 101 event = kmalloc(alloc_len, GFP_KERNEL);
102 if (unlikely(!event)) 102 if (unlikely(!event)) {
103 /*
104 * Treat lost event due to ENOMEM the same way as queue
105 * overflow to let userspace know event was lost.
106 */
107 fsnotify_queue_overflow(group);
103 return -ENOMEM; 108 return -ENOMEM;
109 }
104 110
105 fsn_event = &event->fse; 111 fsn_event = &event->fse;
106 fsnotify_init_event(fsn_event, inode, mask); 112 fsnotify_init_event(fsn_event, inode, mask);
diff --git a/fs/notify/notification.c b/fs/notify/notification.c
index 66f85c651c52..3c3e36745f59 100644
--- a/fs/notify/notification.c
+++ b/fs/notify/notification.c
@@ -111,7 +111,8 @@ int fsnotify_add_event(struct fsnotify_group *group,
111 return 2; 111 return 2;
112 } 112 }
113 113
114 if (group->q_len >= group->max_events) { 114 if (event == group->overflow_event ||
115 group->q_len >= group->max_events) {
115 ret = 2; 116 ret = 2;
116 /* Queue overflow event only if it isn't already queued */ 117 /* Queue overflow event only if it isn't already queued */
117 if (!list_empty(&group->overflow_event->list)) { 118 if (!list_empty(&group->overflow_event->list)) {
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 067d52e95f02..9f1edb92c97e 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -331,6 +331,12 @@ extern int fsnotify_add_event(struct fsnotify_group *group,
331 struct fsnotify_event *event, 331 struct fsnotify_event *event,
332 int (*merge)(struct list_head *, 332 int (*merge)(struct list_head *,
333 struct fsnotify_event *)); 333 struct fsnotify_event *));
334/* Queue overflow event to a notification group */
335static inline void fsnotify_queue_overflow(struct fsnotify_group *group)
336{
337 fsnotify_add_event(group, group->overflow_event, NULL);
338}
339
334/* true if the group notification queue is empty */ 340/* true if the group notification queue is empty */
335extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group); 341extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group);
336/* return, but do not dequeue the first event on the notification queue */ 342/* return, but do not dequeue the first event on the notification queue */