Skip to content

Commit 1b304a1

Browse files
committed
Merge tag 'for-5.3-rc8-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "Here are two fixes, one of them urgent fixing a bug introduced in 5.2 and reported by many users. It took time to identify the root cause, catching the 5.3 release is higly desired also to push the fix to 5.2 stable tree. The bug is a mess up of return values after adding proper error handling and honestly the kind of bug that can cause sleeping disorders until it's caught. My appologies to everybody who was affected. Summary of what could happen: 1) either a hang when committing a transaction, if this happens there's no risk of corruption, still the hang is very inconvenient and can't be resolved without a reboot 2) writeback for some btree nodes may never be started and we end up committing a transaction without noticing that, this is really serious and that will lead to the "parent transid verify failed" messages" * tag 'for-5.3-rc8-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: Btrfs: fix unwritten extent buffers and hangs on future writeback attempts Btrfs: fix assertion failure during fsync and use of stale transaction
2 parents 505a8ec + 18dfa71 commit 1b304a1

File tree

2 files changed

+34
-17
lines changed

2 files changed

+34
-17
lines changed

fs/btrfs/extent_io.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3628,6 +3628,13 @@ void wait_on_extent_buffer_writeback(struct extent_buffer *eb)
36283628
TASK_UNINTERRUPTIBLE);
36293629
}
36303630

3631+
static void end_extent_buffer_writeback(struct extent_buffer *eb)
3632+
{
3633+
clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
3634+
smp_mb__after_atomic();
3635+
wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK);
3636+
}
3637+
36313638
/*
36323639
* Lock eb pages and flush the bio if we can't the locks
36333640
*
@@ -3699,8 +3706,11 @@ static noinline_for_stack int lock_extent_buffer_for_io(struct extent_buffer *eb
36993706

37003707
if (!trylock_page(p)) {
37013708
if (!flush) {
3702-
ret = flush_write_bio(epd);
3703-
if (ret < 0) {
3709+
int err;
3710+
3711+
err = flush_write_bio(epd);
3712+
if (err < 0) {
3713+
ret = err;
37043714
failed_page_nr = i;
37053715
goto err_unlock;
37063716
}
@@ -3715,16 +3725,23 @@ static noinline_for_stack int lock_extent_buffer_for_io(struct extent_buffer *eb
37153725
/* Unlock already locked pages */
37163726
for (i = 0; i < failed_page_nr; i++)
37173727
unlock_page(eb->pages[i]);
3728+
/*
3729+
* Clear EXTENT_BUFFER_WRITEBACK and wake up anyone waiting on it.
3730+
* Also set back EXTENT_BUFFER_DIRTY so future attempts to this eb can
3731+
* be made and undo everything done before.
3732+
*/
3733+
btrfs_tree_lock(eb);
3734+
spin_lock(&eb->refs_lock);
3735+
set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags);
3736+
end_extent_buffer_writeback(eb);
3737+
spin_unlock(&eb->refs_lock);
3738+
percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, eb->len,
3739+
fs_info->dirty_metadata_batch);
3740+
btrfs_clear_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
3741+
btrfs_tree_unlock(eb);
37183742
return ret;
37193743
}
37203744

3721-
static void end_extent_buffer_writeback(struct extent_buffer *eb)
3722-
{
3723-
clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
3724-
smp_mb__after_atomic();
3725-
wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK);
3726-
}
3727-
37283745
static void set_btree_ioerr(struct page *page)
37293746
{
37303747
struct extent_buffer *eb = (struct extent_buffer *)page->private;

fs/btrfs/tree-log.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4985,7 +4985,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
49854985
BTRFS_I(inode),
49864986
LOG_OTHER_INODE_ALL,
49874987
0, LLONG_MAX, ctx);
4988-
iput(inode);
4988+
btrfs_add_delayed_iput(inode);
49894989
}
49904990
}
49914991
continue;
@@ -5000,7 +5000,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
50005000
ret = btrfs_log_inode(trans, root, BTRFS_I(inode),
50015001
LOG_OTHER_INODE, 0, LLONG_MAX, ctx);
50025002
if (ret) {
5003-
iput(inode);
5003+
btrfs_add_delayed_iput(inode);
50045004
continue;
50055005
}
50065006

@@ -5009,7 +5009,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
50095009
key.offset = 0;
50105010
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
50115011
if (ret < 0) {
5012-
iput(inode);
5012+
btrfs_add_delayed_iput(inode);
50135013
continue;
50145014
}
50155015

@@ -5056,7 +5056,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
50565056
}
50575057
path->slots[0]++;
50585058
}
5059-
iput(inode);
5059+
btrfs_add_delayed_iput(inode);
50605060
}
50615061

50625062
return ret;
@@ -5689,7 +5689,7 @@ static int log_new_dir_dentries(struct btrfs_trans_handle *trans,
56895689
}
56905690

56915691
if (btrfs_inode_in_log(BTRFS_I(di_inode), trans->transid)) {
5692-
iput(di_inode);
5692+
btrfs_add_delayed_iput(di_inode);
56935693
break;
56945694
}
56955695

@@ -5701,7 +5701,7 @@ static int log_new_dir_dentries(struct btrfs_trans_handle *trans,
57015701
if (!ret &&
57025702
btrfs_must_commit_transaction(trans, BTRFS_I(di_inode)))
57035703
ret = 1;
5704-
iput(di_inode);
5704+
btrfs_add_delayed_iput(di_inode);
57055705
if (ret)
57065706
goto next_dir_inode;
57075707
if (ctx->log_new_dentries) {
@@ -5848,7 +5848,7 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans,
58485848
if (!ret && ctx && ctx->log_new_dentries)
58495849
ret = log_new_dir_dentries(trans, root,
58505850
BTRFS_I(dir_inode), ctx);
5851-
iput(dir_inode);
5851+
btrfs_add_delayed_iput(dir_inode);
58525852
if (ret)
58535853
goto out;
58545854
}
@@ -5891,7 +5891,7 @@ static int log_new_ancestors(struct btrfs_trans_handle *trans,
58915891
ret = btrfs_log_inode(trans, root, BTRFS_I(inode),
58925892
LOG_INODE_EXISTS,
58935893
0, LLONG_MAX, ctx);
5894-
iput(inode);
5894+
btrfs_add_delayed_iput(inode);
58955895
if (ret)
58965896
return ret;
58975897

0 commit comments

Comments
 (0)