diff options
| -rw-r--r-- | fs/notify/fanotify/fanotify.c | 9 | ||||
| -rw-r--r-- | fs/notify/inotify/inotify_fsnotify.c | 8 | ||||
| -rw-r--r-- | fs/notify/notification.c | 3 | ||||
| -rw-r--r-- | include/linux/fsnotify_backend.h | 6 |
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 */ | ||
| 335 | static 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 */ |
| 335 | extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group); | 341 | extern 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 */ |
