From b84b7a1e64ae2b485bdb43ddaa583cfd51373eb1 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 18 Dec 2013 00:46:22 -0500 Subject: [PATCH] add patch fix-deadllock-when-writing-in-ENOSPC-conditions --- fix-deadllock-when-writing-in-ENOSPC-conditions | 86 +++++++++++++++++++++++++ series | 1 + timestamps | 9 ++- 3 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 fix-deadllock-when-writing-in-ENOSPC-conditions diff --git a/fix-deadllock-when-writing-in-ENOSPC-conditions b/fix-deadllock-when-writing-in-ENOSPC-conditions new file mode 100644 index 00000000..c29db57e --- /dev/null +++ b/fix-deadllock-when-writing-in-ENOSPC-conditions @@ -0,0 +1,86 @@ +ext4: fix deadlock when writing in ENOSPC conditions + +From: Jan Kara + +Akira-san has been reporting rare deadlocks of his machine when running +xfstests test 269 on ext4 filesystem. The problem turned out to be in +ext4_da_reserve_metadata() and ext4_da_reserve_space() which called +ext4_should_retry_alloc() while holding i_data_sem. Since +ext4_should_retry_alloc() can force a transaction commit, this is a +lock ordering violation and leads to deadlocks. + +Fix the problem by just removing the retry loops. These functions should +just report ENOSPC to the caller (e.g. ext4_da_write_begin()) and that +function must take care of retrying after dropping all necessary locks. + +Reported-and-tested-by: Akira Fujita +Reviewed-by: Zheng Liu +Signed-off-by: Jan Kara +Signed-off-by: "Theodore Ts'o" +Cc: stable@vger.kernel.org +--- + fs/ext4/inode.c | 12 ------------ + 1 file changed, 12 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 075763474118..61d49ff22c81 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -1206,7 +1206,6 @@ static int ext4_journalled_write_end(struct file *file, + */ + static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock) + { +- int retries = 0; + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + struct ext4_inode_info *ei = EXT4_I(inode); + unsigned int md_needed; +@@ -1218,7 +1217,6 @@ static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock) + * in order to allocate nrblocks + * worse case is one extent per block + */ +-repeat: + spin_lock(&ei->i_block_reservation_lock); + /* + * ext4_calc_metadata_amount() has side effects, which we have +@@ -1238,10 +1236,6 @@ repeat: + ei->i_da_metadata_calc_len = save_len; + ei->i_da_metadata_calc_last_lblock = save_last_lblock; + spin_unlock(&ei->i_block_reservation_lock); +- if (ext4_should_retry_alloc(inode->i_sb, &retries)) { +- cond_resched(); +- goto repeat; +- } + return -ENOSPC; + } + ei->i_reserved_meta_blocks += md_needed; +@@ -1255,7 +1249,6 @@ repeat: + */ + static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) + { +- int retries = 0; + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + struct ext4_inode_info *ei = EXT4_I(inode); + unsigned int md_needed; +@@ -1277,7 +1270,6 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) + * in order to allocate nrblocks + * worse case is one extent per block + */ +-repeat: + spin_lock(&ei->i_block_reservation_lock); + /* + * ext4_calc_metadata_amount() has side effects, which we have +@@ -1297,10 +1289,6 @@ repeat: + ei->i_da_metadata_calc_len = save_len; + ei->i_da_metadata_calc_last_lblock = save_last_lblock; + spin_unlock(&ei->i_block_reservation_lock); +- if (ext4_should_retry_alloc(inode->i_sb, &retries)) { +- cond_resched(); +- goto repeat; +- } + dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1)); + return -ENOSPC; + } +-- +1.8.1.4 + + diff --git a/series b/series index 0f89d7f5..b781b8f4 100644 --- a/series +++ b/series @@ -12,6 +12,7 @@ enable-punch-hole-for-bigalloc retry-allocation-when-inline-extent-conversion-failed standardize-error-handling-in-ext4_da_write_inline_data_begin +fix-deadllock-when-writing-in-ENOSPC-conditions ########################################## # unstable patches diff --git a/timestamps b/timestamps index e0c98177..6f03ba1b 100755 --- a/timestamps +++ b/timestamps @@ -26,6 +26,9 @@ touch -d @1386555239 revise-KERN_EMERG-error-messages touch -d @1386555299 rename-oboleted-msg-JBD-to-JBD2 touch -d @1386555359 enable-punch-hole-for-bigalloc touch -d @1386555419 stable-boundary -touch -d @1386561235 timestamps -touch -d @1386561689 series -touch -d @1386561745 status +touch -d @1387344993 retry-allocation-when-inline-extent-conversion-failed +touch -d @1387344998 standardize-error-handling-in-ext4_da_write_inline_data_begin +touch -d @1387345484 fix-deadllock-when-writing-in-ENOSPC-conditions +touch -d @1387345501 series +touch -d @1387345505 status +touch -d @1387345571 timestamps -- 2.11.4.GIT