diff mbox series

[16/23] btrfs: serialize data reservations if we are flushing

Message ID 20200131223613.490779-17-josef@toxicpanda.com (mailing list archive)
State New, archived
Headers show
Series Convert data reservations to the ticketing infrastructure | expand

Commit Message

Josef Bacik Jan. 31, 2020, 10:36 p.m. UTC
Nikolay reported a problem where generic/371 would fail sometimes with a
slow drive.  The gist of the test is that we fallocate a file in
parallel with a pwrite of a different file.  These two files combined
are smaller than the file system, but sometimes the pwrite would ENOSPC.

A fair bit of investigation uncovered the fact that the fallocate
workload was racing in and grabbing the free space that the pwrite
workload was trying to free up so it could make its own reservation.
After a few loops of this eventually the pwrite workload would error out
with an ENOSPC.

We've had the same problem with metadata as well, and we serialized all
metadata allocations to satisfy this problem.  This wasn't usually a
problem with data because data reservations are more straightforward,
but obviously could still happen.

Fix this by not allowing reservations to occur if there are any pending
tickets waiting to be satisfied on the space info.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/space-info.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

Comments

Nikolay Borisov Feb. 3, 2020, 3:06 p.m. UTC | #1
On 1.02.20 г. 0:36 ч., Josef Bacik wrote:
> Nikolay reported a problem where generic/371 would fail sometimes with a
> slow drive.  The gist of the test is that we fallocate a file in
> parallel with a pwrite of a different file.  These two files combined
> are smaller than the file system, but sometimes the pwrite would ENOSPC.
> 
> A fair bit of investigation uncovered the fact that the fallocate
> workload was racing in and grabbing the free space that the pwrite
> workload was trying to free up so it could make its own reservation.
> After a few loops of this eventually the pwrite workload would error out
> with an ENOSPC.
> 
> We've had the same problem with metadata as well, and we serialized all
> metadata allocations to satisfy this problem.  This wasn't usually a
> problem with data because data reservations are more straightforward,
> but obviously could still happen.
> 
> Fix this by not allowing reservations to occur if there are any pending
> tickets waiting to be satisfied on the space info.
> 
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

Reviewed-by: Nikolay Borisov <nborisov@suse.com>
diff mbox series

Patch

diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c
index 43c5775bcbc6..97379524bac8 100644
--- a/fs/btrfs/space-info.c
+++ b/fs/btrfs/space-info.c
@@ -1154,13 +1154,17 @@  int btrfs_reserve_data_bytes(struct btrfs_fs_info *fs_info, u64 bytes,
 	struct btrfs_space_info *data_sinfo = fs_info->data_sinfo;
 	u64 used;
 	int ret = -ENOSPC;
+	bool pending_tickets;
 
 	ASSERT(!current->journal_info || flush != BTRFS_RESERVE_FLUSH_DATA);
 
 	spin_lock(&data_sinfo->lock);
 	used = btrfs_space_info_used(data_sinfo, true);
+	pending_tickets = !list_empty(&data_sinfo->tickets) ||
+		!list_empty(&data_sinfo->priority_tickets);
 
-	if (used + bytes > data_sinfo->total_bytes) {
+	if (pending_tickets ||
+	    used + bytes > data_sinfo->total_bytes) {
 		struct reserve_ticket ticket;
 
 		init_waitqueue_head(&ticket.wait);