diff options
author | Yang Dongsheng <yangds.fnst@cn.fujitsu.com> | 2015-04-09 00:08:43 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-04-26 09:27:03 -0400 |
commit | 6e17d30bfaf43e04d991392d8484f1c556810c33 (patch) | |
tree | 6a07d82e7c3667748e4a179aa1cb184250143947 /fs/btrfs | |
parent | 909e26dce3f7600f5e293ac0522c28790a0c8c9c (diff) |
Btrfs: fill ->last_trans for delayed inode in btrfs_fill_inode.
We need to fill inode when we found a node for it in delayed_nodes_tree.
But we did not fill the ->last_trans currently, it will cause the test
of xfstest/generic/311 fail. Scenario of the 311 is shown as below:
Problem:
(1). test_fd = open(fname, O_RDWR|O_DIRECT)
(2). pwrite(test_fd, buf, 4096, 0)
(3). close(test_fd)
(4). drop_all_caches() <-------- "echo 3 > /proc/sys/vm/drop_caches"
(5). test_fd = open(fname, O_RDWR|O_DIRECT)
(6). fsync(test_fd);
<-------- we did not get the correct log entry for the file
Reason:
When we re-open this file in (5), we would find a node
in delayed_nodes_tree and fill the inode we are lookup with the
information. But the ->last_trans is not filled, then the fsync()
will check the ->last_trans and found it's 0 then say this inode
is already in our tree which is commited, not recording the extents
for it.
Fix:
This patch fill the ->last_trans properly and set the
runtime_flags if needed in this situation. Then we can get the
log entries we expected after (6) and generic/311 passed.
Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
Reviewed-by: Miao Xie <miaoxie@huawei.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/delayed-inode.c | 2 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 21 |
2 files changed, 14 insertions, 9 deletions
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index cde698a07d21..a2ae42720a6a 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
@@ -1802,6 +1802,8 @@ int btrfs_fill_inode(struct inode *inode, u32 *rdev) | |||
1802 | set_nlink(inode, btrfs_stack_inode_nlink(inode_item)); | 1802 | set_nlink(inode, btrfs_stack_inode_nlink(inode_item)); |
1803 | inode_set_bytes(inode, btrfs_stack_inode_nbytes(inode_item)); | 1803 | inode_set_bytes(inode, btrfs_stack_inode_nbytes(inode_item)); |
1804 | BTRFS_I(inode)->generation = btrfs_stack_inode_generation(inode_item); | 1804 | BTRFS_I(inode)->generation = btrfs_stack_inode_generation(inode_item); |
1805 | BTRFS_I(inode)->last_trans = btrfs_stack_inode_transid(inode_item); | ||
1806 | |||
1805 | inode->i_version = btrfs_stack_inode_sequence(inode_item); | 1807 | inode->i_version = btrfs_stack_inode_sequence(inode_item); |
1806 | inode->i_rdev = 0; | 1808 | inode->i_rdev = 0; |
1807 | *rdev = btrfs_stack_inode_rdev(inode_item); | 1809 | *rdev = btrfs_stack_inode_rdev(inode_item); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 27b59b8362f9..0020b5675fa9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -3633,25 +3633,28 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
3633 | BTRFS_I(inode)->generation = btrfs_inode_generation(leaf, inode_item); | 3633 | BTRFS_I(inode)->generation = btrfs_inode_generation(leaf, inode_item); |
3634 | BTRFS_I(inode)->last_trans = btrfs_inode_transid(leaf, inode_item); | 3634 | BTRFS_I(inode)->last_trans = btrfs_inode_transid(leaf, inode_item); |
3635 | 3635 | ||
3636 | inode->i_version = btrfs_inode_sequence(leaf, inode_item); | ||
3637 | inode->i_generation = BTRFS_I(inode)->generation; | ||
3638 | inode->i_rdev = 0; | ||
3639 | rdev = btrfs_inode_rdev(leaf, inode_item); | ||
3640 | |||
3641 | BTRFS_I(inode)->index_cnt = (u64)-1; | ||
3642 | BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); | ||
3643 | |||
3644 | cache_index: | ||
3636 | /* | 3645 | /* |
3637 | * If we were modified in the current generation and evicted from memory | 3646 | * If we were modified in the current generation and evicted from memory |
3638 | * and then re-read we need to do a full sync since we don't have any | 3647 | * and then re-read we need to do a full sync since we don't have any |
3639 | * idea about which extents were modified before we were evicted from | 3648 | * idea about which extents were modified before we were evicted from |
3640 | * cache. | 3649 | * cache. |
3650 | * | ||
3651 | * This is required for both inode re-read from disk and delayed inode | ||
3652 | * in delayed_nodes_tree. | ||
3641 | */ | 3653 | */ |
3642 | if (BTRFS_I(inode)->last_trans == root->fs_info->generation) | 3654 | if (BTRFS_I(inode)->last_trans == root->fs_info->generation) |
3643 | set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, | 3655 | set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, |
3644 | &BTRFS_I(inode)->runtime_flags); | 3656 | &BTRFS_I(inode)->runtime_flags); |
3645 | 3657 | ||
3646 | inode->i_version = btrfs_inode_sequence(leaf, inode_item); | ||
3647 | inode->i_generation = BTRFS_I(inode)->generation; | ||
3648 | inode->i_rdev = 0; | ||
3649 | rdev = btrfs_inode_rdev(leaf, inode_item); | ||
3650 | |||
3651 | BTRFS_I(inode)->index_cnt = (u64)-1; | ||
3652 | BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); | ||
3653 | |||
3654 | cache_index: | ||
3655 | path->slots[0]++; | 3658 | path->slots[0]++; |
3656 | if (inode->i_nlink != 1 || | 3659 | if (inode->i_nlink != 1 || |
3657 | path->slots[0] >= btrfs_header_nritems(leaf)) | 3660 | path->slots[0] >= btrfs_header_nritems(leaf)) |