diff options
Diffstat (limited to 'fs/notify/inode_mark.c')
-rw-r--r-- | fs/notify/inode_mark.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 4c29fcf557d1..07ea8d3e6ea2 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c | |||
@@ -22,13 +22,14 @@ | |||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/writeback.h> /* for inode_lock */ | ||
26 | 25 | ||
27 | #include <asm/atomic.h> | 26 | #include <asm/atomic.h> |
28 | 27 | ||
29 | #include <linux/fsnotify_backend.h> | 28 | #include <linux/fsnotify_backend.h> |
30 | #include "fsnotify.h" | 29 | #include "fsnotify.h" |
31 | 30 | ||
31 | #include "../internal.h" | ||
32 | |||
32 | /* | 33 | /* |
33 | * Recalculate the mask of events relevant to a given inode locked. | 34 | * Recalculate the mask of events relevant to a given inode locked. |
34 | */ | 35 | */ |
@@ -237,15 +238,14 @@ out: | |||
237 | * fsnotify_unmount_inodes - an sb is unmounting. handle any watched inodes. | 238 | * fsnotify_unmount_inodes - an sb is unmounting. handle any watched inodes. |
238 | * @list: list of inodes being unmounted (sb->s_inodes) | 239 | * @list: list of inodes being unmounted (sb->s_inodes) |
239 | * | 240 | * |
240 | * Called with inode_lock held, protecting the unmounting super block's list | 241 | * Called during unmount with no locks held, so needs to be safe against |
241 | * of inodes, and with iprune_mutex held, keeping shrink_icache_memory() at bay. | 242 | * concurrent modifiers. We temporarily drop inode_sb_list_lock and CAN block. |
242 | * We temporarily drop inode_lock, however, and CAN block. | ||
243 | */ | 243 | */ |
244 | void fsnotify_unmount_inodes(struct list_head *list) | 244 | void fsnotify_unmount_inodes(struct list_head *list) |
245 | { | 245 | { |
246 | struct inode *inode, *next_i, *need_iput = NULL; | 246 | struct inode *inode, *next_i, *need_iput = NULL; |
247 | 247 | ||
248 | spin_lock(&inode_lock); | 248 | spin_lock(&inode_sb_list_lock); |
249 | list_for_each_entry_safe(inode, next_i, list, i_sb_list) { | 249 | list_for_each_entry_safe(inode, next_i, list, i_sb_list) { |
250 | struct inode *need_iput_tmp; | 250 | struct inode *need_iput_tmp; |
251 | 251 | ||
@@ -254,8 +254,11 @@ void fsnotify_unmount_inodes(struct list_head *list) | |||
254 | * I_WILL_FREE, or I_NEW which is fine because by that point | 254 | * I_WILL_FREE, or I_NEW which is fine because by that point |
255 | * the inode cannot have any associated watches. | 255 | * the inode cannot have any associated watches. |
256 | */ | 256 | */ |
257 | if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) | 257 | spin_lock(&inode->i_lock); |
258 | if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) { | ||
259 | spin_unlock(&inode->i_lock); | ||
258 | continue; | 260 | continue; |
261 | } | ||
259 | 262 | ||
260 | /* | 263 | /* |
261 | * If i_count is zero, the inode cannot have any watches and | 264 | * If i_count is zero, the inode cannot have any watches and |
@@ -263,8 +266,10 @@ void fsnotify_unmount_inodes(struct list_head *list) | |||
263 | * evict all inodes with zero i_count from icache which is | 266 | * evict all inodes with zero i_count from icache which is |
264 | * unnecessarily violent and may in fact be illegal to do. | 267 | * unnecessarily violent and may in fact be illegal to do. |
265 | */ | 268 | */ |
266 | if (!atomic_read(&inode->i_count)) | 269 | if (!atomic_read(&inode->i_count)) { |
270 | spin_unlock(&inode->i_lock); | ||
267 | continue; | 271 | continue; |
272 | } | ||
268 | 273 | ||
269 | need_iput_tmp = need_iput; | 274 | need_iput_tmp = need_iput; |
270 | need_iput = NULL; | 275 | need_iput = NULL; |
@@ -274,22 +279,25 @@ void fsnotify_unmount_inodes(struct list_head *list) | |||
274 | __iget(inode); | 279 | __iget(inode); |
275 | else | 280 | else |
276 | need_iput_tmp = NULL; | 281 | need_iput_tmp = NULL; |
282 | spin_unlock(&inode->i_lock); | ||
277 | 283 | ||
278 | /* In case the dropping of a reference would nuke next_i. */ | 284 | /* In case the dropping of a reference would nuke next_i. */ |
279 | if ((&next_i->i_sb_list != list) && | 285 | if ((&next_i->i_sb_list != list) && |
280 | atomic_read(&next_i->i_count) && | 286 | atomic_read(&next_i->i_count)) { |
281 | !(next_i->i_state & (I_FREEING | I_WILL_FREE))) { | 287 | spin_lock(&next_i->i_lock); |
282 | __iget(next_i); | 288 | if (!(next_i->i_state & (I_FREEING | I_WILL_FREE))) { |
283 | need_iput = next_i; | 289 | __iget(next_i); |
290 | need_iput = next_i; | ||
291 | } | ||
292 | spin_unlock(&next_i->i_lock); | ||
284 | } | 293 | } |
285 | 294 | ||
286 | /* | 295 | /* |
287 | * We can safely drop inode_lock here because we hold | 296 | * We can safely drop inode_sb_list_lock here because we hold |
288 | * references on both inode and next_i. Also no new inodes | 297 | * references on both inode and next_i. Also no new inodes |
289 | * will be added since the umount has begun. Finally, | 298 | * will be added since the umount has begun. |
290 | * iprune_mutex keeps shrink_icache_memory() away. | ||
291 | */ | 299 | */ |
292 | spin_unlock(&inode_lock); | 300 | spin_unlock(&inode_sb_list_lock); |
293 | 301 | ||
294 | if (need_iput_tmp) | 302 | if (need_iput_tmp) |
295 | iput(need_iput_tmp); | 303 | iput(need_iput_tmp); |
@@ -301,7 +309,7 @@ void fsnotify_unmount_inodes(struct list_head *list) | |||
301 | 309 | ||
302 | iput(inode); | 310 | iput(inode); |
303 | 311 | ||
304 | spin_lock(&inode_lock); | 312 | spin_lock(&inode_sb_list_lock); |
305 | } | 313 | } |
306 | spin_unlock(&inode_lock); | 314 | spin_unlock(&inode_sb_list_lock); |
307 | } | 315 | } |