]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/dax/super.c
netfilter: conntrack: rename nf_ct_iterate_cleanup
[mirror_ubuntu-artful-kernel.git] / drivers / dax / super.c
index 465dcd7317d5f620c1b7c1fcf67597afae1fb9f0..6ed32aac8bbeec9f139d0ba622d4b5fb6d1aca4b 100644 (file)
 #include <linux/module.h>
 #include <linux/mount.h>
 #include <linux/magic.h>
+#include <linux/genhd.h>
 #include <linux/cdev.h>
 #include <linux/hash.h>
 #include <linux/slab.h>
 #include <linux/dax.h>
 #include <linux/fs.h>
 
-static int nr_dax = CONFIG_NR_DEV_DAX;
-module_param(nr_dax, int, S_IRUGO);
-MODULE_PARM_DESC(nr_dax, "max number of dax device instances");
-
 static dev_t dax_devt;
 DEFINE_STATIC_SRCU(dax_srcu);
 static struct vfsmount *dax_mnt;
@@ -47,6 +44,77 @@ void dax_read_unlock(int id)
 }
 EXPORT_SYMBOL_GPL(dax_read_unlock);
 
+#ifdef CONFIG_BLOCK
+int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size,
+               pgoff_t *pgoff)
+{
+       phys_addr_t phys_off = (get_start_sect(bdev) + sector) * 512;
+
+       if (pgoff)
+               *pgoff = PHYS_PFN(phys_off);
+       if (phys_off % PAGE_SIZE || size % PAGE_SIZE)
+               return -EINVAL;
+       return 0;
+}
+EXPORT_SYMBOL(bdev_dax_pgoff);
+
+/**
+ * __bdev_dax_supported() - Check if the device supports dax for filesystem
+ * @sb: The superblock of the device
+ * @blocksize: The block size of the device
+ *
+ * This is a library function for filesystems to check if the block device
+ * can be mounted with dax option.
+ *
+ * Return: negative errno if unsupported, 0 if supported.
+ */
+int __bdev_dax_supported(struct super_block *sb, int blocksize)
+{
+       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) {
+               pr_err("VFS (%s): error: unsupported blocksize for dax\n",
+                               sb->s_id);
+               return -EINVAL;
+       }
+
+       err = bdev_dax_pgoff(bdev, 0, PAGE_SIZE, &pgoff);
+       if (err) {
+               pr_err("VFS (%s): error: unaligned partition for dax\n",
+                               sb->s_id);
+               return err;
+       }
+
+       dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
+       if (!dax_dev) {
+               pr_err("VFS (%s): error: device does not support dax\n",
+                               sb->s_id);
+               return -EOPNOTSUPP;
+       }
+
+       id = dax_read_lock();
+       len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn);
+       dax_read_unlock(id);
+
+       put_dax(dax_dev);
+
+       if (len < 1) {
+               pr_err("VFS (%s): error: dax access failed (%ld)",
+                               sb->s_id, len);
+               return len < 0 ? len : -EIO;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(__bdev_dax_supported);
+#endif
+
 /**
  * struct dax_device - anchor object for dax services
  * @inode: core vfs
@@ -261,7 +329,7 @@ struct dax_device *alloc_dax(void *private, const char *__host,
        if (__host && !host)
                return NULL;
 
-       minor = ida_simple_get(&dax_minor_ida, 0, nr_dax, GFP_KERNEL);
+       minor = ida_simple_get(&dax_minor_ida, 0, MINORMASK+1, GFP_KERNEL);
        if (minor < 0)
                goto err_minor;
 
@@ -405,8 +473,7 @@ static int __init dax_fs_init(void)
        if (rc)
                return rc;
 
-       nr_dax = max(nr_dax, 256);
-       rc = alloc_chrdev_region(&dax_devt, 0, nr_dax, "dax");
+       rc = alloc_chrdev_region(&dax_devt, 0, MINORMASK+1, "dax");
        if (rc)
                __dax_fs_exit();
        return rc;
@@ -414,7 +481,7 @@ static int __init dax_fs_init(void)
 
 static void __exit dax_fs_exit(void)
 {
-       unregister_chrdev_region(dax_devt, nr_dax);
+       unregister_chrdev_region(dax_devt, MINORMASK+1);
        ida_destroy(&dax_minor_ida);
        __dax_fs_exit();
 }