Skip to content

Commit

Permalink
udf: Fix deadlock between writeback and udf_setsize()
Browse files Browse the repository at this point in the history
udf_setsize() called truncate_setsize() with i_data_sem held. Thus
truncate_pagecache() called from truncate_setsize() could lock a page
under i_data_sem which can deadlock as page lock ranks below
i_data_sem - e. g. writeback can hold page lock and try to acquire
i_data_sem to map a block.

Fix the problem by moving truncate_setsize() calls from under
i_data_sem. It is safe for us to change i_size without holding
i_data_sem as all the places that depend on i_size being stable already
hold inode_lock.

CC: stable@vger.kernel.org
Fixes: 7e49b6f
Signed-off-by: Jan Kara <jack@suse.cz>
  • Loading branch information
Jan Kara committed Jun 14, 2017
1 parent 146c4ad commit f2e9535
Showing 1 changed file with 2 additions and 2 deletions.
4 changes: 2 additions & 2 deletions fs/udf/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1222,8 +1222,8 @@ int udf_setsize(struct inode *inode, loff_t newsize)
return err;
}
set_size:
truncate_setsize(inode, newsize);
up_write(&iinfo->i_data_sem);
truncate_setsize(inode, newsize);
} else {
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
down_write(&iinfo->i_data_sem);
Expand All @@ -1240,9 +1240,9 @@ int udf_setsize(struct inode *inode, loff_t newsize)
udf_get_block);
if (err)
return err;
truncate_setsize(inode, newsize);
down_write(&iinfo->i_data_sem);
udf_clear_extent_cache(inode);
truncate_setsize(inode, newsize);
udf_truncate_extents(inode);
up_write(&iinfo->i_data_sem);
}
Expand Down

0 comments on commit f2e9535

Please sign in to comment.