diff options
author | Zach Brown <zab@redhat.com> | 2013-04-02 17:02:16 -0400 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2013-05-06 15:54:36 -0400 |
commit | d4e3991b9945906528c7abb627d759ea43f53bce (patch) | |
tree | 8ef759bd9b3348528c29bb0433c57eae921d6ad2 /fs/btrfs | |
parent | f63e0cca9174dd8b47380f61565ab7b921d6ac2c (diff) |
btrfs: abort unlink trans in missed error case
__btrfs_unlink_inode() aborts its transaction when it sees errors after
it removes the directory item. But it missed the case where
btrfs_del_dir_entries_in_log() returns an error. If this happens then
the unlink appears to fail but the items have been removed without
updating the directory size. The directory then has leaked bytes in
i_size and can never be removed.
Adding the missing transaction abort at least makes this failure
consistent with the other failure cases.
I noticed this while reading the code after someone on irc reported
having a directory with i_size but no entries. I tested it by forcing
btrfs_del_dir_entries_in_log() to return -ENOMEM.
Signed-off-by: Zach Brown <zab@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/inode.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c41637a1ed38..ca4051713633 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -3616,6 +3616,8 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans, | |||
3616 | dir, index); | 3616 | dir, index); |
3617 | if (ret == -ENOENT) | 3617 | if (ret == -ENOENT) |
3618 | ret = 0; | 3618 | ret = 0; |
3619 | else if (ret) | ||
3620 | btrfs_abort_transaction(trans, root, ret); | ||
3619 | err: | 3621 | err: |
3620 | btrfs_free_path(path); | 3622 | btrfs_free_path(path); |
3621 | if (ret) | 3623 | if (ret) |