aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-20 23:11:52 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-20 23:11:52 -0500
commit96680d2b9174668100824d763382240c71baa811 (patch)
treeec84c2347df47913cc98e3cfc1d43f427d51fa1f /include
parent4c9a44aebeaef35570a67aed17b72a2cf8d0b219 (diff)
parent1ca39ab9d21ac93f94b9e3eb364ea9a5cf2aba06 (diff)
Merge branch 'for-next' of git://git.infradead.org/users/eparis/notify
Pull filesystem notification updates from Eric Paris: "This pull mostly is about locking changes in the fsnotify system. By switching the group lock from a spin_lock() to a mutex() we can now hold the lock across things like iput(). This fixes a problem involving unmounting a fs and having inodes be busy, first pointed out by FAT, but reproducible with tmpfs. This also restores signal driven I/O for inotify, which has been broken since about 2.6.32." Ugh. I *hate* the timing of this. It was rebased after the merge window opened, and then left to sit with the pull request coming the day before the merge window closes. That's just crap. But apparently the patches themselves have been around for over a year, just gathering dust, so now it's suddenly critical. Fixed up semantic conflict in fs/notify/fdinfo.c as per Stephen Rothwell's fixes from -next. * 'for-next' of git://git.infradead.org/users/eparis/notify: inotify: automatically restart syscalls inotify: dont skip removal of watch descriptor if creation of ignored event failed fanotify: dont merge permission events fsnotify: make fasync generic for both inotify and fanotify fsnotify: change locking order fsnotify: dont put marks on temporary list when clearing marks by group fsnotify: introduce locked versions of fsnotify_add_mark() and fsnotify_remove_mark() fsnotify: pass group to fsnotify_destroy_mark() fsnotify: use a mutex instead of a spinlock to protect a groups mark list fanotify: add an extra flag to mark_remove_from_mask that indicates wheather a mark should be destroyed fsnotify: take groups mark_lock before mark lock fsnotify: use reference counting for groups fsnotify: introduce fsnotify_get_group() inotify, fanotify: replace fsnotify_put_group() with fsnotify_destroy_group()
Diffstat (limited to 'include')
-rw-r--r--include/linux/fsnotify_backend.h31
1 files changed, 21 insertions, 10 deletions
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 63d966d5c2ea..d5b0910d4961 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -88,9 +88,10 @@ struct fsnotify_event_private_data;
88 * if the group is interested in this event. 88 * if the group is interested in this event.
89 * handle_event - main call for a group to handle an fs event 89 * handle_event - main call for a group to handle an fs event
90 * free_group_priv - called when a group refcnt hits 0 to clean up the private union 90 * free_group_priv - called when a group refcnt hits 0 to clean up the private union
91 * freeing-mark - this means that a mark has been flagged to die when everything 91 * freeing_mark - called when a mark is being destroyed for some reason. The group
92 * finishes using it. The function is supplied with what must be a 92 * MUST be holding a reference on each mark and that reference must be
93 * valid group and inode to use to clean up. 93 * dropped in this function. inotify uses this function to send
94 * userspace messages that marks have been removed.
94 */ 95 */
95struct fsnotify_ops { 96struct fsnotify_ops {
96 bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode, 97 bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,
@@ -141,12 +142,14 @@ struct fsnotify_group {
141 unsigned int priority; 142 unsigned int priority;
142 143
143 /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */ 144 /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */
144 spinlock_t mark_lock; /* protect marks_list */ 145 struct mutex mark_mutex; /* protect marks_list */
145 atomic_t num_marks; /* 1 for each mark and 1 for not being 146 atomic_t num_marks; /* 1 for each mark and 1 for not being
146 * past the point of no return when freeing 147 * past the point of no return when freeing
147 * a group */ 148 * a group */
148 struct list_head marks_list; /* all inode marks for this group */ 149 struct list_head marks_list; /* all inode marks for this group */
149 150
151 struct fasync_struct *fsn_fa; /* async notification */
152
150 /* groups can define private fields here or use the void *private */ 153 /* groups can define private fields here or use the void *private */
151 union { 154 union {
152 void *private; 155 void *private;
@@ -155,7 +158,6 @@ struct fsnotify_group {
155 spinlock_t idr_lock; 158 spinlock_t idr_lock;
156 struct idr idr; 159 struct idr idr;
157 u32 last_wd; 160 u32 last_wd;
158 struct fasync_struct *fa; /* async notification */
159 struct user_struct *user; 161 struct user_struct *user;
160 } inotify_data; 162 } inotify_data;
161#endif 163#endif
@@ -287,7 +289,6 @@ struct fsnotify_mark {
287 struct fsnotify_inode_mark i; 289 struct fsnotify_inode_mark i;
288 struct fsnotify_vfsmount_mark m; 290 struct fsnotify_vfsmount_mark m;
289 }; 291 };
290 struct list_head free_g_list; /* tmp list used when freeing this mark */
291 __u32 ignored_mask; /* events types to ignore */ 292 __u32 ignored_mask; /* events types to ignore */
292#define FSNOTIFY_MARK_FLAG_INODE 0x01 293#define FSNOTIFY_MARK_FLAG_INODE 0x01
293#define FSNOTIFY_MARK_FLAG_VFSMOUNT 0x02 294#define FSNOTIFY_MARK_FLAG_VFSMOUNT 0x02
@@ -360,11 +361,16 @@ static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode
360 361
361/* called from fsnotify listeners, such as fanotify or dnotify */ 362/* called from fsnotify listeners, such as fanotify or dnotify */
362 363
363/* get a reference to an existing or create a new group */ 364/* create a new group */
364extern struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops); 365extern struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops);
366/* get reference to a group */
367extern void fsnotify_get_group(struct fsnotify_group *group);
365/* drop reference on a group from fsnotify_alloc_group */ 368/* drop reference on a group from fsnotify_alloc_group */
366extern void fsnotify_put_group(struct fsnotify_group *group); 369extern void fsnotify_put_group(struct fsnotify_group *group);
367 370/* destroy group */
371extern void fsnotify_destroy_group(struct fsnotify_group *group);
372/* fasync handler function */
373extern int fsnotify_fasync(int fd, struct file *file, int on);
368/* take a reference to an event */ 374/* take a reference to an event */
369extern void fsnotify_get_event(struct fsnotify_event *event); 375extern void fsnotify_get_event(struct fsnotify_event *event);
370extern void fsnotify_put_event(struct fsnotify_event *event); 376extern void fsnotify_put_event(struct fsnotify_event *event);
@@ -405,8 +411,13 @@ extern void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask
405/* attach the mark to both the group and the inode */ 411/* attach the mark to both the group and the inode */
406extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group, 412extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group,
407 struct inode *inode, struct vfsmount *mnt, int allow_dups); 413 struct inode *inode, struct vfsmount *mnt, int allow_dups);
408/* given a mark, flag it to be freed when all references are dropped */ 414extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark, struct fsnotify_group *group,
409extern void fsnotify_destroy_mark(struct fsnotify_mark *mark); 415 struct inode *inode, struct vfsmount *mnt, int allow_dups);
416/* given a group and a mark, flag mark to be freed when all references are dropped */
417extern void fsnotify_destroy_mark(struct fsnotify_mark *mark,
418 struct fsnotify_group *group);
419extern void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark,
420 struct fsnotify_group *group);
410/* run all the marks in a group, and clear all of the vfsmount marks */ 421/* run all the marks in a group, and clear all of the vfsmount marks */
411extern void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group); 422extern void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group);
412/* run all the marks in a group, and clear all of the inode marks */ 423/* run all the marks in a group, and clear all of the inode marks */