Btrfs: fix a bug of writting free space cache during balance
authorLiu Bo <liubo2009@cn.fujitsu.com>
Fri, 6 Jul 2012 09:31:34 +0000 (03:31 -0600)
committerChris Mason <chris.mason@fusionio.com>
Mon, 23 Jul 2012 20:28:02 +0000 (16:28 -0400)
commitcf7c1ef6e1fe05864369f59dd516e816b11de7d0
tree53284520447b2d62cd221e76b77a28b5394a7cac
parent067893842341e7b7487062367ecfaa46c97505e0
Btrfs: fix a bug of writting free space cache during balance

Here is the whole story:
1)
A free space cache consists of two parts:
o  free space cache inode, which is special becase it's stored in root tree.
o  free space info, which is stored as the above inode's file data.

But we only build up another new inode and does not flush its free space info
onto disk when we _clear and setup_ free space cache, and this ends up with
that the block group cache's cache_state remains DC_SETUP instead of DC_WRITTEN.

And holding DC_SETUP means that we will not truncate this free space cache inode,
which means the disk offset of its file extent will remain _unchanged_ at least
until next transaction finishes committing itself.

2)
We can set a block group readonly when we relocate the block group.

However,
if the readonly block group covers the disk offset where our free space cache
inode is going to write, it will force the free space cache inode into
cow_file_range() and it'll end up hitting a BUG_ON.

3)
Due to the above analysis, we fix this bug by adding the missing dirty flag.

4)
However, it's not over, there is still another case, nospace_cache.

With nospace_cache, we do not want to set dirty flag, instead we just truncate
free space cache inode and bail out with setting cache state DC_WRITTEN.

We can benifit from it since it saves us another 'pre-allocation' part which
usually costs a lot.

Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
fs/btrfs/extent-tree.c