Commit 0c0ef4bc authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason

Btrfs: abort the transaction if we fail to update the free space cache inode

Our gluster boxes were hitting a problem where they'd run out of space when
updating the block group cache and therefore wouldn't be able to update the free
space inode.  This is a problem because this is how we invalidate the cache and
protect ourselves from errors further down the stack, so if this fails we have
to abort the transaction so we make sure we don't end up with stale free space
cache.  Thanks,
Signed-off-by: default avatarJosef Bacik <jbacik@fb.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent 4d884fce
...@@ -3208,6 +3208,8 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, ...@@ -3208,6 +3208,8 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group,
return 0; return 0;
} }
if (trans->aborted)
return 0;
again: again:
inode = lookup_free_space_inode(root, block_group, path); inode = lookup_free_space_inode(root, block_group, path);
if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) {
...@@ -3243,6 +3245,20 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, ...@@ -3243,6 +3245,20 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group,
*/ */
BTRFS_I(inode)->generation = 0; BTRFS_I(inode)->generation = 0;
ret = btrfs_update_inode(trans, root, inode); ret = btrfs_update_inode(trans, root, inode);
if (ret) {
/*
* So theoretically we could recover from this, simply set the
* super cache generation to 0 so we know to invalidate the
* cache, but then we'd have to keep track of the block groups
* that fail this way so we know we _have_ to reset this cache
* before the next commit or risk reading stale cache. So to
* limit our exposure to horrible edge cases lets just abort the
* transaction, this only happens in really bad situations
* anyway.
*/
btrfs_abort_transaction(trans, root, ret);
goto out_put;
}
WARN_ON(ret); WARN_ON(ret);
if (i_size_read(inode) > 0) { if (i_size_read(inode) > 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment