diff mbox series

[1/2] btrfs: fix nowait buffered write returning -ENOSPC

Message ID 4a8c46c2152ba9ab49e8002b66441354611c7c39.1667392727.git.fdmanana@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs: fixes for nowait buffered writes | expand

Commit Message

Filipe Manana Nov. 2, 2022, 12:46 p.m. UTC
From: Filipe Manana <fdmanana@suse.com>

If we are doing a buffered write in NOWAIT context and we can't reserve
metadata space due to -ENOSPC, then we should return -EAGAIN so that we
retry the write in a context allowed to block and do metadata reservation
with flushing, which might succeed this time due to the allowed flushing.

Returning -ENOSPC while in NOWAIT context simply makes some writes fail
with -ENOSPC when they would likely succeed after switching from NOWAIT
context to blocking context. That is unexpected behaviour and even fio
complains about it with a warning like this:

  fio: io_u error on file /mnt/sdi/task_0.0.0: No space left on device: write offset=1535705088, buflen=65536
  fio: pid=592630, err=28/file:io_u.c:1846, func=io_u error, error=No space left on device

The fio's job config is this:

   [global]
   bs=64K
   ioengine=io_uring
   iodepth=1
   size=2236962133
   nr_files=1
   filesize=2236962133
   direct=0
   runtime=10
   fallocate=posix
   io_size=2236962133
   group_reporting
   time_based

   [task_0]
   rw=randwrite
   directory=/mnt/sdi
   numjobs=4

So fix this by returning -EAGAIN if we are in NOWAIT context and the
metadata reservation failed with -ENOSPC.

Fixes: 304e45acdb8f ("btrfs: plumb NOWAIT through the write path")
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/file.c | 3 +++
 1 file changed, 3 insertions(+)
diff mbox series

Patch

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index b7855f794ba6..75d4d0bc9d8f 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1286,6 +1286,9 @@  static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
 						write_bytes);
 			else
 				btrfs_check_nocow_unlock(BTRFS_I(inode));
+
+			if (nowait && ret == -ENOSPC)
+				ret = -EAGAIN;
 			break;
 		}