diff options
Diffstat (limited to 'fs/notify')
-rw-r--r-- | fs/notify/inode_mark.c | 14 | ||||
-rw-r--r-- | fs/notify/inotify/inotify.c | 16 |
2 files changed, 18 insertions, 12 deletions
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 869f94bb040f..81b5bbb3a7ee 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -369,13 +369,16 @@ void fsnotify_unmount_inodes(struct list_head *list) list_for_each_entry_safe(inode, next_i, list, i_sb_list) { struct inode *need_iput_tmp; + spin_lock(&inode->i_lock); /* * We cannot __iget() an inode in state I_CLEAR, I_FREEING, * I_WILL_FREE, or I_NEW which is fine because by that point * the inode cannot have any associated watches. */ - if (inode->i_state & (I_CLEAR|I_FREEING|I_WILL_FREE|I_NEW)) + if (inode->i_state & (I_CLEAR|I_FREEING|I_WILL_FREE|I_NEW)) { + spin_unlock(&inode->i_lock); continue; + } /* * If i_count is zero, the inode cannot have any watches and @@ -383,19 +386,20 @@ void fsnotify_unmount_inodes(struct list_head *list) * evict all inodes with zero i_count from icache which is * unnecessarily violent and may in fact be illegal to do. */ - if (!inode->i_count) + if (!inode->i_count) { + spin_unlock(&inode->i_lock); continue; + } need_iput_tmp = need_iput; need_iput = NULL; /* In case fsnotify_inode_delete() drops a reference. */ if (inode != need_iput_tmp) { - spin_lock(&inode->i_lock); __iget(inode); - spin_unlock(&inode->i_lock); } else need_iput_tmp = NULL; + spin_unlock(&inode->i_lock); /* In case the dropping of a reference would nuke next_i. */ if (&next_i->i_sb_list != list) { @@ -416,7 +420,6 @@ void fsnotify_unmount_inodes(struct list_head *list) * iprune_mutex keeps shrink_icache_memory() away. */ spin_unlock(&sb_inode_list_lock); - spin_unlock(&inode_lock); if (need_iput_tmp) iput(need_iput_tmp); @@ -428,7 +431,6 @@ void fsnotify_unmount_inodes(struct list_head *list) iput(inode); - spin_lock(&inode_lock); spin_lock(&sb_inode_list_lock); } } diff --git a/fs/notify/inotify/inotify.c b/fs/notify/inotify/inotify.c index 44e90ef0b0a3..7846758db7da 100644 --- a/fs/notify/inotify/inotify.c +++ b/fs/notify/inotify/inotify.c @@ -394,13 +394,16 @@ void inotify_unmount_inodes(struct list_head *list) struct inode *need_iput_tmp; struct list_head *watches; + spin_lock(&inode->i_lock); /* * We cannot __iget() an inode in state I_CLEAR, I_FREEING, * I_WILL_FREE, or I_NEW which is fine because by that point * the inode cannot have any associated watches. */ - if (inode->i_state & (I_CLEAR|I_FREEING|I_WILL_FREE|I_NEW)) + if (inode->i_state & (I_CLEAR|I_FREEING|I_WILL_FREE|I_NEW)) { + spin_unlock(&inode->i_lock); continue; + } /* * If i_count is zero, the inode cannot have any watches and @@ -408,18 +411,21 @@ void inotify_unmount_inodes(struct list_head *list) * evict all inodes with zero i_count from icache which is * unnecessarily violent and may in fact be illegal to do. */ - if (!inode->i_count) + if (!inode->i_count) { + spin_unlock(&inode->i_lock); continue; + } need_iput_tmp = need_iput; need_iput = NULL; /* In case inotify_remove_watch_locked() drops a reference. */ if (inode != need_iput_tmp) { - spin_lock(&inode->i_lock); __iget(inode); - spin_unlock(&inode->i_lock); } else need_iput_tmp = NULL; + + spin_unlock(&inode->i_lock); + /* In case the dropping of a reference would nuke next_i. */ if (&next_i->i_sb_list != list) { spin_lock(&next_i->i_lock); @@ -439,7 +445,6 @@ void inotify_unmount_inodes(struct list_head *list) * iprune_mutex keeps shrink_icache_memory() away. */ spin_unlock(&sb_inode_list_lock); - spin_unlock(&inode_lock); if (need_iput_tmp) iput(need_iput_tmp); @@ -459,7 +464,6 @@ void inotify_unmount_inodes(struct list_head *list) mutex_unlock(&inode->inotify_mutex); iput(inode); - spin_lock(&inode_lock); spin_lock(&sb_inode_list_lock); } } |