diff options
author | Eric Paris <eparis@redhat.com> | 2009-05-21 17:01:37 -0400 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2009-06-11 14:57:53 -0400 |
commit | a2d8bc6cb4a3024661baf877242f123787d0c054 (patch) | |
tree | 4ff3f93877a8992d5383c14fb6012ab9b1954660 /include | |
parent | 3c5119c05d624f95f4967d16b38c9624b816bdb9 (diff) |
fsnotify: generic notification queue and waitq
inotify needs to do asyc notification in which event information is stored
on a queue until the listener is ready to receive it. This patch
implements a generic notification queue for inotify (and later fanotify) to
store events to be sent at a later time.
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')
-rw-r--r-- | include/linux/fsnotify_backend.h | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 9ea800e840f1..15f8f82a5c57 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
@@ -119,6 +119,13 @@ struct fsnotify_group { | |||
119 | 119 | ||
120 | const struct fsnotify_ops *ops; /* how this group handles things */ | 120 | const struct fsnotify_ops *ops; /* how this group handles things */ |
121 | 121 | ||
122 | /* needed to send notification to userspace */ | ||
123 | struct mutex notification_mutex; /* protect the notification_list */ | ||
124 | struct list_head notification_list; /* list of event_holder this group needs to send to userspace */ | ||
125 | wait_queue_head_t notification_waitq; /* read() on the notification file blocks on this waitq */ | ||
126 | unsigned int q_len; /* events on the queue */ | ||
127 | unsigned int max_events; /* maximum events allowed on the list */ | ||
128 | |||
122 | /* stores all fastapth entries assoc with this group so they can be cleaned on unregister */ | 129 | /* stores all fastapth entries assoc with this group so they can be cleaned on unregister */ |
123 | spinlock_t mark_lock; /* protect mark_entries list */ | 130 | spinlock_t mark_lock; /* protect mark_entries list */ |
124 | atomic_t num_marks; /* 1 for each mark entry and 1 for not being | 131 | atomic_t num_marks; /* 1 for each mark entry and 1 for not being |
@@ -136,11 +143,32 @@ struct fsnotify_group { | |||
136 | }; | 143 | }; |
137 | 144 | ||
138 | /* | 145 | /* |
146 | * A single event can be queued in multiple group->notification_lists. | ||
147 | * | ||
148 | * each group->notification_list will point to an event_holder which in turns points | ||
149 | * to the actual event that needs to be sent to userspace. | ||
150 | * | ||
151 | * Seemed cheaper to create a refcnt'd event and a small holder for every group | ||
152 | * than create a different event for every group | ||
153 | * | ||
154 | */ | ||
155 | struct fsnotify_event_holder { | ||
156 | struct fsnotify_event *event; | ||
157 | struct list_head event_list; | ||
158 | }; | ||
159 | |||
160 | /* | ||
139 | * all of the information about the original object we want to now send to | 161 | * all of the information about the original object we want to now send to |
140 | * a group. If you want to carry more info from the accessing task to the | 162 | * a group. If you want to carry more info from the accessing task to the |
141 | * listener this structure is where you need to be adding fields. | 163 | * listener this structure is where you need to be adding fields. |
142 | */ | 164 | */ |
143 | struct fsnotify_event { | 165 | struct fsnotify_event { |
166 | /* | ||
167 | * If we create an event we are also likely going to need a holder | ||
168 | * to link to a group. So embed one holder in the event. Means only | ||
169 | * one allocation for the common case where we only have one group | ||
170 | */ | ||
171 | struct fsnotify_event_holder holder; | ||
144 | spinlock_t lock; /* protection for the associated event_holder and private_list */ | 172 | spinlock_t lock; /* protection for the associated event_holder and private_list */ |
145 | /* to_tell may ONLY be dereferenced during handle_event(). */ | 173 | /* to_tell may ONLY be dereferenced during handle_event(). */ |
146 | struct inode *to_tell; /* either the inode the event happened to or its parent */ | 174 | struct inode *to_tell; /* either the inode the event happened to or its parent */ |
@@ -264,6 +292,15 @@ extern void fsnotify_put_event(struct fsnotify_event *event); | |||
264 | extern struct fsnotify_event_private_data *fsnotify_get_priv_from_event(struct fsnotify_group *group, | 292 | extern struct fsnotify_event_private_data *fsnotify_get_priv_from_event(struct fsnotify_group *group, |
265 | struct fsnotify_event *event); | 293 | struct fsnotify_event *event); |
266 | 294 | ||
295 | /* attach the event to the group notification queue */ | ||
296 | extern int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_event *event); | ||
297 | /* true if the group notification queue is empty */ | ||
298 | extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group); | ||
299 | /* return, but do not dequeue the first event on the notification queue */ | ||
300 | extern struct fsnotify_event *fsnotify_peek_notify_event(struct fsnotify_group *group); | ||
301 | /* reutnr AND dequeue the first event on the notification queue */ | ||
302 | extern struct fsnotify_event *fsnotify_remove_notify_event(struct fsnotify_group *group); | ||
303 | |||
267 | /* functions used to manipulate the marks attached to inodes */ | 304 | /* functions used to manipulate the marks attached to inodes */ |
268 | 305 | ||
269 | /* run all marks associated with an inode and update inode->i_fsnotify_mask */ | 306 | /* run all marks associated with an inode and update inode->i_fsnotify_mask */ |