mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
fs: protect inode->i_state with inode->i_lock
Protect inode state transitions and validity checks with the inode->i_lock. This enables us to make inode state transitions independently of the inode_lock and is the first step to peeling away the inode_lock from the code. This requires that __iget() is done atomically with i_state checks during list traversals so that we don't race with another thread marking the inode I_FREEING between the state check and grabbing the reference. Also remove the unlock_new_inode() memory barrier optimisation required to avoid taking the inode_lock when clearing I_NEW. Simplify the code by simply taking the inode->i_lock around the state change and wakeup. Because the wakeup is no longer tricky, remove the wake_up_inode() function and open code the wakeup where necessary. Signed-off-by: Dave Chinner <[email protected]> Signed-off-by: Al Viro <[email protected]>
This commit is contained in:
parent
3dc8fe4dca
commit
250df6ed27
11 changed files with 174 additions and 74 deletions
|
|
@ -254,8 +254,11 @@ void fsnotify_unmount_inodes(struct list_head *list)
|
|||
* 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_FREEING|I_WILL_FREE|I_NEW))
|
||||
spin_lock(&inode->i_lock);
|
||||
if (inode->i_state & (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
|
||||
|
|
@ -263,8 +266,10 @@ 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 (!atomic_read(&inode->i_count))
|
||||
if (!atomic_read(&inode->i_count)) {
|
||||
spin_unlock(&inode->i_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
need_iput_tmp = need_iput;
|
||||
need_iput = NULL;
|
||||
|
|
@ -274,13 +279,17 @@ void fsnotify_unmount_inodes(struct list_head *list)
|
|||
__iget(inode);
|
||||
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) &&
|
||||
atomic_read(&next_i->i_count) &&
|
||||
!(next_i->i_state & (I_FREEING | I_WILL_FREE))) {
|
||||
__iget(next_i);
|
||||
need_iput = next_i;
|
||||
atomic_read(&next_i->i_count)) {
|
||||
spin_lock(&next_i->i_lock);
|
||||
if (!(next_i->i_state & (I_FREEING | I_WILL_FREE))) {
|
||||
__iget(next_i);
|
||||
need_iput = next_i;
|
||||
}
|
||||
spin_unlock(&next_i->i_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue