aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-10-25 05:33:36 -0400
committerChris Mason <chris.mason@fusionio.com>2013-11-11 22:08:49 -0500
commit9dced186f934648bb7796ad3301cfc2563e2ad6e (patch)
tree8a982bcff082d94b639a57fb35b4e0b10c892edf /fs/btrfs/extent-tree.c
parent9e6a0c52b74b2d63a6cdb09cec5eaf66038b218f (diff)
Btrfs: fix the free space write out failure when there is no data space
After running space balance on a new fs, the fs check program outputed the following warning message: free space inode generation (0) did not match free space cache generation (20) Steps to reproduce: # mkfs.btrfs -f <dev> # mount <dev> <mnt> # btrfs balance start <mnt> # umount <mnt> # btrfs check <dev> It was because there was no data space after the space balance, and the free space write out task didn't try to allocate a new data chunk for the free space inode when doing the reservation. So the data space reservation failed, and in order to tell the free space loader that this free space inode could not be trusted, the generation of the free space inode wasn't updated. Then the check program found this problem and outputed the above message. But in fact, it is safe that we try to allocate a new data chunk when we find the data space is not enough. The patch fixes the above problem by this way. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 4595a65db729..3aa52701d04a 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3621,10 +3621,9 @@ int btrfs_check_data_free_space(struct inode *inode, u64 bytes)
3621 /* make sure bytes are sectorsize aligned */ 3621 /* make sure bytes are sectorsize aligned */
3622 bytes = ALIGN(bytes, root->sectorsize); 3622 bytes = ALIGN(bytes, root->sectorsize);
3623 3623
3624 if (root == root->fs_info->tree_root || 3624 if (btrfs_is_free_space_inode(inode)) {
3625 BTRFS_I(inode)->location.objectid == BTRFS_FREE_INO_OBJECTID) {
3626 alloc_chunk = 0;
3627 committed = 1; 3625 committed = 1;
3626 ASSERT(current->journal_info);
3628 } 3627 }
3629 3628
3630 data_sinfo = fs_info->data_sinfo; 3629 data_sinfo = fs_info->data_sinfo;
@@ -3652,6 +3651,16 @@ again:
3652 spin_unlock(&data_sinfo->lock); 3651 spin_unlock(&data_sinfo->lock);
3653alloc: 3652alloc:
3654 alloc_target = btrfs_get_alloc_profile(root, 1); 3653 alloc_target = btrfs_get_alloc_profile(root, 1);
3654 /*
3655 * It is ugly that we don't call nolock join
3656 * transaction for the free space inode case here.
3657 * But it is safe because we only do the data space
3658 * reservation for the free space cache in the
3659 * transaction context, the common join transaction
3660 * just increase the counter of the current transaction
3661 * handler, doesn't try to acquire the trans_lock of
3662 * the fs.
3663 */
3655 trans = btrfs_join_transaction(root); 3664 trans = btrfs_join_transaction(root);
3656 if (IS_ERR(trans)) 3665 if (IS_ERR(trans))
3657 return PTR_ERR(trans); 3666 return PTR_ERR(trans);