aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilipe Manana2020-06-15 12:48:58 -0500
committerSasha Levin2020-06-30 22:17:16 -0500
commite4b2fd3008058befb3fa8722a7dc2df4f54f40c2 (patch)
tree9177f572a0f65182c047fb8e29c2d3cc4b2b37a1
parenta092d4548a29d69c265c052a22dfb1a58c5a5976 (diff)
downloadkernel-e4b2fd3008058befb3fa8722a7dc2df4f54f40c2.tar.gz
kernel-e4b2fd3008058befb3fa8722a7dc2df4f54f40c2.tar.xz
kernel-e4b2fd3008058befb3fa8722a7dc2df4f54f40c2.zip
btrfs: fix failure of RWF_NOWAIT write into prealloc extent beyond eof
commit 4b1946284dd6641afdb9457101056d9e6ee6204c upstream. 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") CC: stable@vger.kernel.org # 4.14+ Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/btrfs/inode.c3
1 files changed, 0 insertions, 3 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 7ffb15b473a7..8dd2702ce859 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -8656,9 +8656,6 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
8656 dio_data.overwrite = 1; 8656 dio_data.overwrite = 1;
8657 inode_unlock(inode); 8657 inode_unlock(inode);
8658 relock = true; 8658 relock = true;
8659 } else if (iocb->ki_flags & IOCB_NOWAIT) {
8660 ret = -EAGAIN;
8661 goto out;
8662 } 8659 }
8663 ret = btrfs_delalloc_reserve_space(inode, &data_reserved, 8660 ret = btrfs_delalloc_reserve_space(inode, &data_reserved,
8664 offset, count); 8661 offset, count);