aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/fanotify/fanotify_user.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2014-04-03 17:46:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-03 19:20:51 -0400
commitf083441ba86acb9e2ef9c1d1747725e488c8b1ff (patch)
tree227d46ea995a81645b0a1eb9b5147397a1e0de87 /fs/notify/fanotify/fanotify_user.c
parent3298cf37bee59c66a51da0cea8bae0d0418e27fd (diff)
fanotify: use fanotify event structure for permission response processing
Currently, fanotify creates new structure to track the fact that permission event has been reported to userspace and someone is waiting for a response to it. As event structures are now completely in the hands of each notification framework, we can use the event structure for this tracking instead of allocating a new structure. Since this makes the event structures for normal events and permission events even more different and the structures have different lifetime rules, we split them into two separate structures (where permission event structure contains the structure for a normal event). This makes normal events 8 bytes smaller and the code a tad bit cleaner. [akpm@linux-foundation.org: fix build] Signed-off-by: Jan Kara <jack@suse.cz> Cc: Eric Paris <eparis@redhat.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Wu Fengguang <fengguang.wu@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/notify/fanotify/fanotify_user.c')
-rw-r--r--fs/notify/fanotify/fanotify_user.c123
1 files changed, 44 insertions, 79 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 70fe65437d21..8f5e85269110 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -28,14 +28,8 @@
28extern const struct fsnotify_ops fanotify_fsnotify_ops; 28extern const struct fsnotify_ops fanotify_fsnotify_ops;
29 29
30static struct kmem_cache *fanotify_mark_cache __read_mostly; 30static struct kmem_cache *fanotify_mark_cache __read_mostly;
31static struct kmem_cache *fanotify_response_event_cache __read_mostly;
32struct kmem_cache *fanotify_event_cachep __read_mostly; 31struct kmem_cache *fanotify_event_cachep __read_mostly;
33 32struct kmem_cache *fanotify_perm_event_cachep __read_mostly;
34struct fanotify_response_event {
35 struct list_head list;
36 __s32 fd;
37 struct fanotify_event_info *event;
38};
39 33
40/* 34/*
41 * Get an fsnotify notification event if one exists and is small 35 * Get an fsnotify notification event if one exists and is small
@@ -135,33 +129,34 @@ static int fill_event_metadata(struct fsnotify_group *group,
135} 129}
136 130
137#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 131#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
138static struct fanotify_response_event *dequeue_re(struct fsnotify_group *group, 132static struct fanotify_perm_event_info *dequeue_event(
139 __s32 fd) 133 struct fsnotify_group *group, int fd)
140{ 134{
141 struct fanotify_response_event *re, *return_re = NULL; 135 struct fanotify_perm_event_info *event, *return_e = NULL;
142 136
143 mutex_lock(&group->fanotify_data.access_mutex); 137 mutex_lock(&group->fanotify_data.access_mutex);
144 list_for_each_entry(re, &group->fanotify_data.access_list, list) { 138 list_for_each_entry(event, &group->fanotify_data.access_list,
145 if (re->fd != fd) 139 fae.fse.list) {
140 if (event->fd != fd)
146 continue; 141 continue;
147 142
148 list_del_init(&re->list); 143 list_del_init(&event->fae.fse.list);
149 return_re = re; 144 return_e = event;
150 break; 145 break;
151 } 146 }
152 mutex_unlock(&group->fanotify_data.access_mutex); 147 mutex_unlock(&group->fanotify_data.access_mutex);
153 148
154 pr_debug("%s: found return_re=%p\n", __func__, return_re); 149 pr_debug("%s: found return_re=%p\n", __func__, return_e);
155 150
156 return return_re; 151 return return_e;
157} 152}
158 153
159static int process_access_response(struct fsnotify_group *group, 154static int process_access_response(struct fsnotify_group *group,
160 struct fanotify_response *response_struct) 155 struct fanotify_response *response_struct)
161{ 156{
162 struct fanotify_response_event *re; 157 struct fanotify_perm_event_info *event;
163 __s32 fd = response_struct->fd; 158 int fd = response_struct->fd;
164 __u32 response = response_struct->response; 159 int response = response_struct->response;
165 160
166 pr_debug("%s: group=%p fd=%d response=%d\n", __func__, group, 161 pr_debug("%s: group=%p fd=%d response=%d\n", __func__, group,
167 fd, response); 162 fd, response);
@@ -181,50 +176,15 @@ static int process_access_response(struct fsnotify_group *group,
181 if (fd < 0) 176 if (fd < 0)
182 return -EINVAL; 177 return -EINVAL;
183 178
184 re = dequeue_re(group, fd); 179 event = dequeue_event(group, fd);
185 if (!re) 180 if (!event)
186 return -ENOENT; 181 return -ENOENT;
187 182
188 re->event->response = response; 183 event->response = response;
189
190 wake_up(&group->fanotify_data.access_waitq); 184 wake_up(&group->fanotify_data.access_waitq);
191 185
192 kmem_cache_free(fanotify_response_event_cache, re);
193
194 return 0;
195}
196
197static int prepare_for_access_response(struct fsnotify_group *group,
198 struct fsnotify_event *event,
199 __s32 fd)
200{
201 struct fanotify_response_event *re;
202
203 if (!(event->mask & FAN_ALL_PERM_EVENTS))
204 return 0;
205
206 re = kmem_cache_alloc(fanotify_response_event_cache, GFP_KERNEL);
207 if (!re)
208 return -ENOMEM;
209
210 re->event = FANOTIFY_E(event);
211 re->fd = fd;
212
213 mutex_lock(&group->fanotify_data.access_mutex);
214 list_add_tail(&re->list, &group->fanotify_data.access_list);
215 mutex_unlock(&group->fanotify_data.access_mutex);
216
217 return 0;
218}
219
220#else
221static int prepare_for_access_response(struct fsnotify_group *group,
222 struct fsnotify_event *event,
223 __s32 fd)
224{
225 return 0; 186 return 0;
226} 187}
227
228#endif 188#endif
229 189
230static ssize_t copy_event_to_user(struct fsnotify_group *group, 190static ssize_t copy_event_to_user(struct fsnotify_group *group,
@@ -247,9 +207,18 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
247 fanotify_event_metadata.event_len)) 207 fanotify_event_metadata.event_len))
248 goto out_close_fd; 208 goto out_close_fd;
249 209
250 ret = prepare_for_access_response(group, event, fd); 210#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
251 if (ret) 211 if (event->mask & FAN_ALL_PERM_EVENTS) {
252 goto out_close_fd; 212 struct fanotify_perm_event_info *pevent;
213
214 pevent = FANOTIFY_PE(event);
215 pevent->fd = fd;
216 mutex_lock(&group->fanotify_data.access_mutex);
217 list_add_tail(&pevent->fae.fse.list,
218 &group->fanotify_data.access_list);
219 mutex_unlock(&group->fanotify_data.access_mutex);
220 }
221#endif
253 222
254 if (fd != FAN_NOFD) 223 if (fd != FAN_NOFD)
255 fd_install(fd, f); 224 fd_install(fd, f);
@@ -263,7 +232,7 @@ out_close_fd:
263out: 232out:
264#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 233#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
265 if (event->mask & FAN_ALL_PERM_EVENTS) { 234 if (event->mask & FAN_ALL_PERM_EVENTS) {
266 FANOTIFY_E(event)->response = FAN_DENY; 235 FANOTIFY_PE(event)->response = FAN_DENY;
267 wake_up(&group->fanotify_data.access_waitq); 236 wake_up(&group->fanotify_data.access_waitq);
268 } 237 }
269#endif 238#endif
@@ -312,8 +281,8 @@ static ssize_t fanotify_read(struct file *file, char __user *buf,
312 break; 281 break;
313 ret = copy_event_to_user(group, kevent, buf); 282 ret = copy_event_to_user(group, kevent, buf);
314 /* 283 /*
315 * Permission events get destroyed after we 284 * Permission events get queued to wait for response.
316 * receive response 285 * Other events can be destroyed now.
317 */ 286 */
318 if (!(kevent->mask & FAN_ALL_PERM_EVENTS)) 287 if (!(kevent->mask & FAN_ALL_PERM_EVENTS))
319 fsnotify_destroy_event(group, kevent); 288 fsnotify_destroy_event(group, kevent);
@@ -375,20 +344,19 @@ static int fanotify_release(struct inode *ignored, struct file *file)
375 struct fsnotify_group *group = file->private_data; 344 struct fsnotify_group *group = file->private_data;
376 345
377#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 346#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
378 struct fanotify_response_event *re, *lre; 347 struct fanotify_perm_event_info *event, *next;
379 348
380 mutex_lock(&group->fanotify_data.access_mutex); 349 mutex_lock(&group->fanotify_data.access_mutex);
381 350
382 atomic_inc(&group->fanotify_data.bypass_perm); 351 atomic_inc(&group->fanotify_data.bypass_perm);
383 352
384 list_for_each_entry_safe(re, lre, &group->fanotify_data.access_list, list) { 353 list_for_each_entry_safe(event, next, &group->fanotify_data.access_list,
385 pr_debug("%s: found group=%p re=%p event=%p\n", __func__, group, 354 fae.fse.list) {
386 re, re->event); 355 pr_debug("%s: found group=%p event=%p\n", __func__, group,
387 356 event);
388 list_del_init(&re->list);
389 re->event->response = FAN_ALLOW;
390 357
391 kmem_cache_free(fanotify_response_event_cache, re); 358 list_del_init(&event->fae.fse.list);
359 event->response = FAN_ALLOW;
392 } 360 }
393 mutex_unlock(&group->fanotify_data.access_mutex); 361 mutex_unlock(&group->fanotify_data.access_mutex);
394 362
@@ -723,20 +691,15 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
723 group->fanotify_data.user = user; 691 group->fanotify_data.user = user;
724 atomic_inc(&user->fanotify_listeners); 692 atomic_inc(&user->fanotify_listeners);
725 693
726 oevent = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL); 694 oevent = fanotify_alloc_event(NULL, FS_Q_OVERFLOW, NULL);
727 if (unlikely(!oevent)) { 695 if (unlikely(!oevent)) {
728 fd = -ENOMEM; 696 fd = -ENOMEM;
729 goto out_destroy_group; 697 goto out_destroy_group;
730 } 698 }
731 group->overflow_event = &oevent->fse; 699 group->overflow_event = &oevent->fse;
732 fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW);
733 oevent->tgid = get_pid(task_tgid(current));
734 oevent->path.mnt = NULL;
735 oevent->path.dentry = NULL;
736 700
737 group->fanotify_data.f_flags = event_f_flags; 701 group->fanotify_data.f_flags = event_f_flags;
738#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 702#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
739 oevent->response = 0;
740 mutex_init(&group->fanotify_data.access_mutex); 703 mutex_init(&group->fanotify_data.access_mutex);
741 init_waitqueue_head(&group->fanotify_data.access_waitq); 704 init_waitqueue_head(&group->fanotify_data.access_waitq);
742 INIT_LIST_HEAD(&group->fanotify_data.access_list); 705 INIT_LIST_HEAD(&group->fanotify_data.access_list);
@@ -912,9 +875,11 @@ COMPAT_SYSCALL_DEFINE6(fanotify_mark,
912static int __init fanotify_user_setup(void) 875static int __init fanotify_user_setup(void)
913{ 876{
914 fanotify_mark_cache = KMEM_CACHE(fsnotify_mark, SLAB_PANIC); 877 fanotify_mark_cache = KMEM_CACHE(fsnotify_mark, SLAB_PANIC);
915 fanotify_response_event_cache = KMEM_CACHE(fanotify_response_event,
916 SLAB_PANIC);
917 fanotify_event_cachep = KMEM_CACHE(fanotify_event_info, SLAB_PANIC); 878 fanotify_event_cachep = KMEM_CACHE(fanotify_event_info, SLAB_PANIC);
879#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
880 fanotify_perm_event_cachep = KMEM_CACHE(fanotify_perm_event_info,
881 SLAB_PANIC);
882#endif
918 883
919 return 0; 884 return 0;
920} 885}