diff mbox series

[2/4] Btrfs: fix failure of RWF_NOWAIT write into prealloc extent beyond eof

Message ID 20200615174858.14888-1-fdmanana@kernel.org (mailing list archive)
State New, archived
Headers show
Series [1/4] Btrfs: fix hang on snapshot creation after RWF_NOWAIT write | expand

Commit Message

Filipe Manana June 15, 2020, 5:48 p.m. UTC
From: Filipe Manana <fdmanana@suse.com>

If we attempt to write to prealloc extent located after eof using a
RWF_NOWAIT write, we always fail with -EAGAIN.

We do actually check if we have an allocated extent for the write at
the start of btrfs_file_write_iter() through a call to check_can_nocow(),
but later when we go into the actual direct IO write path we simply
return -EAGAIN if the write starts at or beyond EOF.

Trivial to reproduce:

  $ mkfs.btrfs -f /dev/sdb
  $ mount /dev/sdb /mnt

  $ touch /mnt/foo
  $ chattr +C /mnt/foo

  $ xfs_io -d -c "pwrite -S 0xab 0 64K" /mnt/foo
  wrote 65536/65536 bytes at offset 0
  64 KiB, 16 ops; 0.0004 sec (135.575 MiB/sec and 34707.1584 ops/sec)

  $ xfs_io -c "falloc -k 64K 1M" /mnt/foo

  $ xfs_io -d -c "pwrite -N -V 1 -S 0xfe -b 64K 64K 64K" /mnt/foo
  pwrite: Resource temporarily unavailable

On xfs and ext4 the write succeeds, as expected.

Fix this by removing the wrong check at btrfs_direct_IO().

Fixes: edf064e7c6fec3 ("btrfs: nowait aio support")
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/inode.c | 3 ---
 1 file changed, 3 deletions(-)

Comments

Josef Bacik June 16, 2020, 7:27 p.m. UTC | #1
On 6/15/20 1:48 PM, fdmanana@kernel.org wrote:
> From: Filipe Manana <fdmanana@suse.com>
> 
> If we attempt to write to prealloc extent located after eof using a
> RWF_NOWAIT write, we always fail with -EAGAIN.
> 
> We do actually check if we have an allocated extent for the write at
> the start of btrfs_file_write_iter() through a call to check_can_nocow(),
> but later when we go into the actual direct IO write path we simply
> return -EAGAIN if the write starts at or beyond EOF.
> 
> Trivial to reproduce:
> 
>    $ mkfs.btrfs -f /dev/sdb
>    $ mount /dev/sdb /mnt
> 
>    $ touch /mnt/foo
>    $ chattr +C /mnt/foo
> 
>    $ xfs_io -d -c "pwrite -S 0xab 0 64K" /mnt/foo
>    wrote 65536/65536 bytes at offset 0
>    64 KiB, 16 ops; 0.0004 sec (135.575 MiB/sec and 34707.1584 ops/sec)
> 
>    $ xfs_io -c "falloc -k 64K 1M" /mnt/foo
> 
>    $ xfs_io -d -c "pwrite -N -V 1 -S 0xfe -b 64K 64K 64K" /mnt/foo
>    pwrite: Resource temporarily unavailable
> 
> On xfs and ext4 the write succeeds, as expected.
> 
> Fix this by removing the wrong check at btrfs_direct_IO().
> 
> Fixes: edf064e7c6fec3 ("btrfs: nowait aio support")
> Signed-off-by: Filipe Manana <fdmanana@suse.com>

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

Thanks,

Josef
diff mbox series

Patch

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 62b49d2db928..cfa863d2d97c 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7889,9 +7889,6 @@  static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 			dio_data.overwrite = 1;
 			inode_unlock(inode);
 			relock = true;
-		} else if (iocb->ki_flags & IOCB_NOWAIT) {
-			ret = -EAGAIN;
-			goto out;
 		}
 		ret = btrfs_delalloc_reserve_space(inode, &data_reserved,
 						   offset, count);