190586523SEric Paris /* 290586523SEric Paris * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com> 390586523SEric Paris * 490586523SEric Paris * This program is free software; you can redistribute it and/or modify 590586523SEric Paris * it under the terms of the GNU General Public License as published by 690586523SEric Paris * the Free Software Foundation; either version 2, or (at your option) 790586523SEric Paris * any later version. 890586523SEric Paris * 990586523SEric Paris * This program is distributed in the hope that it will be useful, 1090586523SEric Paris * but WITHOUT ANY WARRANTY; without even the implied warranty of 1190586523SEric Paris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1290586523SEric Paris * GNU General Public License for more details. 1390586523SEric Paris * 1490586523SEric Paris * You should have received a copy of the GNU General Public License 1590586523SEric Paris * along with this program; see the file COPYING. If not, write to 1690586523SEric Paris * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 1790586523SEric Paris */ 1890586523SEric Paris 1990586523SEric Paris #include <linux/dcache.h> 2090586523SEric Paris #include <linux/fs.h> 2190586523SEric Paris #include <linux/init.h> 2290586523SEric Paris #include <linux/module.h> 2390586523SEric Paris #include <linux/srcu.h> 2490586523SEric Paris 2590586523SEric Paris #include <linux/fsnotify_backend.h> 2690586523SEric Paris #include "fsnotify.h" 2790586523SEric Paris 2890586523SEric Paris /* 2990586523SEric Paris * This is the main call to fsnotify. The VFS calls into hook specific functions 3090586523SEric Paris * in linux/fsnotify.h. Those functions then in turn call here. Here will call 3190586523SEric Paris * out to all of the registered fsnotify_group. Those groups can then use the 3290586523SEric Paris * notification event in whatever means they feel necessary. 3390586523SEric Paris */ 3490586523SEric Paris void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is) 3590586523SEric Paris { 3690586523SEric Paris struct fsnotify_group *group; 3790586523SEric Paris struct fsnotify_event *event = NULL; 3890586523SEric Paris int idx; 3990586523SEric Paris 4090586523SEric Paris if (list_empty(&fsnotify_groups)) 4190586523SEric Paris return; 4290586523SEric Paris 4390586523SEric Paris if (!(mask & fsnotify_mask)) 4490586523SEric Paris return; 4590586523SEric Paris 4690586523SEric Paris /* 4790586523SEric Paris * SRCU!! the groups list is very very much read only and the path is 4890586523SEric Paris * very hot. The VAST majority of events are not going to need to do 4990586523SEric Paris * anything other than walk the list so it's crazy to pre-allocate. 5090586523SEric Paris */ 5190586523SEric Paris idx = srcu_read_lock(&fsnotify_grp_srcu); 5290586523SEric Paris list_for_each_entry_rcu(group, &fsnotify_groups, group_list) { 5390586523SEric Paris if (mask & group->mask) { 5490586523SEric Paris if (!event) { 5590586523SEric Paris event = fsnotify_create_event(to_tell, mask, data, data_is); 5690586523SEric Paris /* shit, we OOM'd and now we can't tell, maybe 5790586523SEric Paris * someday someone else will want to do something 5890586523SEric Paris * here */ 5990586523SEric Paris if (!event) 6090586523SEric Paris break; 6190586523SEric Paris } 6290586523SEric Paris group->ops->handle_event(group, event); 6390586523SEric Paris } 6490586523SEric Paris } 6590586523SEric Paris srcu_read_unlock(&fsnotify_grp_srcu, idx); 6690586523SEric Paris /* 6790586523SEric Paris * fsnotify_create_event() took a reference so the event can't be cleaned 6890586523SEric Paris * up while we are still trying to add it to lists, drop that one. 6990586523SEric Paris */ 7090586523SEric Paris if (event) 7190586523SEric Paris fsnotify_put_event(event); 7290586523SEric Paris } 7390586523SEric Paris EXPORT_SYMBOL_GPL(fsnotify); 7490586523SEric Paris 7590586523SEric Paris static __init int fsnotify_init(void) 7690586523SEric Paris { 7790586523SEric Paris return init_srcu_struct(&fsnotify_grp_srcu); 7890586523SEric Paris } 7990586523SEric Paris subsys_initcall(fsnotify_init); 80