| From 93149f6169d427ee6f682b265c20bae8d8bb71a5 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 10 Aug 2020 17:31:16 -0400 |
| Subject: btrfs: check the right error variable in btrfs_del_dir_entries_in_log |
| |
| From: Josef Bacik <josef@toxicpanda.com> |
| |
| [ Upstream commit fb2fecbad50964b9f27a3b182e74e437b40753ef ] |
| |
| With my new locking code dbench is so much faster that I tripped over a |
| transaction abort from ENOSPC. This turned out to be because |
| btrfs_del_dir_entries_in_log was checking for ret == -ENOSPC, but this |
| function sets err on error, and returns err. So instead of properly |
| marking the inode as needing a full commit, we were returning -ENOSPC |
| and aborting in __btrfs_unlink_inode. Fix this by checking the proper |
| variable so that we return the correct thing in the case of ENOSPC. |
| |
| The ENOENT needs to be checked, because btrfs_lookup_dir_item_index() |
| can return -ENOENT if the dir item isn't in the tree log (which would |
| happen if we hadn't fsync'ed this guy). We actually handle that case in |
| __btrfs_unlink_inode, so it's an expected error to get back. |
| |
| Fixes: 4a500fd178c8 ("Btrfs: Metadata ENOSPC handling for tree log") |
| CC: stable@vger.kernel.org # 4.4+ |
| Reviewed-by: Filipe Manana <fdmanana@suse.com> |
| Signed-off-by: Josef Bacik <josef@toxicpanda.com> |
| Reviewed-by: David Sterba <dsterba@suse.com> |
| [ add note and comment about ENOENT ] |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/btrfs/tree-log.c | 10 ++++++---- |
| 1 file changed, 6 insertions(+), 4 deletions(-) |
| |
| diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c |
| index c28ac9c464251..5bd1758f57b64 100644 |
| --- a/fs/btrfs/tree-log.c |
| +++ b/fs/btrfs/tree-log.c |
| @@ -3191,11 +3191,13 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, |
| btrfs_free_path(path); |
| out_unlock: |
| mutex_unlock(&BTRFS_I(dir)->log_mutex); |
| - if (ret == -ENOSPC) { |
| + if (err == -ENOSPC) { |
| btrfs_set_log_full_commit(root->fs_info, trans); |
| - ret = 0; |
| - } else if (ret < 0) |
| - btrfs_abort_transaction(trans, ret); |
| + err = 0; |
| + } else if (err < 0 && err != -ENOENT) { |
| + /* ENOENT can be returned if the entry hasn't been fsynced yet */ |
| + btrfs_abort_transaction(trans, err); |
| + } |
| |
| btrfs_end_log_trans(root); |
| |
| -- |
| 2.25.1 |
| |