]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
f2fs: allow wrong configured dio to buffered write
authorJaegeuk Kim <jaegeuk@kernel.org>
Sat, 30 Jun 2018 01:55:12 +0000 (18:55 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Sun, 15 Jul 2018 03:14:04 +0000 (12:14 +0900)
This fixes to support dio having unaligned buffers as buffered writes.

xfs_io -f -d -c "pwrite 0 512" $testfile
 -> okay

xfs_io -f -d -c "pwrite 1 512" $testfile
 -> EINVAL

Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/data.c

index 8f931d699287af894e0101f7aedd4f4f2ef75d72..5e53d210e22275ad4408759f0775464305f686dc 100644 (file)
@@ -2371,14 +2371,20 @@ unlock_out:
 static int check_direct_IO(struct inode *inode, struct iov_iter *iter,
                           loff_t offset)
 {
-       unsigned blocksize_mask = inode->i_sb->s_blocksize - 1;
-
-       if (offset & blocksize_mask)
-               return -EINVAL;
-
-       if (iov_iter_alignment(iter) & blocksize_mask)
-               return -EINVAL;
-
+       unsigned i_blkbits = READ_ONCE(inode->i_blkbits);
+       unsigned blkbits = i_blkbits;
+       unsigned blocksize_mask = (1 << blkbits) - 1;
+       unsigned long align = offset | iov_iter_alignment(iter);
+       struct block_device *bdev = inode->i_sb->s_bdev;
+
+       if (align & blocksize_mask) {
+               if (bdev)
+                       blkbits = blksize_bits(bdev_logical_block_size(bdev));
+               blocksize_mask = (1 << blkbits) - 1;
+               if (align & blocksize_mask)
+                       return -EINVAL;
+               return 1;
+       }
        return 0;
 }
 
@@ -2396,7 +2402,7 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 
        err = check_direct_IO(inode, iter, offset);
        if (err)
-               return err;
+               return err < 0 ? err : 0;
 
        if (f2fs_force_buffered_io(inode, rw))
                return 0;