diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/fs.h | 5 | ||||
-rw-r--r-- | include/linux/fsnotify.h | 9 | ||||
-rw-r--r-- | include/linux/fsnotify_backend.h | 65 |
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 | */ | ||
105 | static 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 | */ |
105 | static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) | 113 | static 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 | ||
49 | struct fsnotify_group; | 49 | struct fsnotify_group; |
50 | struct fsnotify_event; | 50 | struct fsnotify_event; |
51 | struct 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 | */ |
59 | struct fsnotify_ops { | 65 | struct 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 | */ | ||
165 | struct 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 */ |
145 | extern void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is); | 185 | extern void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is); |
186 | extern 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); | |||
153 | extern struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, | 194 | extern 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 */ | ||
198 | extern 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 */ |
157 | extern void fsnotify_put_group(struct fsnotify_group *group); | 200 | extern void fsnotify_put_group(struct fsnotify_group *group); |
158 | 201 | ||
@@ -163,6 +206,22 @@ extern void fsnotify_put_event(struct fsnotify_event *event); | |||
163 | extern struct fsnotify_event_private_data *fsnotify_get_priv_from_event(struct fsnotify_group *group, | 206 | extern 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 */ | ||
212 | extern void fsnotify_recalc_inode_mask(struct inode *inode); | ||
213 | extern 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 */ | ||
215 | extern 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 */ | ||
217 | extern 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 */ | ||
219 | extern 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 */ | ||
221 | extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group); | ||
222 | extern void fsnotify_get_mark(struct fsnotify_mark_entry *entry); | ||
223 | extern 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 */ |
167 | extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, | 226 | extern 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 | ||
171 | static inline void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is) | 230 | static inline void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is) |
172 | {} | 231 | {} |
232 | |||
233 | static 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 __ */ |