aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorQu Wenruo <quwenruo@cn.fujitsu.com>2014-03-26 22:51:58 -0400
committerChris Mason <clm@fb.com>2014-04-07 12:08:42 -0400
commit3ac0d7b96a268a98bd474cab8bce3a9f125aaccf (patch)
tree204d2121e02075ef4a5c23b3011010a537a556da /fs/btrfs
parent60999ca4b4033ee199702a4ceb9f5b801f7962b9 (diff)
btrfs: Change the expanding write sequence to fix snapshot related bug.
When testing fsstress with snapshot making background, some snapshot following problem. Snapshot 270: inode 323: size 0 Snapshot 271: inode 323: size 349145 |-------Hole---|---------Empty gap-------|-------Hole-----| 0 122880 172032 349145 Snapshot 272: inode 323: size 349145 |-------Hole---|------------Data---------|-------Hole-----| 0 122880 172032 349145 The fsstress operation on inode 323 is the following: write: offset 126832 len 43124 truncate: size 349145 Since the write with offset is consist of 2 operations: 1. punch hole 2. write data Hole punching is faster than data write, so hole punching in write and truncate is done first and then buffered write, so the snapshot 271 got empty gap, which will not pass btrfsck. To fix the bug, this patch will change the write sequence which will first punch a hole covering the write end if a hole is needed. Reported-by: Gui Hecheng <guihc.fnst@cn.fujitsu.com> Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/file.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 036f506cabd8..23f6a9d9f104 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1727,6 +1727,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
1727 struct btrfs_root *root = BTRFS_I(inode)->root; 1727 struct btrfs_root *root = BTRFS_I(inode)->root;
1728 loff_t *ppos = &iocb->ki_pos; 1728 loff_t *ppos = &iocb->ki_pos;
1729 u64 start_pos; 1729 u64 start_pos;
1730 u64 end_pos;
1730 ssize_t num_written = 0; 1731 ssize_t num_written = 0;
1731 ssize_t err = 0; 1732 ssize_t err = 0;
1732 size_t count, ocount; 1733 size_t count, ocount;
@@ -1781,7 +1782,9 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
1781 1782
1782 start_pos = round_down(pos, root->sectorsize); 1783 start_pos = round_down(pos, root->sectorsize);
1783 if (start_pos > i_size_read(inode)) { 1784 if (start_pos > i_size_read(inode)) {
1784 err = btrfs_cont_expand(inode, i_size_read(inode), start_pos); 1785 /* Expand hole size to cover write data, preventing empty gap */
1786 end_pos = round_up(pos + iov->iov_len, root->sectorsize);
1787 err = btrfs_cont_expand(inode, i_size_read(inode), end_pos);
1785 if (err) { 1788 if (err) {
1786 mutex_unlock(&inode->i_mutex); 1789 mutex_unlock(&inode->i_mutex);
1787 goto out; 1790 goto out;