diff options
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r-- | drivers/md/dm.c | 67 |
1 files changed, 53 insertions, 14 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 268edf402bbb..6ef9500226c0 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> |
@@ -629,6 +630,7 @@ static int open_table_device(struct table_device *td, dev_t dev, | |||
629 | } | 630 | } |
630 | 631 | ||
631 | td->dm_dev.bdev = bdev; | 632 | td->dm_dev.bdev = bdev; |
633 | td->dm_dev.dax_dev = dax_get_by_host(bdev->bd_disk->disk_name); | ||
632 | return 0; | 634 | return 0; |
633 | } | 635 | } |
634 | 636 | ||
@@ -642,7 +644,9 @@ static void close_table_device(struct table_device *td, struct mapped_device *md | |||
642 | 644 | ||
643 | bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md)); | 645 | bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md)); |
644 | blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL); | 646 | blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL); |
647 | put_dax(td->dm_dev.dax_dev); | ||
645 | td->dm_dev.bdev = NULL; | 648 | td->dm_dev.bdev = NULL; |
649 | td->dm_dev.dax_dev = NULL; | ||
646 | } | 650 | } |
647 | 651 | ||
648 | static struct table_device *find_table_device(struct list_head *l, dev_t dev, | 652 | static struct table_device *find_table_device(struct list_head *l, dev_t dev, |
@@ -920,31 +924,49 @@ int dm_set_target_max_io_len(struct dm_target *ti, sector_t len) | |||
920 | } | 924 | } |
921 | EXPORT_SYMBOL_GPL(dm_set_target_max_io_len); | 925 | EXPORT_SYMBOL_GPL(dm_set_target_max_io_len); |
922 | 926 | ||
923 | static long dm_blk_direct_access(struct block_device *bdev, sector_t sector, | 927 | static struct dm_target *dm_dax_get_live_target(struct mapped_device *md, |
924 | void **kaddr, pfn_t *pfn, long size) | 928 | sector_t sector, int *srcu_idx) |
925 | { | 929 | { |
926 | struct mapped_device *md = bdev->bd_disk->private_data; | ||
927 | struct dm_table *map; | 930 | struct dm_table *map; |
928 | struct dm_target *ti; | 931 | struct dm_target *ti; |
929 | int srcu_idx; | ||
930 | long len, ret = -EIO; | ||
931 | 932 | ||
932 | map = dm_get_live_table(md, &srcu_idx); | 933 | map = dm_get_live_table(md, srcu_idx); |
933 | if (!map) | 934 | if (!map) |
934 | goto out; | 935 | return NULL; |
935 | 936 | ||
936 | ti = dm_table_find_target(map, sector); | 937 | ti = dm_table_find_target(map, sector); |
937 | if (!dm_target_is_valid(ti)) | 938 | if (!dm_target_is_valid(ti)) |
938 | goto out; | 939 | return NULL; |
940 | |||
941 | return ti; | ||
942 | } | ||
943 | |||
944 | static long dm_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, | ||
945 | long nr_pages, void **kaddr, pfn_t *pfn) | ||
946 | { | ||
947 | struct mapped_device *md = dax_get_private(dax_dev); | ||
948 | sector_t sector = pgoff * PAGE_SECTORS; | ||
949 | struct dm_target *ti; | ||
950 | long len, ret = -EIO; | ||
951 | int srcu_idx; | ||
939 | 952 | ||
940 | len = max_io_len(sector, ti) << SECTOR_SHIFT; | 953 | ti = dm_dax_get_live_target(md, sector, &srcu_idx); |
941 | size = min(len, size); | ||
942 | 954 | ||
955 | if (!ti) | ||
956 | goto out; | ||
957 | if (!ti->type->direct_access) | ||
958 | goto out; | ||
959 | len = max_io_len(sector, ti) / PAGE_SECTORS; | ||
960 | if (len < 1) | ||
961 | goto out; | ||
962 | nr_pages = min(len, nr_pages); | ||
943 | if (ti->type->direct_access) | 963 | if (ti->type->direct_access) |
944 | ret = ti->type->direct_access(ti, sector, kaddr, pfn, size); | 964 | ret = ti->type->direct_access(ti, pgoff, nr_pages, kaddr, pfn); |
945 | out: | 965 | |
966 | out: | ||
946 | dm_put_live_table(md, srcu_idx); | 967 | dm_put_live_table(md, srcu_idx); |
947 | return min(ret, size); | 968 | |
969 | return ret; | ||
948 | } | 970 | } |
949 | 971 | ||
950 | /* | 972 | /* |
@@ -1471,6 +1493,7 @@ static int next_free_minor(int *minor) | |||
1471 | } | 1493 | } |
1472 | 1494 | ||
1473 | static const struct block_device_operations dm_blk_dops; | 1495 | static const struct block_device_operations dm_blk_dops; |
1496 | static const struct dax_operations dm_dax_ops; | ||
1474 | 1497 | ||
1475 | static void dm_wq_work(struct work_struct *work); | 1498 | static void dm_wq_work(struct work_struct *work); |
1476 | 1499 | ||
@@ -1517,6 +1540,12 @@ static void cleanup_mapped_device(struct mapped_device *md) | |||
1517 | if (md->bs) | 1540 | if (md->bs) |
1518 | bioset_free(md->bs); | 1541 | bioset_free(md->bs); |
1519 | 1542 | ||
1543 | if (md->dax_dev) { | ||
1544 | kill_dax(md->dax_dev); | ||
1545 | put_dax(md->dax_dev); | ||
1546 | md->dax_dev = NULL; | ||
1547 | } | ||
1548 | |||
1520 | if (md->disk) { | 1549 | if (md->disk) { |
1521 | spin_lock(&_minor_lock); | 1550 | spin_lock(&_minor_lock); |
1522 | md->disk->private_data = NULL; | 1551 | md->disk->private_data = NULL; |
@@ -1544,6 +1573,7 @@ static void cleanup_mapped_device(struct mapped_device *md) | |||
1544 | static struct mapped_device *alloc_dev(int minor) | 1573 | static struct mapped_device *alloc_dev(int minor) |
1545 | { | 1574 | { |
1546 | int r, numa_node_id = dm_get_numa_node(); | 1575 | int r, numa_node_id = dm_get_numa_node(); |
1576 | struct dax_device *dax_dev; | ||
1547 | struct mapped_device *md; | 1577 | struct mapped_device *md; |
1548 | void *old_md; | 1578 | void *old_md; |
1549 | 1579 | ||
@@ -1608,6 +1638,12 @@ static struct mapped_device *alloc_dev(int minor) | |||
1608 | md->disk->queue = md->queue; | 1638 | md->disk->queue = md->queue; |
1609 | md->disk->private_data = md; | 1639 | md->disk->private_data = md; |
1610 | sprintf(md->disk->disk_name, "dm-%d", minor); | 1640 | sprintf(md->disk->disk_name, "dm-%d", minor); |
1641 | |||
1642 | dax_dev = alloc_dax(md, md->disk->disk_name, &dm_dax_ops); | ||
1643 | if (!dax_dev) | ||
1644 | goto bad; | ||
1645 | md->dax_dev = dax_dev; | ||
1646 | |||
1611 | add_disk(md->disk); | 1647 | add_disk(md->disk); |
1612 | format_dev_t(md->name, MKDEV(_major, minor)); | 1648 | format_dev_t(md->name, MKDEV(_major, minor)); |
1613 | 1649 | ||
@@ -2816,12 +2852,15 @@ static const struct block_device_operations dm_blk_dops = { | |||
2816 | .open = dm_blk_open, | 2852 | .open = dm_blk_open, |
2817 | .release = dm_blk_close, | 2853 | .release = dm_blk_close, |
2818 | .ioctl = dm_blk_ioctl, | 2854 | .ioctl = dm_blk_ioctl, |
2819 | .direct_access = dm_blk_direct_access, | ||
2820 | .getgeo = dm_blk_getgeo, | 2855 | .getgeo = dm_blk_getgeo, |
2821 | .pr_ops = &dm_pr_ops, | 2856 | .pr_ops = &dm_pr_ops, |
2822 | .owner = THIS_MODULE | 2857 | .owner = THIS_MODULE |
2823 | }; | 2858 | }; |
2824 | 2859 | ||
2860 | static const struct dax_operations dm_dax_ops = { | ||
2861 | .direct_access = dm_dax_direct_access, | ||
2862 | }; | ||
2863 | |||
2825 | /* | 2864 | /* |
2826 | * module hooks | 2865 | * module hooks |
2827 | */ | 2866 | */ |