• Liu Bo's avatar
    Btrfs: fix a bug of writting free space cache during balance · cf7c1ef6
    Liu Bo authored
    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: default avatarLiu Bo <liubo2009@cn.fujitsu.com>
    Signed-off-by: default avatarMiao Xie <miaox@cn.fujitsu.com>
    Signed-off-by: default avatarJosef Bacik <jbacik@fusionio.com>
    cf7c1ef6
extent-tree.c 214 KB