aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/linux/fs.h5
-rw-r--r--include/linux/fsnotify.h9
-rw-r--r--include/linux/fsnotify_backend.h65
3 files changed, 78 insertions, 1 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 83d6b4397245..275b0860044c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -755,6 +755,11 @@ struct inode {
755 755
756 __u32 i_generation; 756 __u32 i_generation;
757 757
758#ifdef CONFIG_FSNOTIFY
759 __u32 i_fsnotify_mask; /* all events this inode cares about */
760 struct hlist_head i_fsnotify_mark_entries; /* fsnotify mark entries */
761#endif
762
758#ifdef CONFIG_DNOTIFY 763#ifdef CONFIG_DNOTIFY
759 unsigned long i_dnotify_mask; /* Directory notify events */ 764 unsigned long i_dnotify_mask; /* Directory notify events */
760 struct dnotify_struct *i_dnotify; /* for directory notifications */ 765 struct dnotify_struct *i_dnotify; /* for directory notifications */
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 6c9ebefdac8e..3856eb6e5973 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -100,6 +100,14 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
100} 100}
101 101
102/* 102/*
103 * fsnotify_inode_delete - and inode is being evicted from cache, clean up is needed
104 */
105static inline void fsnotify_inode_delete(struct inode *inode)
106{
107 __fsnotify_inode_delete(inode);
108}
109
110/*
103 * fsnotify_nameremove - a filename was removed from a directory 111 * fsnotify_nameremove - a filename was removed from a directory
104 */ 112 */
105static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) 113static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
@@ -121,6 +129,7 @@ static inline void fsnotify_inoderemove(struct inode *inode)
121 inotify_inode_is_dead(inode); 129 inotify_inode_is_dead(inode);
122 130
123 fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE); 131 fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE);
132 __fsnotify_inode_delete(inode);
124} 133}
125 134
126/* 135/*
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 1a55718b38aa..cad5c4d75c1d 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -48,17 +48,25 @@
48 48
49struct fsnotify_group; 49struct fsnotify_group;
50struct fsnotify_event; 50struct fsnotify_event;
51struct fsnotify_mark_entry;
51 52
52/* 53/*
53 * Each group much define these ops. The fsnotify infrastructure will call 54 * Each group much define these ops. The fsnotify infrastructure will call
54 * these operations for each relevant group. 55 * these operations for each relevant group.
55 * 56 *
57 * should_send_event - given a group, inode, and mask this function determines
58 * if the group is interested in this event.
56 * handle_event - main call for a group to handle an fs event 59 * handle_event - main call for a group to handle an fs event
57 * free_group_priv - called when a group refcnt hits 0 to clean up the private union 60 * free_group_priv - called when a group refcnt hits 0 to clean up the private union
61 * freeing-mark - this means that a mark has been flagged to die when everything
62 * finishes using it. The function is supplied with what must be a
63 * valid group and inode to use to clean up.
58 */ 64 */
59struct fsnotify_ops { 65struct fsnotify_ops {
66 bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode, __u32 mask);
60 int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event); 67 int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event);
61 void (*free_group_priv)(struct fsnotify_group *group); 68 void (*free_group_priv)(struct fsnotify_group *group);
69 void (*freeing_mark)(struct fsnotify_mark_entry *entry, struct fsnotify_group *group);
62}; 70};
63 71
64/* 72/*
@@ -97,7 +105,14 @@ struct fsnotify_group {
97 105
98 const struct fsnotify_ops *ops; /* how this group handles things */ 106 const struct fsnotify_ops *ops; /* how this group handles things */
99 107
100 /* prevents double list_del of group_list. protected by global fsnotify_gr_mutex */ 108 /* stores all fastapth entries assoc with this group so they can be cleaned on unregister */
109 spinlock_t mark_lock; /* protect mark_entries list */
110 atomic_t num_marks; /* 1 for each mark entry and 1 for not being
111 * past the point of no return when freeing
112 * a group */
113 struct list_head mark_entries; /* all inode mark entries for this group */
114
115 /* prevents double list_del of group_list. protected by global fsnotify_grp_mutex */
101 bool on_group_list; 116 bool on_group_list;
102 117
103 /* groups can define private fields here or use the void *private */ 118 /* groups can define private fields here or use the void *private */
@@ -137,12 +152,38 @@ struct fsnotify_event {
137 __u32 mask; /* the type of access, bitwise OR for FS_* event types */ 152 __u32 mask; /* the type of access, bitwise OR for FS_* event types */
138}; 153};
139 154
155/*
156 * a mark is simply an entry attached to an in core inode which allows an
157 * fsnotify listener to indicate they are either no longer interested in events
158 * of a type matching mask or only interested in those events.
159 *
160 * these are flushed when an inode is evicted from core and may be flushed
161 * when the inode is modified (as seen by fsnotify_access). Some fsnotify users
162 * (such as dnotify) will flush these when the open fd is closed and not at
163 * inode eviction or modification.
164 */
165struct fsnotify_mark_entry {
166 __u32 mask; /* mask this mark entry is for */
167 /* we hold ref for each i_list and g_list. also one ref for each 'thing'
168 * in kernel that found and may be using this mark. */
169 atomic_t refcnt; /* active things looking at this mark */
170 struct inode *inode; /* inode this entry is associated with */
171 struct fsnotify_group *group; /* group this mark entry is for */
172 struct hlist_node i_list; /* list of mark_entries by inode->i_fsnotify_mark_entries */
173 struct list_head g_list; /* list of mark_entries by group->i_fsnotify_mark_entries */
174 spinlock_t lock; /* protect group, inode, and killme */
175 struct list_head free_i_list; /* tmp list used when freeing this mark */
176 struct list_head free_g_list; /* tmp list used when freeing this mark */
177 void (*free_mark)(struct fsnotify_mark_entry *entry); /* called on final put+free */
178};
179
140#ifdef CONFIG_FSNOTIFY 180#ifdef CONFIG_FSNOTIFY
141 181
142/* called from the vfs helpers */ 182/* called from the vfs helpers */
143 183
144/* main fsnotify call to send events */ 184/* main fsnotify call to send events */
145extern void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is); 185extern void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is);
186extern void __fsnotify_inode_delete(struct inode *inode);
146 187
147 188
148/* called from fsnotify listeners, such as fanotify or dnotify */ 189/* called from fsnotify listeners, such as fanotify or dnotify */
@@ -153,6 +194,8 @@ extern void fsnotify_recalc_global_mask(void);
153extern struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, 194extern struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num,
154 __u32 mask, 195 __u32 mask,
155 const struct fsnotify_ops *ops); 196 const struct fsnotify_ops *ops);
197/* run all marks associated with this group and update group->mask */
198extern void fsnotify_recalc_group_mask(struct fsnotify_group *group);
156/* drop reference on a group from fsnotify_obtain_group */ 199/* drop reference on a group from fsnotify_obtain_group */
157extern void fsnotify_put_group(struct fsnotify_group *group); 200extern void fsnotify_put_group(struct fsnotify_group *group);
158 201
@@ -163,6 +206,22 @@ extern void fsnotify_put_event(struct fsnotify_event *event);
163extern struct fsnotify_event_private_data *fsnotify_get_priv_from_event(struct fsnotify_group *group, 206extern struct fsnotify_event_private_data *fsnotify_get_priv_from_event(struct fsnotify_group *group,
164 struct fsnotify_event *event); 207 struct fsnotify_event *event);
165 208
209/* functions used to manipulate the marks attached to inodes */
210
211/* run all marks associated with an inode and update inode->i_fsnotify_mask */
212extern void fsnotify_recalc_inode_mask(struct inode *inode);
213extern void fsnotify_init_mark(struct fsnotify_mark_entry *entry, void (*free_mark)(struct fsnotify_mark_entry *entry));
214/* find (and take a reference) to a mark associated with group and inode */
215extern struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_group *group, struct inode *inode);
216/* attach the mark to both the group and the inode */
217extern int fsnotify_add_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group, struct inode *inode);
218/* given a mark, flag it to be freed when all references are dropped */
219extern void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry);
220/* run all the marks in a group, and flag them to be freed */
221extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group);
222extern void fsnotify_get_mark(struct fsnotify_mark_entry *entry);
223extern void fsnotify_put_mark(struct fsnotify_mark_entry *entry);
224
166/* put here because inotify does some weird stuff when destroying watches */ 225/* put here because inotify does some weird stuff when destroying watches */
167extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, 226extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
168 void *data, int data_is); 227 void *data, int data_is);
@@ -170,6 +229,10 @@ extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32
170 229
171static inline void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is) 230static inline void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is)
172{} 231{}
232
233static inline void __fsnotify_inode_delete(struct inode *inode)
234{}
235
173#endif /* CONFIG_FSNOTIFY */ 236#endif /* CONFIG_FSNOTIFY */
174 237
175#endif /* __KERNEL __ */ 238#endif /* __KERNEL __ */