Merge tag 'for-linus-4.3-rc0b-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[deliverable/linux.git] / fs / block_dev.c
index 4fe10f93db8a3e52ebbb5330e94b80ee92455e1d..22ea424ee741ea1a967676298e7877332fc324b2 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/namei.h>
 #include <linux/log2.h>
 #include <linux/cleancache.h>
+#include <linux/dax.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -152,6 +153,9 @@ 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;
 
+       if (IS_DAX(inode))
+               return dax_do_io(iocb, inode, iter, offset, blkdev_get_block,
+                               NULL, DIO_SKIP_DIO_COUNT);
        return __blockdev_direct_IO(iocb, inode, I_BDEV(inode), iter, offset,
                                    blkdev_get_block, NULL, NULL,
                                    DIO_SKIP_DIO_COUNT);
@@ -438,11 +442,17 @@ EXPORT_SYMBOL_GPL(bdev_write_page);
  * accessible at this address.
  */
 long bdev_direct_access(struct block_device *bdev, sector_t sector,
-                       void **addr, unsigned long *pfn, long size)
+                       void __pmem **addr, unsigned long *pfn, long size)
 {
        long avail;
        const struct block_device_operations *ops = bdev->bd_disk->fops;
 
+       /*
+        * The device driver is allowed to sleep, in order to make the
+        * memory directly accessible.
+        */
+       might_sleep();
+
        if (size < 0)
                return size;
        if (!ops->direct_access)
@@ -453,7 +463,7 @@ long bdev_direct_access(struct block_device *bdev, sector_t sector,
        sector += get_start_sect(bdev);
        if (sector % (PAGE_SIZE / 512))
                return -EINVAL;
-       avail = ops->direct_access(bdev, sector, addr, pfn, size);
+       avail = ops->direct_access(bdev, sector, addr, pfn);
        if (!avail)
                return -ERANGE;
        return min(avail, size);
@@ -1170,6 +1180,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                bdev->bd_disk = disk;
                bdev->bd_queue = disk->queue;
                bdev->bd_contains = bdev;
+               bdev->bd_inode->i_flags = disk->fops->direct_access ? S_DAX : 0;
                if (!partno) {
                        ret = -ENXIO;
                        bdev->bd_part = disk_get_part(disk, partno);
@@ -1759,7 +1770,7 @@ void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
 {
        struct inode *inode, *old_inode = NULL;
 
-       spin_lock(&inode_sb_list_lock);
+       spin_lock(&blockdev_superblock->s_inode_list_lock);
        list_for_each_entry(inode, &blockdev_superblock->s_inodes, i_sb_list) {
                struct address_space *mapping = inode->i_mapping;
 
@@ -1771,13 +1782,13 @@ void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
                }
                __iget(inode);
                spin_unlock(&inode->i_lock);
-               spin_unlock(&inode_sb_list_lock);
+               spin_unlock(&blockdev_superblock->s_inode_list_lock);
                /*
                 * We hold a reference to 'inode' so it couldn't have been
                 * removed from s_inodes list while we dropped the
-                * inode_sb_list_lock.  We cannot iput the inode now as we can
+                * s_inode_list_lock  We cannot iput the inode now as we can
                 * be holding the last reference and we cannot iput it under
-                * inode_sb_list_lock. So we keep the reference and iput it
+                * s_inode_list_lock. So we keep the reference and iput it
                 * later.
                 */
                iput(old_inode);
@@ -1785,8 +1796,8 @@ void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
 
                func(I_BDEV(inode), arg);
 
-               spin_lock(&inode_sb_list_lock);
+               spin_lock(&blockdev_superblock->s_inode_list_lock);
        }
-       spin_unlock(&inode_sb_list_lock);
+       spin_unlock(&blockdev_superblock->s_inode_list_lock);
        iput(old_inode);
 }
This page took 0.040817 seconds and 5 git commands to generate.