summaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-05 21:49:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-05 21:49:20 -0400
commit53ef7d0e208fa38c3f63d287e0c3ab174f1e1235 (patch)
tree7d437edf73ef6deb0d77ce291aa25f041837d056 /drivers/md
parentc6a677c6f37bb7abc85ba7e3465e82b9f7eb1d91 (diff)
parent736163671bcb163fc82600b46c83dfa89d532d95 (diff)
Merge tag 'libnvdimm-for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull libnvdimm updates from Dan Williams: "The bulk of this has been in multiple -next releases. There were a few late breaking fixes and small features that got added in the last couple days, but the whole set has received a build success notification from the kbuild robot. Change summary: - Region media error reporting: A libnvdimm region device is the parent to one or more namespaces. To date, media errors have been reported via the "badblocks" attribute attached to pmem block devices for namespaces in "raw" or "memory" mode. Given that namespaces can be in "device-dax" or "btt-sector" mode this new interface reports media errors generically, i.e. independent of namespace modes or state. This subsequently allows userspace tooling to craft "ACPI 6.1 Section 9.20.7.6 Function Index 4 - Clear Uncorrectable Error" requests and submit them via the ioctl path for NVDIMM root bus devices. - Introduce 'struct dax_device' and 'struct dax_operations': Prompted by a request from Linus and feedback from Christoph this allows for dax capable drivers to publish their own custom dax operations. This fixes the broken assumption that all dax operations are related to a persistent memory device, and makes it easier for other architectures and platforms to add customized persistent memory support. - 'libnvdimm' core updates: A new "deep_flush" sysfs attribute is available for storage appliance applications to manually trigger memory controllers to drain write-pending buffers that would otherwise be flushed automatically by the platform ADR (asynchronous-DRAM-refresh) mechanism at a power loss event. Support for "locked" DIMMs is included to prevent namespaces from surfacing when the namespace label data area is locked. Finally, fixes for various reported deadlocks and crashes, also tagged for -stable. - ACPI / nfit driver updates: General updates of the nfit driver to add DSM command overrides, ACPI 6.1 health state flags support, DSM payload debug available by default, and various fixes. Acknowledgements that came after the branch was pushed: - commmit 565851c972b5 "device-dax: fix sysfs attribute deadlock": Tested-by: Yi Zhang <yizhan@redhat.com> - commit 23f498448362 "libnvdimm: rework region badblocks clearing" Tested-by: Toshi Kani <toshi.kani@hpe.com>" * tag 'libnvdimm-for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: (52 commits) libnvdimm, pfn: fix 'npfns' vs section alignment libnvdimm: handle locked label storage areas libnvdimm: convert NDD_ flags to use bitops, introduce NDD_LOCKED brd: fix uninitialized use of brd->dax_dev block, dax: use correct format string in bdev_dax_supported device-dax: fix sysfs attribute deadlock libnvdimm: restore "libnvdimm: band aid btt vs clear poison locking" libnvdimm: fix nvdimm_bus_lock() vs device_lock() ordering libnvdimm: rework region badblocks clearing acpi, nfit: kill ACPI_NFIT_DEBUG libnvdimm: fix clear length of nvdimm_forget_poison() libnvdimm, pmem: fix a NULL pointer BUG in nd_pmem_notify libnvdimm, region: sysfs trigger for nvdimm_flush() libnvdimm: fix phys_addr for nvdimm_clear_poison x86, dax, pmem: remove indirection around memcpy_from_pmem() block: remove block_device_operations ->direct_access() block, dax: convert bdev_dax_supported() to dax_direct_access() filesystem-dax: convert to dax_direct_access() Revert "block: use DAX for partition table reads" ext2, ext4, xfs: retrieve dax_device for iomap operations ...
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-linear.c27
-rw-r--r--drivers/md/dm-snap.c6
-rw-r--r--drivers/md/dm-stripe.c29
-rw-r--r--drivers/md/dm-target.c6
-rw-r--r--drivers/md/dm.c67
7 files changed, 88 insertions, 49 deletions
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 7468a22f9d10..349ff8813401 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 97db4d11c05a..52ca8d059e82 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-linear.c b/drivers/md/dm-linear.c
index a5120961632a..7d42a9d9f406 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -9,6 +9,7 @@
9#include <linux/init.h> 9#include <linux/init.h>
10#include <linux/blkdev.h> 10#include <linux/blkdev.h>
11#include <linux/bio.h> 11#include <linux/bio.h>
12#include <linux/dax.h>
12#include <linux/slab.h> 13#include <linux/slab.h>
13#include <linux/device-mapper.h> 14#include <linux/device-mapper.h>
14 15
@@ -142,22 +143,20 @@ static int linear_iterate_devices(struct dm_target *ti,
142 return fn(ti, lc->dev, lc->start, ti->len, data); 143 return fn(ti, lc->dev, lc->start, ti->len, data);
143} 144}
144 145
145static long linear_direct_access(struct dm_target *ti, sector_t sector, 146static long linear_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
146 void **kaddr, pfn_t *pfn, long size) 147 long nr_pages, void **kaddr, pfn_t *pfn)
147{ 148{
149 long ret;
148 struct linear_c *lc = ti->private; 150 struct linear_c *lc = ti->private;
149 struct block_device *bdev = lc->dev->bdev; 151 struct block_device *bdev = lc->dev->bdev;
150 struct blk_dax_ctl dax = { 152 struct dax_device *dax_dev = lc->dev->dax_dev;
151 .sector = linear_map_sector(ti, sector), 153 sector_t dev_sector, sector = pgoff * PAGE_SECTORS;
152 .size = size, 154
153 }; 155 dev_sector = linear_map_sector(ti, sector);
154 long ret; 156 ret = bdev_dax_pgoff(bdev, dev_sector, nr_pages * PAGE_SIZE, &pgoff);
155 157 if (ret)
156 ret = bdev_direct_access(bdev, &dax); 158 return ret;
157 *kaddr = dax.addr; 159 return dax_direct_access(dax_dev, pgoff, nr_pages, kaddr, pfn);
158 *pfn = dax.pfn;
159
160 return ret;
161} 160}
162 161
163static struct target_type linear_target = { 162static struct target_type linear_target = {
@@ -171,7 +170,7 @@ static struct target_type linear_target = {
171 .status = linear_status, 170 .status = linear_status,
172 .prepare_ioctl = linear_prepare_ioctl, 171 .prepare_ioctl = linear_prepare_ioctl,
173 .iterate_devices = linear_iterate_devices, 172 .iterate_devices = linear_iterate_devices,
174 .direct_access = linear_direct_access, 173 .direct_access = linear_dax_direct_access,
175}; 174};
176 175
177int __init dm_linear_init(void) 176int __init dm_linear_init(void)
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index c65feeada864..e152d9817c81 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -2302,8 +2302,8 @@ static int origin_map(struct dm_target *ti, struct bio *bio)
2302 return do_origin(o->dev, bio); 2302 return do_origin(o->dev, bio);
2303} 2303}
2304 2304
2305static long origin_direct_access(struct dm_target *ti, sector_t sector, 2305static long origin_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
2306 void **kaddr, pfn_t *pfn, long size) 2306 long nr_pages, void **kaddr, pfn_t *pfn)
2307{ 2307{
2308 DMWARN("device does not support dax."); 2308 DMWARN("device does not support dax.");
2309 return -EIO; 2309 return -EIO;
@@ -2368,7 +2368,7 @@ static struct target_type origin_target = {
2368 .postsuspend = origin_postsuspend, 2368 .postsuspend = origin_postsuspend,
2369 .status = origin_status, 2369 .status = origin_status,
2370 .iterate_devices = origin_iterate_devices, 2370 .iterate_devices = origin_iterate_devices,
2371 .direct_access = origin_direct_access, 2371 .direct_access = origin_dax_direct_access,
2372}; 2372};
2373 2373
2374static struct target_type snapshot_target = { 2374static struct target_type snapshot_target = {
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 4b50ae115c6d..75152482f3ad 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -11,6 +11,7 @@
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/blkdev.h> 12#include <linux/blkdev.h>
13#include <linux/bio.h> 13#include <linux/bio.h>
14#include <linux/dax.h>
14#include <linux/slab.h> 15#include <linux/slab.h>
15#include <linux/log2.h> 16#include <linux/log2.h>
16 17
@@ -310,27 +311,25 @@ static int stripe_map(struct dm_target *ti, struct bio *bio)
310 return DM_MAPIO_REMAPPED; 311 return DM_MAPIO_REMAPPED;
311} 312}
312 313
313static long stripe_direct_access(struct dm_target *ti, sector_t sector, 314static long stripe_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
314 void **kaddr, pfn_t *pfn, long size) 315 long nr_pages, void **kaddr, pfn_t *pfn)
315{ 316{
317 sector_t dev_sector, sector = pgoff * PAGE_SECTORS;
316 struct stripe_c *sc = ti->private; 318 struct stripe_c *sc = ti->private;
317 uint32_t stripe; 319 struct dax_device *dax_dev;
318 struct block_device *bdev; 320 struct block_device *bdev;
319 struct blk_dax_ctl dax = { 321 uint32_t stripe;
320 .size = size,
321 };
322 long ret; 322 long ret;
323 323
324 stripe_map_sector(sc, sector, &stripe, &dax.sector); 324 stripe_map_sector(sc, sector, &stripe, &dev_sector);
325 325 dev_sector += sc->stripe[stripe].physical_start;
326 dax.sector += sc->stripe[stripe].physical_start; 326 dax_dev = sc->stripe[stripe].dev->dax_dev;
327 bdev = sc->stripe[stripe].dev->bdev; 327 bdev = sc->stripe[stripe].dev->bdev;
328 328
329 ret = bdev_direct_access(bdev, &dax); 329 ret = bdev_dax_pgoff(bdev, dev_sector, nr_pages * PAGE_SIZE, &pgoff);
330 *kaddr = dax.addr; 330 if (ret)
331 *pfn = dax.pfn; 331 return ret;
332 332 return dax_direct_access(dax_dev, pgoff, nr_pages, kaddr, pfn);
333 return ret;
334} 333}
335 334
336/* 335/*
@@ -451,7 +450,7 @@ static struct target_type stripe_target = {
451 .status = stripe_status, 450 .status = stripe_status,
452 .iterate_devices = stripe_iterate_devices, 451 .iterate_devices = stripe_iterate_devices,
453 .io_hints = stripe_io_hints, 452 .io_hints = stripe_io_hints,
454 .direct_access = stripe_direct_access, 453 .direct_access = stripe_dax_direct_access,
455}; 454};
456 455
457int __init dm_stripe_init(void) 456int __init dm_stripe_init(void)
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c
index 6264ff00dcf0..b242b750542f 100644
--- a/drivers/md/dm-target.c
+++ b/drivers/md/dm-target.c
@@ -142,8 +142,8 @@ static void io_err_release_clone_rq(struct request *clone)
142{ 142{
143} 143}
144 144
145static long io_err_direct_access(struct dm_target *ti, sector_t sector, 145static long io_err_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
146 void **kaddr, pfn_t *pfn, long size) 146 long nr_pages, void **kaddr, pfn_t *pfn)
147{ 147{
148 return -EIO; 148 return -EIO;
149} 149}
@@ -157,7 +157,7 @@ static struct target_type error_target = {
157 .map = io_err_map, 157 .map = io_err_map,
158 .clone_and_map_rq = io_err_clone_and_map_rq, 158 .clone_and_map_rq = io_err_clone_and_map_rq,
159 .release_clone_rq = io_err_release_clone_rq, 159 .release_clone_rq = io_err_release_clone_rq,
160 .direct_access = io_err_direct_access, 160 .direct_access = io_err_dax_direct_access,
161}; 161};
162 162
163int __init dm_target_init(void) 163int __init dm_target_init(void)
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
648static struct table_device *find_table_device(struct list_head *l, dev_t dev, 652static 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}
921EXPORT_SYMBOL_GPL(dm_set_target_max_io_len); 925EXPORT_SYMBOL_GPL(dm_set_target_max_io_len);
922 926
923static long dm_blk_direct_access(struct block_device *bdev, sector_t sector, 927static 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
944static 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);
945out: 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
1473static const struct block_device_operations dm_blk_dops; 1495static const struct block_device_operations dm_blk_dops;
1496static const struct dax_operations dm_dax_ops;
1474 1497
1475static void dm_wq_work(struct work_struct *work); 1498static 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)
1544static struct mapped_device *alloc_dev(int minor) 1573static 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
2860static 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 */