]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - fs/block_dev.c
Merge tag 'libnvdimm-for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdim...
[mirror_ubuntu-artful-kernel.git] / fs / block_dev.c
index 0d435c794d760b7530945e3b82cf40f8cfcc7fb7..2a305c1a2d881a78e8251288908a7bafcc840af9 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/blkpg.h>
 #include <linux/magic.h>
+#include <linux/dax.h>
 #include <linux/buffer_head.h>
 #include <linux/swap.h>
 #include <linux/pagevec.h>
@@ -716,50 +717,18 @@ int bdev_write_page(struct block_device *bdev, sector_t sector,
 }
 EXPORT_SYMBOL_GPL(bdev_write_page);
 
-/**
- * bdev_direct_access() - Get the address for directly-accessibly memory
- * @bdev: The device containing the memory
- * @dax: control and output parameters for ->direct_access
- *
- * If a block device is made up of directly addressable memory, this function
- * will tell the caller the PFN and the address of the memory.  The address
- * may be directly dereferenced within the kernel without the need to call
- * ioremap(), kmap() or similar.  The PFN is suitable for inserting into
- * page tables.
- *
- * Return: negative errno if an error occurs, otherwise the number of bytes
- * accessible at this address.
- */
-long bdev_direct_access(struct block_device *bdev, struct blk_dax_ctl *dax)
+int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size,
+               pgoff_t *pgoff)
 {
-       sector_t sector = dax->sector;
-       long avail, size = dax->size;
-       const struct block_device_operations *ops = bdev->bd_disk->fops;
+       phys_addr_t phys_off = (get_start_sect(bdev) + sector) * 512;
 
-       /*
-        * The device driver is allowed to sleep, in order to make the
-        * memory directly accessible.
-        */
-       might_sleep();
-
-       if (size < 0)
-               return size;
-       if (!blk_queue_dax(bdev_get_queue(bdev)) || !ops->direct_access)
-               return -EOPNOTSUPP;
-       if ((sector + DIV_ROUND_UP(size, 512)) >
-                                       part_nr_sects_read(bdev->bd_part))
-               return -ERANGE;
-       sector += get_start_sect(bdev);
-       if (sector % (PAGE_SIZE / 512))
+       if (pgoff)
+               *pgoff = PHYS_PFN(phys_off);
+       if (phys_off % PAGE_SIZE || size % PAGE_SIZE)
                return -EINVAL;
-       avail = ops->direct_access(bdev, sector, &dax->addr, &dax->pfn, size);
-       if (!avail)
-               return -ERANGE;
-       if (avail > 0 && avail & ~PAGE_MASK)
-               return -ENXIO;
-       return min(avail, size);
+       return 0;
 }
-EXPORT_SYMBOL_GPL(bdev_direct_access);
+EXPORT_SYMBOL(bdev_dax_pgoff);
 
 /**
  * bdev_dax_supported() - Check if the device supports dax for filesystem
@@ -773,62 +742,46 @@ EXPORT_SYMBOL_GPL(bdev_direct_access);
  */
 int bdev_dax_supported(struct super_block *sb, int blocksize)
 {
-       struct blk_dax_ctl dax = {
-               .sector = 0,
-               .size = PAGE_SIZE,
-       };
-       int err;
+       struct block_device *bdev = sb->s_bdev;
+       struct dax_device *dax_dev;
+       pgoff_t pgoff;
+       int err, id;
+       void *kaddr;
+       pfn_t pfn;
+       long len;
 
        if (blocksize != PAGE_SIZE) {
                vfs_msg(sb, KERN_ERR, "error: unsupported blocksize for dax");
                return -EINVAL;
        }
 
-       err = bdev_direct_access(sb->s_bdev, &dax);
-       if (err < 0) {
-               switch (err) {
-               case -EOPNOTSUPP:
-                       vfs_msg(sb, KERN_ERR,
-                               "error: device does not support dax");
-                       break;
-               case -EINVAL:
-                       vfs_msg(sb, KERN_ERR,
-                               "error: unaligned partition for dax");
-                       break;
-               default:
-                       vfs_msg(sb, KERN_ERR,
-                               "error: dax access failed (%d)", err);
-               }
+       err = bdev_dax_pgoff(bdev, 0, PAGE_SIZE, &pgoff);
+       if (err) {
+               vfs_msg(sb, KERN_ERR, "error: unaligned partition for dax");
                return err;
        }
 
-       return 0;
-}
-EXPORT_SYMBOL_GPL(bdev_dax_supported);
-
-/**
- * bdev_dax_capable() - Return if the raw device is capable for dax
- * @bdev: The device for raw block device access
- */
-bool bdev_dax_capable(struct block_device *bdev)
-{
-       struct blk_dax_ctl dax = {
-               .size = PAGE_SIZE,
-       };
+       dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
+       if (!dax_dev) {
+               vfs_msg(sb, KERN_ERR, "error: device does not support dax");
+               return -EOPNOTSUPP;
+       }
 
-       if (!IS_ENABLED(CONFIG_FS_DAX))
-               return false;
+       id = dax_read_lock();
+       len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn);
+       dax_read_unlock(id);
 
-       dax.sector = 0;
-       if (bdev_direct_access(bdev, &dax) < 0)
-               return false;
+       put_dax(dax_dev);
 
-       dax.sector = bdev->bd_part->nr_sects - (PAGE_SIZE / 512);
-       if (bdev_direct_access(bdev, &dax) < 0)
-               return false;
+       if (len < 1) {
+               vfs_msg(sb, KERN_ERR,
+                               "error: dax access failed (%ld)", len);
+               return len < 0 ? len : -EIO;
+       }
 
-       return true;
+       return 0;
 }
+EXPORT_SYMBOL_GPL(bdev_dax_supported);
 
 /*
  * pseudo-fs