0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #include <linux/fs.h>
0022 #include <linux/init.h>
0023 #include <linux/kernel.h>
0024 #include <linux/list.h>
0025 #include <linux/module.h>
0026 #include <linux/mount.h>
0027 #include <linux/mutex.h>
0028 #include <linux/namei.h>
0029 #include <linux/path.h>
0030 #include <linux/slab.h>
0031 #include <linux/spinlock.h>
0032
0033 #include <linux/atomic.h>
0034
0035 #include <linux/fsnotify_backend.h>
0036 #include "fsnotify.h"
0037
0038 static atomic_t fsnotify_sync_cookie = ATOMIC_INIT(0);
0039
0040
0041
0042
0043
0044 u32 fsnotify_get_cookie(void)
0045 {
0046 return atomic_inc_return(&fsnotify_sync_cookie);
0047 }
0048 EXPORT_SYMBOL_GPL(fsnotify_get_cookie);
0049
0050 void fsnotify_destroy_event(struct fsnotify_group *group,
0051 struct fsnotify_event *event)
0052 {
0053
0054 if (!event || event == group->overflow_event)
0055 return;
0056
0057
0058
0059
0060
0061
0062 if (!list_empty(&event->list)) {
0063 spin_lock(&group->notification_lock);
0064 WARN_ON(!list_empty(&event->list));
0065 spin_unlock(&group->notification_lock);
0066 }
0067 group->ops->free_event(group, event);
0068 }
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 int fsnotify_insert_event(struct fsnotify_group *group,
0082 struct fsnotify_event *event,
0083 int (*merge)(struct fsnotify_group *,
0084 struct fsnotify_event *),
0085 void (*insert)(struct fsnotify_group *,
0086 struct fsnotify_event *))
0087 {
0088 int ret = 0;
0089 struct list_head *list = &group->notification_list;
0090
0091 pr_debug("%s: group=%p event=%p\n", __func__, group, event);
0092
0093 spin_lock(&group->notification_lock);
0094
0095 if (group->shutdown) {
0096 spin_unlock(&group->notification_lock);
0097 return 2;
0098 }
0099
0100 if (event == group->overflow_event ||
0101 group->q_len >= group->max_events) {
0102 ret = 2;
0103
0104 if (!list_empty(&group->overflow_event->list)) {
0105 spin_unlock(&group->notification_lock);
0106 return ret;
0107 }
0108 event = group->overflow_event;
0109 goto queue;
0110 }
0111
0112 if (!list_empty(list) && merge) {
0113 ret = merge(group, event);
0114 if (ret) {
0115 spin_unlock(&group->notification_lock);
0116 return ret;
0117 }
0118 }
0119
0120 queue:
0121 group->q_len++;
0122 list_add_tail(&event->list, list);
0123 if (insert)
0124 insert(group, event);
0125 spin_unlock(&group->notification_lock);
0126
0127 wake_up(&group->notification_waitq);
0128 kill_fasync(&group->fsn_fa, SIGIO, POLL_IN);
0129 return ret;
0130 }
0131
0132 void fsnotify_remove_queued_event(struct fsnotify_group *group,
0133 struct fsnotify_event *event)
0134 {
0135 assert_spin_locked(&group->notification_lock);
0136
0137
0138
0139
0140 list_del_init(&event->list);
0141 group->q_len--;
0142 }
0143
0144
0145
0146
0147
0148 struct fsnotify_event *fsnotify_peek_first_event(struct fsnotify_group *group)
0149 {
0150 assert_spin_locked(&group->notification_lock);
0151
0152 if (fsnotify_notify_queue_is_empty(group))
0153 return NULL;
0154
0155 return list_first_entry(&group->notification_list,
0156 struct fsnotify_event, list);
0157 }
0158
0159
0160
0161
0162
0163 struct fsnotify_event *fsnotify_remove_first_event(struct fsnotify_group *group)
0164 {
0165 struct fsnotify_event *event = fsnotify_peek_first_event(group);
0166
0167 if (!event)
0168 return NULL;
0169
0170 pr_debug("%s: group=%p event=%p\n", __func__, group, event);
0171
0172 fsnotify_remove_queued_event(group, event);
0173
0174 return event;
0175 }
0176
0177
0178
0179
0180
0181 void fsnotify_flush_notify(struct fsnotify_group *group)
0182 {
0183 struct fsnotify_event *event;
0184
0185 spin_lock(&group->notification_lock);
0186 while (!fsnotify_notify_queue_is_empty(group)) {
0187 event = fsnotify_remove_first_event(group);
0188 spin_unlock(&group->notification_lock);
0189 fsnotify_destroy_event(group, event);
0190 spin_lock(&group->notification_lock);
0191 }
0192 spin_unlock(&group->notification_lock);
0193 }