aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/fsnotify_backend.h
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-05-21 17:01:26 -0400
committerEric Paris <eparis@redhat.com>2009-06-11 14:57:53 -0400
commit3be25f49b9d6a97eae9bcb96d3292072b7658bd8 (patch)
tree36f7d96481a47a6bde3c2f961346e940698111e0 /include/linux/fsnotify_backend.h
parent90586523eb4b349806887c62ee70685a49415124 (diff)
fsnotify: add marks to inodes so groups can interpret how to handle those inodes
This patch creates a way for fsnotify groups to attach marks to inodes. These marks have little meaning to the generic fsnotify infrastructure and thus their meaning should be interpreted by the group that attached them to the inode's list. dnotify and inotify will make use of these markings to indicate which inodes are of interest to their respective groups. But this implementation has the useful property that in the future other listeners could actually use the marks for the exact opposite reason, aka to indicate which inodes it had NO interest in. Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'include/linux/fsnotify_backend.h')
-rw-r--r--include/linux/fsnotify_backend.h65
1 files changed, 64 insertions, 1 deletions
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 __ */