diff options
Diffstat (limited to 'fs/notify')
-rw-r--r-- | fs/notify/inode_mark.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 282150f74cfa..0a499d2c6191 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c | |||
@@ -89,6 +89,7 @@ | |||
89 | #include <linux/mutex.h> | 89 | #include <linux/mutex.h> |
90 | #include <linux/slab.h> | 90 | #include <linux/slab.h> |
91 | #include <linux/spinlock.h> | 91 | #include <linux/spinlock.h> |
92 | #include <linux/writeback.h> /* for inode_lock */ | ||
92 | 93 | ||
93 | #include <asm/atomic.h> | 94 | #include <asm/atomic.h> |
94 | 95 | ||
@@ -351,3 +352,74 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry, | |||
351 | 352 | ||
352 | return ret; | 353 | return ret; |
353 | } | 354 | } |
355 | |||
356 | /** | ||
357 | * fsnotify_unmount_inodes - an sb is unmounting. handle any watched inodes. | ||
358 | * @list: list of inodes being unmounted (sb->s_inodes) | ||
359 | * | ||
360 | * Called with inode_lock held, protecting the unmounting super block's list | ||
361 | * of inodes, and with iprune_mutex held, keeping shrink_icache_memory() at bay. | ||
362 | * We temporarily drop inode_lock, however, and CAN block. | ||
363 | */ | ||
364 | void fsnotify_unmount_inodes(struct list_head *list) | ||
365 | { | ||
366 | struct inode *inode, *next_i, *need_iput = NULL; | ||
367 | |||
368 | list_for_each_entry_safe(inode, next_i, list, i_sb_list) { | ||
369 | struct inode *need_iput_tmp; | ||
370 | |||
371 | /* | ||
372 | * We cannot __iget() an inode in state I_CLEAR, I_FREEING, | ||
373 | * I_WILL_FREE, or I_NEW which is fine because by that point | ||
374 | * the inode cannot have any associated watches. | ||
375 | */ | ||
376 | if (inode->i_state & (I_CLEAR|I_FREEING|I_WILL_FREE|I_NEW)) | ||
377 | continue; | ||
378 | |||
379 | /* | ||
380 | * If i_count is zero, the inode cannot have any watches and | ||
381 | * doing an __iget/iput with MS_ACTIVE clear would actually | ||
382 | * evict all inodes with zero i_count from icache which is | ||
383 | * unnecessarily violent and may in fact be illegal to do. | ||
384 | */ | ||
385 | if (!atomic_read(&inode->i_count)) | ||
386 | continue; | ||
387 | |||
388 | need_iput_tmp = need_iput; | ||
389 | need_iput = NULL; | ||
390 | |||
391 | /* In case fsnotify_inode_delete() drops a reference. */ | ||
392 | if (inode != need_iput_tmp) | ||
393 | __iget(inode); | ||
394 | else | ||
395 | need_iput_tmp = NULL; | ||
396 | |||
397 | /* In case the dropping of a reference would nuke next_i. */ | ||
398 | if ((&next_i->i_sb_list != list) && | ||
399 | atomic_read(&next_i->i_count) && | ||
400 | !(next_i->i_state & (I_CLEAR | I_FREEING | I_WILL_FREE))) { | ||
401 | __iget(next_i); | ||
402 | need_iput = next_i; | ||
403 | } | ||
404 | |||
405 | /* | ||
406 | * We can safely drop inode_lock here because we hold | ||
407 | * references on both inode and next_i. Also no new inodes | ||
408 | * will be added since the umount has begun. Finally, | ||
409 | * iprune_mutex keeps shrink_icache_memory() away. | ||
410 | */ | ||
411 | spin_unlock(&inode_lock); | ||
412 | |||
413 | if (need_iput_tmp) | ||
414 | iput(need_iput_tmp); | ||
415 | |||
416 | /* for each watch, send FS_UNMOUNT and then remove it */ | ||
417 | fsnotify(inode, FS_UNMOUNT, inode, FSNOTIFY_EVENT_INODE, NULL, 0); | ||
418 | |||
419 | fsnotify_inode_delete(inode); | ||
420 | |||
421 | iput(inode); | ||
422 | |||
423 | spin_lock(&inode_lock); | ||
424 | } | ||
425 | } | ||