]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/block_dev.c
fs/block_dev.c: skip rw_page if bdev has integrity
[karo-tx-linux.git] / fs / block_dev.c
index 975266be67d319aa019a48e94cfda0a3ca8ce1e0..054ef1bbb821b403f47ab8bd02c7960dac73f6ae 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/namei.h>
 #include <linux/log2.h>
 #include <linux/cleancache.h>
-#include <linux/aio.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -147,15 +146,14 @@ blkdev_get_block(struct inode *inode, sector_t iblock,
 }
 
 static ssize_t
-blkdev_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
-                       loff_t offset)
+blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
 
-       return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iter,
-                                   offset, blkdev_get_block,
-                                   NULL, NULL, 0);
+       return __blockdev_direct_IO(iocb, inode, I_BDEV(inode), iter, offset,
+                                   blkdev_get_block, NULL, NULL,
+                                   DIO_SKIP_DIO_COUNT);
 }
 
 int __sync_blockdev(struct block_device *bdev, int wait)
@@ -378,7 +376,7 @@ int bdev_read_page(struct block_device *bdev, sector_t sector,
                        struct page *page)
 {
        const struct block_device_operations *ops = bdev->bd_disk->fops;
-       if (!ops->rw_page)
+       if (!ops->rw_page || bdev_get_integrity(bdev))
                return -EOPNOTSUPP;
        return ops->rw_page(bdev, sector + get_start_sect(bdev), page, READ);
 }
@@ -409,7 +407,7 @@ int bdev_write_page(struct block_device *bdev, sector_t sector,
        int result;
        int rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE;
        const struct block_device_operations *ops = bdev->bd_disk->fops;
-       if (!ops->rw_page)
+       if (!ops->rw_page || bdev_get_integrity(bdev))
                return -EOPNOTSUPP;
        set_page_writeback(page);
        result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, rw);
@@ -1598,9 +1596,22 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
        struct file *file = iocb->ki_filp;
+       struct inode *bd_inode = file->f_mapping->host;
+       loff_t size = i_size_read(bd_inode);
        struct blk_plug plug;
        ssize_t ret;
 
+       if (bdev_read_only(I_BDEV(bd_inode)))
+               return -EPERM;
+
+       if (!iov_iter_count(from))
+               return 0;
+
+       if (iocb->ki_pos >= size)
+               return -ENOSPC;
+
+       iov_iter_truncate(from, size - iocb->ki_pos);
+
        blk_start_plug(&plug);
        ret = __generic_file_write_iter(iocb, from);
        if (ret > 0) {
@@ -1660,8 +1671,6 @@ const struct file_operations def_blk_fops = {
        .open           = blkdev_open,
        .release        = blkdev_close,
        .llseek         = block_llseek,
-       .read           = new_sync_read,
-       .write          = new_sync_write,
        .read_iter      = blkdev_read_iter,
        .write_iter     = blkdev_write_iter,
        .mmap           = generic_file_mmap,
@@ -1708,7 +1717,7 @@ struct block_device *lookup_bdev(const char *pathname)
        if (error)
                return ERR_PTR(error);
 
-       inode = path.dentry->d_inode;
+       inode = d_backing_inode(path.dentry);
        error = -ENOTBLK;
        if (!S_ISBLK(inode->i_mode))
                goto fail;