提交 88090ad3 编写于 作者: F Filipe Manana 提交者: David Sterba

btrfs: do not start and wait for delalloc on snapshot roots on transaction commit

We do not need anymore to start writeback for delalloc of roots that are
being snapshotted and wait for it to complete. This was done in commit
609e804d ("Btrfs: fix file corruption after snapshotting due to mix
of buffered/DIO writes") to fix a type of file corruption where files in a
snapshot end up having their i_size updated in a non-ordered way, leaving
implicit file holes, when buffered IO writes that increase a file's size
are followed by direct IO writes that also increase the file's size.

This is not needed anymore because we now have a more generic mechanism
to prevent a non-ordered i_size update since commit 9ddc959e
("btrfs: use the file extent tree infrastructure"), which addresses this
scenario involving snapshots as well.
Reviewed-by: NJosef Bacik <josef@toxicpanda.com>
Signed-off-by: NFilipe Manana <fdmanana@suse.com>
Reviewed-by: NDavid Sterba <dsterba@suse.com>
Signed-off-by: NDavid Sterba <dsterba@suse.com>
上级 196d59ab
...@@ -1956,10 +1956,8 @@ static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans) ...@@ -1956,10 +1956,8 @@ static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans)
} }
} }
static inline int btrfs_start_delalloc_flush(struct btrfs_trans_handle *trans) static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info)
{ {
struct btrfs_fs_info *fs_info = trans->fs_info;
/* /*
* We use writeback_inodes_sb here because if we used * We use writeback_inodes_sb here because if we used
* btrfs_start_delalloc_roots we would deadlock with fs freeze. * btrfs_start_delalloc_roots we would deadlock with fs freeze.
...@@ -1969,50 +1967,15 @@ static inline int btrfs_start_delalloc_flush(struct btrfs_trans_handle *trans) ...@@ -1969,50 +1967,15 @@ static inline int btrfs_start_delalloc_flush(struct btrfs_trans_handle *trans)
* from already being in a transaction and our join_transaction doesn't * from already being in a transaction and our join_transaction doesn't
* have to re-take the fs freeze lock. * have to re-take the fs freeze lock.
*/ */
if (btrfs_test_opt(fs_info, FLUSHONCOMMIT)) { if (btrfs_test_opt(fs_info, FLUSHONCOMMIT))
writeback_inodes_sb(fs_info->sb, WB_REASON_SYNC); writeback_inodes_sb(fs_info->sb, WB_REASON_SYNC);
} else {
struct btrfs_pending_snapshot *pending;
struct list_head *head = &trans->transaction->pending_snapshots;
/*
* Flush dellaloc for any root that is going to be snapshotted.
* This is done to avoid a corrupted version of files, in the
* snapshots, that had both buffered and direct IO writes (even
* if they were done sequentially) due to an unordered update of
* the inode's size on disk.
*/
list_for_each_entry(pending, head, list) {
int ret;
ret = btrfs_start_delalloc_snapshot(pending->root);
if (ret)
return ret;
}
}
return 0; return 0;
} }
static inline void btrfs_wait_delalloc_flush(struct btrfs_trans_handle *trans) static inline void btrfs_wait_delalloc_flush(struct btrfs_fs_info *fs_info)
{ {
struct btrfs_fs_info *fs_info = trans->fs_info; if (btrfs_test_opt(fs_info, FLUSHONCOMMIT))
if (btrfs_test_opt(fs_info, FLUSHONCOMMIT)) {
btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1); btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
} else {
struct btrfs_pending_snapshot *pending;
struct list_head *head = &trans->transaction->pending_snapshots;
/*
* Wait for any dellaloc that we started previously for the roots
* that are going to be snapshotted. This is to avoid a corrupted
* version of files in the snapshots that had both buffered and
* direct IO writes (even if they were done sequentially).
*/
list_for_each_entry(pending, head, list)
btrfs_wait_ordered_extents(pending->root,
U64_MAX, 0, U64_MAX);
}
} }
int btrfs_commit_transaction(struct btrfs_trans_handle *trans) int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
...@@ -2150,7 +2113,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) ...@@ -2150,7 +2113,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
extwriter_counter_dec(cur_trans, trans->type); extwriter_counter_dec(cur_trans, trans->type);
ret = btrfs_start_delalloc_flush(trans); ret = btrfs_start_delalloc_flush(fs_info);
if (ret) if (ret)
goto cleanup_transaction; goto cleanup_transaction;
...@@ -2166,7 +2129,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) ...@@ -2166,7 +2129,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
if (ret) if (ret)
goto cleanup_transaction; goto cleanup_transaction;
btrfs_wait_delalloc_flush(trans); btrfs_wait_delalloc_flush(fs_info);
/* /*
* Wait for all ordered extents started by a fast fsync that joined this * Wait for all ordered extents started by a fast fsync that joined this
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册