summaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2017-04-12 15:35:44 -0400
committerDan Williams <dan.j.williams@intel.com>2017-04-20 14:57:52 -0400
commitf26c5719b2d7b00de69eb83eb1c1c831759fdc9b (patch)
treed2f4dc917d539e7dae0424d7722affdc1cdd2006 /drivers/md
parentb0686260fecaa924d8eff2ace94bee70506bc308 (diff)
dm: add dax_device and dax_operations support
Allocate a dax_device to represent the capacity of a device-mapper instance. Provide a ->direct_access() method via the new dax_operations indirection that mirrors the functionality of the current direct_access support via block_device_operations. Once fs/dax.c has been converted to use dax_operations the old dm_blk_direct_access() will be removed. A new helper dm_dax_get_live_target() is introduced to separate some of the dm-specifics from the direct_access implementation. This enabling is only for the top-level dm representation to upper layers. Converting target direct_access implementations is deferred to a separate patch. Cc: Toshi Kani <toshi.kani@hpe.com> Reviewed-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/Kconfig1
-rw-r--r--drivers/md/dm-core.h1
-rw-r--r--drivers/md/dm.c84
3 files changed, 72 insertions, 14 deletions
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index b7767da50c26..1de8372d9459 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -200,6 +200,7 @@ config BLK_DEV_DM_BUILTIN
200config BLK_DEV_DM 200config BLK_DEV_DM
201 tristate "Device mapper support" 201 tristate "Device mapper support"
202 select BLK_DEV_DM_BUILTIN 202 select BLK_DEV_DM_BUILTIN
203 select DAX
203 ---help--- 204 ---help---
204 Device-mapper is a low level volume manager. It works by allowing 205 Device-mapper is a low level volume manager. It works by allowing
205 people to specify mappings for ranges of logical sectors. Various 206 people to specify mappings for ranges of logical sectors. Various
diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h
index 136fda3ff9e5..538630190f66 100644
--- a/drivers/md/dm-core.h
+++ b/drivers/md/dm-core.h
@@ -58,6 +58,7 @@ struct mapped_device {
58 struct target_type *immutable_target_type; 58 struct target_type *immutable_target_type;
59 59
60 struct gendisk *disk; 60 struct gendisk *disk;
61 struct dax_device *dax_dev;
61 char name[16]; 62 char name[16];
62 63
63 void *interface_ptr; 64 void *interface_ptr;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index dfb75979e455..bd56dfe43a99 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -16,6 +16,7 @@
16#include <linux/blkpg.h> 16#include <linux/blkpg.h>
17#include <linux/bio.h> 17#include <linux/bio.h>
18#include <linux/mempool.h> 18#include <linux/mempool.h>
19#include <linux/dax.h>
19#include <linux/slab.h> 20#include <linux/slab.h>
20#include <linux/idr.h> 21#include <linux/idr.h>
21#include <linux/hdreg.h> 22#include <linux/hdreg.h>
@@ -908,31 +909,68 @@ int dm_set_target_max_io_len(struct dm_target *ti, sector_t len)
908} 909}
909EXPORT_SYMBOL_GPL(dm_set_target_max_io_len); 910EXPORT_SYMBOL_GPL(dm_set_target_max_io_len);
910 911
911static long dm_blk_direct_access(struct block_device *bdev, sector_t sector, 912static struct dm_target *dm_dax_get_live_target(struct mapped_device *md,
912 void **kaddr, pfn_t *pfn, long size) 913 sector_t sector, int *srcu_idx)
913{ 914{
914 struct mapped_device *md = bdev->bd_disk->private_data;
915 struct dm_table *map; 915 struct dm_table *map;
916 struct dm_target *ti; 916 struct dm_target *ti;
917 int srcu_idx;
918 long len, ret = -EIO;
919 917
920 map = dm_get_live_table(md, &srcu_idx); 918 map = dm_get_live_table(md, srcu_idx);
921 if (!map) 919 if (!map)
922 goto out; 920 return NULL;
923 921
924 ti = dm_table_find_target(map, sector); 922 ti = dm_table_find_target(map, sector);
925 if (!dm_target_is_valid(ti)) 923 if (!dm_target_is_valid(ti))
926 goto out; 924 return NULL;
927 925
928 len = max_io_len(sector, ti) << SECTOR_SHIFT; 926 return ti;
929 size = min(len, size); 927}
930 928
931 if (ti->type->direct_access) 929static long dm_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
932 ret = ti->type->direct_access(ti, sector, kaddr, pfn, size); 930 long nr_pages, void **kaddr, pfn_t *pfn)
933out: 931{
932 struct mapped_device *md = dax_get_private(dax_dev);
933 sector_t sector = pgoff * PAGE_SECTORS;
934 struct dm_target *ti;
935 long len, ret = -EIO;
936 int srcu_idx;
937
938 ti = dm_dax_get_live_target(md, sector, &srcu_idx);
939
940 if (!ti)
941 goto out;
942 if (!ti->type->direct_access)
943 goto out;
944 len = max_io_len(sector, ti) / PAGE_SECTORS;
945 if (len < 1)
946 goto out;
947 nr_pages = min(len, nr_pages);
948 if (ti->type->direct_access) {
949 ret = ti->type->direct_access(ti, sector, kaddr, pfn,
950 nr_pages * PAGE_SIZE);
951 /*
952 * FIXME: convert ti->type->direct_access to return
953 * nr_pages directly.
954 */
955 if (ret >= 0)
956 ret /= PAGE_SIZE;
957 }
958 out:
934 dm_put_live_table(md, srcu_idx); 959 dm_put_live_table(md, srcu_idx);
935 return min(ret, size); 960
961 return ret;
962}
963
964static long dm_blk_direct_access(struct block_device *bdev, sector_t sector,
965 void **kaddr, pfn_t *pfn, long size)
966{
967 struct mapped_device *md = bdev->bd_disk->private_data;
968 struct dax_device *dax_dev = md->dax_dev;
969 long nr_pages = size / PAGE_SIZE;
970
971 nr_pages = dm_dax_direct_access(dax_dev, sector / PAGE_SECTORS,
972 nr_pages, kaddr, pfn);
973 return nr_pages < 0 ? nr_pages : nr_pages * PAGE_SIZE;
936} 974}
937 975
938/* 976/*
@@ -1437,6 +1475,7 @@ static int next_free_minor(int *minor)
1437} 1475}
1438 1476
1439static const struct block_device_operations dm_blk_dops; 1477static const struct block_device_operations dm_blk_dops;
1478static const struct dax_operations dm_dax_ops;
1440 1479
1441static void dm_wq_work(struct work_struct *work); 1480static void dm_wq_work(struct work_struct *work);
1442 1481
@@ -1483,6 +1522,12 @@ static void cleanup_mapped_device(struct mapped_device *md)
1483 if (md->bs) 1522 if (md->bs)
1484 bioset_free(md->bs); 1523 bioset_free(md->bs);
1485 1524
1525 if (md->dax_dev) {
1526 kill_dax(md->dax_dev);
1527 put_dax(md->dax_dev);
1528 md->dax_dev = NULL;
1529 }
1530
1486 if (md->disk) { 1531 if (md->disk) {
1487 spin_lock(&_minor_lock); 1532 spin_lock(&_minor_lock);
1488 md->disk->private_data = NULL; 1533 md->disk->private_data = NULL;
@@ -1510,6 +1555,7 @@ static void cleanup_mapped_device(struct mapped_device *md)
1510static struct mapped_device *alloc_dev(int minor) 1555static struct mapped_device *alloc_dev(int minor)
1511{ 1556{
1512 int r, numa_node_id = dm_get_numa_node(); 1557 int r, numa_node_id = dm_get_numa_node();
1558 struct dax_device *dax_dev;
1513 struct mapped_device *md; 1559 struct mapped_device *md;
1514 void *old_md; 1560 void *old_md;
1515 1561
@@ -1574,6 +1620,12 @@ static struct mapped_device *alloc_dev(int minor)
1574 md->disk->queue = md->queue; 1620 md->disk->queue = md->queue;
1575 md->disk->private_data = md; 1621 md->disk->private_data = md;
1576 sprintf(md->disk->disk_name, "dm-%d", minor); 1622 sprintf(md->disk->disk_name, "dm-%d", minor);
1623
1624 dax_dev = alloc_dax(md, md->disk->disk_name, &dm_dax_ops);
1625 if (!dax_dev)
1626 goto bad;
1627 md->dax_dev = dax_dev;
1628
1577 add_disk(md->disk); 1629 add_disk(md->disk);
1578 format_dev_t(md->name, MKDEV(_major, minor)); 1630 format_dev_t(md->name, MKDEV(_major, minor));
1579 1631
@@ -2781,6 +2833,10 @@ static const struct block_device_operations dm_blk_dops = {
2781 .owner = THIS_MODULE 2833 .owner = THIS_MODULE
2782}; 2834};
2783 2835
2836static const struct dax_operations dm_dax_ops = {
2837 .direct_access = dm_dax_direct_access,
2838};
2839
2784/* 2840/*
2785 * module hooks 2841 * module hooks
2786 */ 2842 */