mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
for-5.3-rc8-tag
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAl16aTEACgkQxWXV+ddt WDvICg//cSn5w+g6EnxbrAZ6IYQJ4GA7lZSk2i6Dc/lI3BTfs7Wj0SPRKd01pBjT N+wbqoOgubsS1jkNfJsGCN80XzSa0tvyQdbezj5ncgSPXp4FRlT0K24EUQNPaqbg SsvvxAOCerVN3Yj2qrHNWIS5qZ5/8/NjLXca1DJ/OYmrkKfhe+Z6/b9EuKffPnco erMnaeSvQ27hYkkcdM0DGcWDoHHAQrefGNjQzp5vncJNN1F7+EGLbcH31UwApk1K /hvOQ6Q6SoR/NKbQu3AitrR9u7v9uhWP9jHJZT46q1m89CzI4S5FjK2wKZFjPE6r 0PGRqnpdaGAERaTo3s6jIqv/X2gzJkhhhzGMiPgPJCQbAH39f/fFGEX22TjG33Yq 2CiGSIPnmKQ7HE494YLuSyHD/89SutMMCkbF0sFBoKuTnu2HQMn9r5Pk6bEKtvIY iTk75/WTXR02qWCVhTyNDa9QnxewQGJC1d1KNQ6MwbzBiYyG9S/DDZnjLJPNx7DF KAAANCDdyPpraLcmw2sD/qd1o10HfQmn9z1L2v3YvJBfjMe76SQFCP5WwaJRcjOm c3ScAX9bXeXJgH+E98kWc7T6p49IPdMDGAtArQmtjO4V8pFRuqG+2Ibg6Za/y5XZ fkaS5UY+XIk3TUpEqkWKMPMigM9a3jgHskyMgdRLQfVnoOc6Z+k= =KXB8 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
1b304a1ae4
2 changed files with 34 additions and 17 deletions
|
@ -3628,6 +3628,13 @@ void wait_on_extent_buffer_writeback(struct extent_buffer *eb)
|
|||
TASK_UNINTERRUPTIBLE);
|
||||
}
|
||||
|
||||
static void end_extent_buffer_writeback(struct extent_buffer *eb)
|
||||
{
|
||||
clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
|
||||
smp_mb__after_atomic();
|
||||
wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock eb pages and flush the bio if we can't the locks
|
||||
*
|
||||
|
@ -3699,8 +3706,11 @@ static noinline_for_stack int lock_extent_buffer_for_io(struct extent_buffer *eb
|
|||
|
||||
if (!trylock_page(p)) {
|
||||
if (!flush) {
|
||||
ret = flush_write_bio(epd);
|
||||
if (ret < 0) {
|
||||
int err;
|
||||
|
||||
err = flush_write_bio(epd);
|
||||
if (err < 0) {
|
||||
ret = err;
|
||||
failed_page_nr = i;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
@ -3715,16 +3725,23 @@ static noinline_for_stack int lock_extent_buffer_for_io(struct extent_buffer *eb
|
|||
/* Unlock already locked pages */
|
||||
for (i = 0; i < failed_page_nr; i++)
|
||||
unlock_page(eb->pages[i]);
|
||||
/*
|
||||
* Clear EXTENT_BUFFER_WRITEBACK and wake up anyone waiting on it.
|
||||
* Also set back EXTENT_BUFFER_DIRTY so future attempts to this eb can
|
||||
* be made and undo everything done before.
|
||||
*/
|
||||
btrfs_tree_lock(eb);
|
||||
spin_lock(&eb->refs_lock);
|
||||
set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags);
|
||||
end_extent_buffer_writeback(eb);
|
||||
spin_unlock(&eb->refs_lock);
|
||||
percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, eb->len,
|
||||
fs_info->dirty_metadata_batch);
|
||||
btrfs_clear_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
|
||||
btrfs_tree_unlock(eb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void end_extent_buffer_writeback(struct extent_buffer *eb)
|
||||
{
|
||||
clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
|
||||
smp_mb__after_atomic();
|
||||
wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK);
|
||||
}
|
||||
|
||||
static void set_btree_ioerr(struct page *page)
|
||||
{
|
||||
struct extent_buffer *eb = (struct extent_buffer *)page->private;
|
||||
|
|
|
@ -4985,7 +4985,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
|
|||
BTRFS_I(inode),
|
||||
LOG_OTHER_INODE_ALL,
|
||||
0, LLONG_MAX, ctx);
|
||||
iput(inode);
|
||||
btrfs_add_delayed_iput(inode);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
@ -5000,7 +5000,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
|
|||
ret = btrfs_log_inode(trans, root, BTRFS_I(inode),
|
||||
LOG_OTHER_INODE, 0, LLONG_MAX, ctx);
|
||||
if (ret) {
|
||||
iput(inode);
|
||||
btrfs_add_delayed_iput(inode);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -5009,7 +5009,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
|
|||
key.offset = 0;
|
||||
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
|
||||
if (ret < 0) {
|
||||
iput(inode);
|
||||
btrfs_add_delayed_iput(inode);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -5056,7 +5056,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
|
|||
}
|
||||
path->slots[0]++;
|
||||
}
|
||||
iput(inode);
|
||||
btrfs_add_delayed_iput(inode);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -5689,7 +5689,7 @@ static int log_new_dir_dentries(struct btrfs_trans_handle *trans,
|
|||
}
|
||||
|
||||
if (btrfs_inode_in_log(BTRFS_I(di_inode), trans->transid)) {
|
||||
iput(di_inode);
|
||||
btrfs_add_delayed_iput(di_inode);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5701,7 +5701,7 @@ static int log_new_dir_dentries(struct btrfs_trans_handle *trans,
|
|||
if (!ret &&
|
||||
btrfs_must_commit_transaction(trans, BTRFS_I(di_inode)))
|
||||
ret = 1;
|
||||
iput(di_inode);
|
||||
btrfs_add_delayed_iput(di_inode);
|
||||
if (ret)
|
||||
goto next_dir_inode;
|
||||
if (ctx->log_new_dentries) {
|
||||
|
@ -5848,7 +5848,7 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans,
|
|||
if (!ret && ctx && ctx->log_new_dentries)
|
||||
ret = log_new_dir_dentries(trans, root,
|
||||
BTRFS_I(dir_inode), ctx);
|
||||
iput(dir_inode);
|
||||
btrfs_add_delayed_iput(dir_inode);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
@ -5891,7 +5891,7 @@ static int log_new_ancestors(struct btrfs_trans_handle *trans,
|
|||
ret = btrfs_log_inode(trans, root, BTRFS_I(inode),
|
||||
LOG_INODE_EXISTS,
|
||||
0, LLONG_MAX, ctx);
|
||||
iput(inode);
|
||||
btrfs_add_delayed_iput(inode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
Loading…
Reference in a new issue