On Tue, Apr 07, 2020 at 11:38:49AM +0100, fdmanana@xxxxxxxxxx wrote:
> From: Filipe Manana <fdmanana@xxxxxxxx>
>
> Whenever we add a ticket to a space_info object we increment the object's
> reclaim_size counter witht the ticket's bytes, and we decrement it with
> the corresponding amount only when we are able to grant the requested
> space to the ticket. When we are not able to grant the space to a ticket,
> or when the ticket is removed due to a signal (e.g. an application has
> received sigterm from the terminal) we never decrement the counter with
> the corresponding bytes from the ticket. This leak can result in the
> space reclaim code to later do much more work than necessary. So fix it
> by decrementing the counter when those two cases happen as well.
>
> Fixes: db161806dc5615 ("btrfs: account ticket size at add/delete time")
> Signed-off-by: Filipe Manana <fdmanana@xxxxxxxx>
There's a minor conflict with Josef's patch "btrfs: run
btrfs_try_granting_tickets if a priority ticket fails" so I'll apply
yours to misc-5.7 as it's a regression fix.
> @@ -1121,7 +1129,7 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info,
> * either the async reclaim job deletes the ticket from the list
> * or we delete it ourselves at wait_reserve_ticket().
> */
> - list_del_init(&ticket->list);
> + remove_ticket(space_info, ticket);
> if (!ret)
> ret = -ENOSPC;
> }
The conflicting hunk is:
--- a/fs/btrfs/space-info.c
+++ b/fs/btrfs/space-info.c
@@ -1156,11 +1156,17 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info,
ret = ticket->error;
if (ticket->bytes || ticket->error) {
/*
- * Need to delete here for priority tickets. For regular tickets
- * either the async reclaim job deletes the ticket from the list
- * or we delete it ourselves at wait_reserve_ticket().
+ * We were a priority ticket, so we need to delete ourselves
+ * from the list. Because we could have other priority tickets
+ * behind us that require less space, run
+ * btrfs_try_granting_tickets() to see if their reservations can
+ * now be made.
*/
- list_del_init(&ticket->list);
+ if (!list_empty(&ticket->list)) {
+ list_del_init(&ticket->list);
+ btrfs_try_granting_tickets(fs_info, space_info);
+ }
+
if (!ret)
ret = -ENOSPC;
}
---
so I assume the correct fixup is to replace list_del_init with
remove_ticket.