Merge tag 'landlock-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic...
[linux-2.6-block.git] / block / fops.c
index 58d0aebc7313a838d4d895fd73f7c383290d75da..555b1b9ecd2cb9d4df15dac1d02a17caaea308b3 100644 (file)
@@ -54,7 +54,7 @@ static bool blkdev_dio_unaligned(struct block_device *bdev, loff_t pos,
 static ssize_t __blkdev_direct_IO_simple(struct kiocb *iocb,
                struct iov_iter *iter, unsigned int nr_pages)
 {
-       struct block_device *bdev = iocb->ki_filp->private_data;
+       struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
        struct bio_vec inline_vecs[DIO_INLINE_BIO_VECS], *vecs;
        loff_t pos = iocb->ki_pos;
        bool should_dirty = false;
@@ -170,7 +170,7 @@ static void blkdev_bio_end_io(struct bio *bio)
 static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
                unsigned int nr_pages)
 {
-       struct block_device *bdev = iocb->ki_filp->private_data;
+       struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
        struct blk_plug plug;
        struct blkdev_dio *dio;
        struct bio *bio;
@@ -310,7 +310,7 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb,
                                        struct iov_iter *iter,
                                        unsigned int nr_pages)
 {
-       struct block_device *bdev = iocb->ki_filp->private_data;
+       struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
        bool is_read = iov_iter_rw(iter) == READ;
        blk_opf_t opf = is_read ? REQ_OP_READ : dio_bio_write_op(iocb);
        struct blkdev_dio *dio;
@@ -451,7 +451,7 @@ static loff_t blkdev_llseek(struct file *file, loff_t offset, int whence)
 static int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
                int datasync)
 {
-       struct block_device *bdev = filp->private_data;
+       struct block_device *bdev = I_BDEV(filp->f_mapping->host);
        int error;
 
        error = file_write_and_wait_range(filp, start, end);
@@ -470,6 +470,30 @@ static int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
        return error;
 }
 
+blk_mode_t file_to_blk_mode(struct file *file)
+{
+       blk_mode_t mode = 0;
+
+       if (file->f_mode & FMODE_READ)
+               mode |= BLK_OPEN_READ;
+       if (file->f_mode & FMODE_WRITE)
+               mode |= BLK_OPEN_WRITE;
+       if (file->private_data)
+               mode |= BLK_OPEN_EXCL;
+       if (file->f_flags & O_NDELAY)
+               mode |= BLK_OPEN_NDELAY;
+
+       /*
+        * If all bits in O_ACCMODE set (aka O_RDWR | O_WRONLY), the floppy
+        * driver has historically allowed ioctls as if the file was opened for
+        * writing, but does not allow and actual reads or writes.
+        */
+       if ((file->f_flags & O_ACCMODE) == (O_RDWR | O_WRONLY))
+               mode |= BLK_OPEN_WRITE_IOCTL;
+
+       return mode;
+}
+
 static int blkdev_open(struct inode *inode, struct file *filp)
 {
        struct block_device *bdev;
@@ -481,30 +505,31 @@ static int blkdev_open(struct inode *inode, struct file *filp)
         * during an unstable branch.
         */
        filp->f_flags |= O_LARGEFILE;
-       filp->f_mode |= FMODE_NOWAIT | FMODE_BUF_RASYNC;
+       filp->f_mode |= FMODE_BUF_RASYNC;
 
-       if (filp->f_flags & O_NDELAY)
-               filp->f_mode |= FMODE_NDELAY;
+       /*
+        * Use the file private data to store the holder for exclusive openes.
+        * file_to_blk_mode relies on it being present to set BLK_OPEN_EXCL.
+        */
        if (filp->f_flags & O_EXCL)
-               filp->f_mode |= FMODE_EXCL;
-       if ((filp->f_flags & O_ACCMODE) == 3)
-               filp->f_mode |= FMODE_WRITE_IOCTL;
+               filp->private_data = filp;
 
-       bdev = blkdev_get_by_dev(inode->i_rdev, filp->f_mode, filp);
+       bdev = blkdev_get_by_dev(inode->i_rdev, file_to_blk_mode(filp),
+                                filp->private_data, NULL);
        if (IS_ERR(bdev))
                return PTR_ERR(bdev);
 
-       filp->private_data = bdev;
+       if (bdev_nowait(bdev))
+               filp->f_mode |= FMODE_NOWAIT;
+
        filp->f_mapping = bdev->bd_inode->i_mapping;
        filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping);
        return 0;
 }
 
-static int blkdev_close(struct inode *inode, struct file *filp)
+static int blkdev_release(struct inode *inode, struct file *filp)
 {
-       struct block_device *bdev = filp->private_data;
-
-       blkdev_put(bdev, filp->f_mode);
+       blkdev_put(I_BDEV(filp->f_mapping->host), filp->private_data);
        return 0;
 }
 
@@ -517,10 +542,9 @@ static int blkdev_close(struct inode *inode, struct file *filp)
  */
 static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
-       struct block_device *bdev = iocb->ki_filp->private_data;
+       struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
        struct inode *bd_inode = bdev->bd_inode;
        loff_t size = bdev_nr_bytes(bdev);
-       struct blk_plug plug;
        size_t shorted = 0;
        ssize_t ret;
 
@@ -545,18 +569,16 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
                iov_iter_truncate(from, size);
        }
 
-       blk_start_plug(&plug);
        ret = __generic_file_write_iter(iocb, from);
        if (ret > 0)
                ret = generic_write_sync(iocb, ret);
        iov_iter_reexpand(from, iov_iter_count(from) + shorted);
-       blk_finish_plug(&plug);
        return ret;
 }
 
 static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
-       struct block_device *bdev = iocb->ki_filp->private_data;
+       struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
        loff_t size = bdev_nr_bytes(bdev);
        loff_t pos = iocb->ki_pos;
        size_t shorted = 0;
@@ -649,7 +671,7 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start,
        filemap_invalidate_lock(inode->i_mapping);
 
        /* Invalidate the page cache, including dirty pages. */
-       error = truncate_bdev_range(bdev, file->f_mode, start, end);
+       error = truncate_bdev_range(bdev, file_to_blk_mode(file), start, end);
        if (error)
                goto fail;
 
@@ -690,7 +712,7 @@ static int blkdev_mmap(struct file *file, struct vm_area_struct *vma)
 
 const struct file_operations def_blk_fops = {
        .open           = blkdev_open,
-       .release        = blkdev_close,
+       .release        = blkdev_release,
        .llseek         = blkdev_llseek,
        .read_iter      = blkdev_read_iter,
        .write_iter     = blkdev_write_iter,
@@ -701,7 +723,7 @@ const struct file_operations def_blk_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_blkdev_ioctl,
 #endif
-       .splice_read    = generic_file_splice_read,
+       .splice_read    = filemap_splice_read,
        .splice_write   = iter_file_splice_write,
        .fallocate      = blkdev_fallocate,
 };