@@ -3705,7 +3705,8 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
* without delay
*/
if (!btrfs_is_free_space_inode(inode)
- && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) {
+ && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID
+ && !trans->log_replay) {
btrfs_update_root_times(trans, root);
ret = btrfs_delayed_update_inode(trans, root, inode);
@@ -486,6 +486,7 @@ again:
h->allocating_chunk = false;
h->reloc_reserved = false;
h->sync = false;
+ h->log_replay = false;
INIT_LIST_HEAD(&h->qgroup_ref_list);
INIT_LIST_HEAD(&h->new_bgs);
@@ -97,6 +97,7 @@ struct btrfs_trans_handle {
bool allocating_chunk;
bool reloc_reserved;
bool sync;
+ bool log_replay;
unsigned int type;
/*
* this root is only needed to validate that the root passed to
@@ -4353,6 +4353,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
ret = PTR_ERR(trans);
goto error;
}
+ trans->log_replay = true;
wc.trans = trans;
wc.pin = 1;
When doing log replay we may have to update inodes, which traditionally goes through our delayed inode stuff. This will try to move space over from the trans handle, but we don't reserve space in our trans handle on replay since we don't know how much we will need, so instead we try to flush. But because we have a trans handle open we won't flush anything, so if we are out of reserve space we will simply return ENOSPC. Since we know that if an operation made it into the log then we definitely had space before the box bought the farm then we don't need to worry about doing this space reservation. Just set a flag saying we are doing log replay and update the tree directly and bypass the reservation code altogether. This will keep us from ENOSP'ing during log replay. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com> --- fs/btrfs/inode.c | 3 ++- fs/btrfs/transaction.c | 1 + fs/btrfs/transaction.h | 1 + fs/btrfs/tree-log.c | 1 + 4 files changed, 5 insertions(+), 1 deletion(-)