diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-03-08 21:17:20 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-03-08 21:17:20 -0300 |
commit | eccbe858ce6412b96fc7cb32eb23a3592f64e5f6 (patch) | |
tree | ed4f0e52d266bffc68a5b68afcfe69882b917efb /fs/fs-writeback.c | |
parent | 0c1ac6822620b9868cfad5b4c2c223c6cd6fbfd8 (diff) |
Linux-libre 4.4.4-gnupck-4.4.4-gnu
Diffstat (limited to 'fs/fs-writeback.c')
-rw-r--r-- | fs/fs-writeback.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 023f6a1f2..e5232bbcb 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -317,6 +317,7 @@ static void inode_switch_wbs_work_fn(struct work_struct *work) struct inode_switch_wbs_context *isw = container_of(work, struct inode_switch_wbs_context, work); struct inode *inode = isw->inode; + struct super_block *sb = inode->i_sb; struct address_space *mapping = inode->i_mapping; struct bdi_writeback *old_wb = inode->i_wb; struct bdi_writeback *new_wb = isw->new_wb; @@ -423,6 +424,7 @@ skip_switch: wb_put(new_wb); iput(inode); + deactivate_super(sb); kfree(isw); } @@ -469,11 +471,14 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id) /* while holding I_WB_SWITCH, no one else can update the association */ spin_lock(&inode->i_lock); + if (inode->i_state & (I_WB_SWITCH | I_FREEING) || - inode_to_wb(inode) == isw->new_wb) { - spin_unlock(&inode->i_lock); - goto out_free; - } + inode_to_wb(inode) == isw->new_wb) + goto out_unlock; + + if (!atomic_inc_not_zero(&inode->i_sb->s_active)) + goto out_unlock; + inode->i_state |= I_WB_SWITCH; spin_unlock(&inode->i_lock); @@ -489,6 +494,8 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id) call_rcu(&isw->rcu_head, inode_switch_wbs_rcu_fn); return; +out_unlock: + spin_unlock(&inode->i_lock); out_free: if (isw->new_wb) wb_put(isw->new_wb); |