diff mbox series

btrfs: do not BUG_ON() on ENOMEM when dropping extent items for a range

Message ID 59ccc7b41be79e5c3b0f39ad5da6591554927af7.1669647978.git.fdmanana@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs: do not BUG_ON() on ENOMEM when dropping extent items for a range | expand

Commit Message

Filipe Manana Nov. 28, 2022, 3:07 p.m. UTC
From: Filipe Manana <fdmanana@suse.com>

If we get -ENOMEM while dropping file extent items in a given range, at
btrfs_drop_extents(), due to failure to allocate memory when attempting to
increment the reference count for an extent or drop the reference count,
we handle it with a BUG_ON(). This is excessive, instead we can simply
abort the transaction and return the error to the caller. In fact most
callers of btrfs_drop_extents(), directly or indirectly, already abort
the transaction if btrfs_drop_extents() returns any error.

Also, we already have error paths at btrfs_drop_extents() that may return
-ENOMEM and in those cases we abort the transaction, like for example
anything that changes the b+tree may return -ENOMEM due to a failure to
allocate a new extent buffer when COWing an existing extent buffer, such
as a call to btrfs_duplicate_item() for example.

So replace the BUG_ON() calls with proper logic to abort the transaction
and return the error.

Reported-by: syzbot+0b1fb6b0108c27419f9f@syzkaller.appspotmail.com
Link: https://lore.kernel.org/linux-btrfs/00000000000089773e05ee4b9cb4@google.com/
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/file.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

Comments

Josef Bacik Nov. 28, 2022, 3:55 p.m. UTC | #1
On Mon, Nov 28, 2022 at 03:07:30PM +0000, fdmanana@kernel.org wrote:
> From: Filipe Manana <fdmanana@suse.com>
> 
> If we get -ENOMEM while dropping file extent items in a given range, at
> btrfs_drop_extents(), due to failure to allocate memory when attempting to
> increment the reference count for an extent or drop the reference count,
> we handle it with a BUG_ON(). This is excessive, instead we can simply
> abort the transaction and return the error to the caller. In fact most
> callers of btrfs_drop_extents(), directly or indirectly, already abort
> the transaction if btrfs_drop_extents() returns any error.
> 
> Also, we already have error paths at btrfs_drop_extents() that may return
> -ENOMEM and in those cases we abort the transaction, like for example
> anything that changes the b+tree may return -ENOMEM due to a failure to
> allocate a new extent buffer when COWing an existing extent buffer, such
> as a call to btrfs_duplicate_item() for example.
> 
> So replace the BUG_ON() calls with proper logic to abort the transaction
> and return the error.
> 
> Reported-by: syzbot+0b1fb6b0108c27419f9f@syzkaller.appspotmail.com
> Link: https://lore.kernel.org/linux-btrfs/00000000000089773e05ee4b9cb4@google.com/
> Signed-off-by: Filipe Manana <fdmanana@suse.com>

Reviewed-by: Josef Bacik <josef@toxicpanda.com>

Thanks,

Josef
David Sterba Nov. 28, 2022, 4:53 p.m. UTC | #2
On Mon, Nov 28, 2022 at 03:07:30PM +0000, fdmanana@kernel.org wrote:
> From: Filipe Manana <fdmanana@suse.com>
> 
> If we get -ENOMEM while dropping file extent items in a given range, at
> btrfs_drop_extents(), due to failure to allocate memory when attempting to
> increment the reference count for an extent or drop the reference count,
> we handle it with a BUG_ON(). This is excessive, instead we can simply
> abort the transaction and return the error to the caller. In fact most
> callers of btrfs_drop_extents(), directly or indirectly, already abort
> the transaction if btrfs_drop_extents() returns any error.
> 
> Also, we already have error paths at btrfs_drop_extents() that may return
> -ENOMEM and in those cases we abort the transaction, like for example
> anything that changes the b+tree may return -ENOMEM due to a failure to
> allocate a new extent buffer when COWing an existing extent buffer, such
> as a call to btrfs_duplicate_item() for example.
> 
> So replace the BUG_ON() calls with proper logic to abort the transaction
> and return the error.
> 
> Reported-by: syzbot+0b1fb6b0108c27419f9f@syzkaller.appspotmail.com
> Link: https://lore.kernel.org/linux-btrfs/00000000000089773e05ee4b9cb4@google.com/
> Signed-off-by: Filipe Manana <fdmanana@suse.com>

Added to misc-next, thanks.
diff mbox series

Patch

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 448b143a5cb2..91b00eb2440e 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -380,7 +380,10 @@  int btrfs_drop_extents(struct btrfs_trans_handle *trans,
 						args->start - extent_offset,
 						0, false);
 				ret = btrfs_inc_extent_ref(trans, &ref);
-				BUG_ON(ret); /* -ENOMEM */
+				if (ret) {
+					btrfs_abort_transaction(trans, ret);
+					break;
+				}
 			}
 			key.offset = args->start;
 		}
@@ -467,7 +470,10 @@  int btrfs_drop_extents(struct btrfs_trans_handle *trans,
 						key.offset - extent_offset, 0,
 						false);
 				ret = btrfs_free_extent(trans, &ref);
-				BUG_ON(ret); /* -ENOMEM */
+				if (ret) {
+					btrfs_abort_transaction(trans, ret);
+					break;
+				}
 				args->bytes_found += extent_end - key.offset;
 			}