diff options
Diffstat (limited to 'fs/notify')
-rw-r--r-- | fs/notify/fsnotify.c | 33 | ||||
-rw-r--r-- | fs/notify/inode_mark.c | 2 |
2 files changed, 7 insertions, 28 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 36802420d69a..4498a208df94 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
@@ -88,8 +88,6 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) | |||
88 | { | 88 | { |
89 | struct dentry *parent; | 89 | struct dentry *parent; |
90 | struct inode *p_inode; | 90 | struct inode *p_inode; |
91 | bool send = false; | ||
92 | bool should_update_children = false; | ||
93 | 91 | ||
94 | if (!dentry) | 92 | if (!dentry) |
95 | dentry = path->dentry; | 93 | dentry = path->dentry; |
@@ -97,29 +95,12 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) | |||
97 | if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) | 95 | if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) |
98 | return; | 96 | return; |
99 | 97 | ||
100 | spin_lock(&dentry->d_lock); | 98 | parent = dget_parent(dentry); |
101 | parent = dentry->d_parent; | ||
102 | p_inode = parent->d_inode; | 99 | p_inode = parent->d_inode; |
103 | 100 | ||
104 | if (fsnotify_inode_watches_children(p_inode)) { | 101 | if (unlikely(!fsnotify_inode_watches_children(p_inode))) |
105 | if (p_inode->i_fsnotify_mask & mask) { | 102 | __fsnotify_update_child_dentry_flags(p_inode); |
106 | dget(parent); | 103 | else if (p_inode->i_fsnotify_mask & mask) { |
107 | send = true; | ||
108 | } | ||
109 | } else { | ||
110 | /* | ||
111 | * The parent doesn't care about events on it's children but | ||
112 | * at least one child thought it did. We need to run all the | ||
113 | * children and update their d_flags to let them know p_inode | ||
114 | * doesn't care about them any more. | ||
115 | */ | ||
116 | dget(parent); | ||
117 | should_update_children = true; | ||
118 | } | ||
119 | |||
120 | spin_unlock(&dentry->d_lock); | ||
121 | |||
122 | if (send) { | ||
123 | /* we are notifying a parent so come up with the new mask which | 104 | /* we are notifying a parent so come up with the new mask which |
124 | * specifies these are events which came from a child. */ | 105 | * specifies these are events which came from a child. */ |
125 | mask |= FS_EVENT_ON_CHILD; | 106 | mask |= FS_EVENT_ON_CHILD; |
@@ -130,13 +111,9 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) | |||
130 | else | 111 | else |
131 | fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, | 112 | fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, |
132 | dentry->d_name.name, 0); | 113 | dentry->d_name.name, 0); |
133 | dput(parent); | ||
134 | } | 114 | } |
135 | 115 | ||
136 | if (unlikely(should_update_children)) { | 116 | dput(parent); |
137 | __fsnotify_update_child_dentry_flags(p_inode); | ||
138 | dput(parent); | ||
139 | } | ||
140 | } | 117 | } |
141 | EXPORT_SYMBOL_GPL(__fsnotify_parent); | 118 | EXPORT_SYMBOL_GPL(__fsnotify_parent); |
142 | 119 | ||
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 33297c005060..21ed10660b80 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c | |||
@@ -240,6 +240,7 @@ void fsnotify_unmount_inodes(struct list_head *list) | |||
240 | { | 240 | { |
241 | struct inode *inode, *next_i, *need_iput = NULL; | 241 | struct inode *inode, *next_i, *need_iput = NULL; |
242 | 242 | ||
243 | spin_lock(&inode_lock); | ||
243 | list_for_each_entry_safe(inode, next_i, list, i_sb_list) { | 244 | list_for_each_entry_safe(inode, next_i, list, i_sb_list) { |
244 | struct inode *need_iput_tmp; | 245 | struct inode *need_iput_tmp; |
245 | 246 | ||
@@ -297,4 +298,5 @@ void fsnotify_unmount_inodes(struct list_head *list) | |||
297 | 298 | ||
298 | spin_lock(&inode_lock); | 299 | spin_lock(&inode_lock); |
299 | } | 300 | } |
301 | spin_unlock(&inode_lock); | ||
300 | } | 302 | } |