diff options
author | Dan Williams <dan.j.williams@intel.com> | 2018-05-02 09:46:33 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2018-05-23 02:18:31 -0400 |
commit | b3a9a0c36e1f7b9e2e6cf965c2bb973624f2b3b9 (patch) | |
tree | 54f43a8720a29159310b112cf21e7d3a3b5dce85 | |
parent | 522239b445a2de988edb81672963708a6aaf9046 (diff) |
dax: Introduce a ->copy_to_iter dax operation
Similar to the ->copy_from_iter() operation, a platform may want to
deploy an architecture or device specific routine for handling reads
from a dax_device like /dev/pmemX. On x86 this routine will point to a
machine check safe version of copy_to_iter(). For now, add the plumbing
to device-mapper and the dax core.
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Cc: Mike Snitzer <snitzer@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | drivers/dax/super.c | 10 | ||||
-rw-r--r-- | drivers/md/dm-linear.c | 16 | ||||
-rw-r--r-- | drivers/md/dm-log-writes.c | 15 | ||||
-rw-r--r-- | drivers/md/dm-stripe.c | 21 | ||||
-rw-r--r-- | drivers/md/dm.c | 25 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.c | 7 | ||||
-rw-r--r-- | drivers/s390/block/dcssblk.c | 7 | ||||
-rw-r--r-- | fs/dax.c | 3 | ||||
-rw-r--r-- | include/linux/dax.h | 5 | ||||
-rw-r--r-- | include/linux/device-mapper.h | 5 |
10 files changed, 111 insertions, 3 deletions
diff --git a/drivers/dax/super.c b/drivers/dax/super.c index 2b2332b605e4..31b839113399 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c | |||
@@ -282,6 +282,16 @@ size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, | |||
282 | } | 282 | } |
283 | EXPORT_SYMBOL_GPL(dax_copy_from_iter); | 283 | EXPORT_SYMBOL_GPL(dax_copy_from_iter); |
284 | 284 | ||
285 | size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, | ||
286 | size_t bytes, struct iov_iter *i) | ||
287 | { | ||
288 | if (!dax_alive(dax_dev)) | ||
289 | return 0; | ||
290 | |||
291 | return dax_dev->ops->copy_to_iter(dax_dev, pgoff, addr, bytes, i); | ||
292 | } | ||
293 | EXPORT_SYMBOL_GPL(dax_copy_to_iter); | ||
294 | |||
285 | #ifdef CONFIG_ARCH_HAS_PMEM_API | 295 | #ifdef CONFIG_ARCH_HAS_PMEM_API |
286 | void arch_wb_cache_pmem(void *addr, size_t size); | 296 | void arch_wb_cache_pmem(void *addr, size_t size); |
287 | void dax_flush(struct dax_device *dax_dev, void *addr, size_t size) | 297 | void dax_flush(struct dax_device *dax_dev, void *addr, size_t size) |
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 775c06d953b7..d10964d41fd7 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c | |||
@@ -185,9 +185,24 @@ static size_t linear_dax_copy_from_iter(struct dm_target *ti, pgoff_t pgoff, | |||
185 | return dax_copy_from_iter(dax_dev, pgoff, addr, bytes, i); | 185 | return dax_copy_from_iter(dax_dev, pgoff, addr, bytes, i); |
186 | } | 186 | } |
187 | 187 | ||
188 | static size_t linear_dax_copy_to_iter(struct dm_target *ti, pgoff_t pgoff, | ||
189 | void *addr, size_t bytes, struct iov_iter *i) | ||
190 | { | ||
191 | struct linear_c *lc = ti->private; | ||
192 | struct block_device *bdev = lc->dev->bdev; | ||
193 | struct dax_device *dax_dev = lc->dev->dax_dev; | ||
194 | sector_t dev_sector, sector = pgoff * PAGE_SECTORS; | ||
195 | |||
196 | dev_sector = linear_map_sector(ti, sector); | ||
197 | if (bdev_dax_pgoff(bdev, dev_sector, ALIGN(bytes, PAGE_SIZE), &pgoff)) | ||
198 | return 0; | ||
199 | return dax_copy_to_iter(dax_dev, pgoff, addr, bytes, i); | ||
200 | } | ||
201 | |||
188 | #else | 202 | #else |
189 | #define linear_dax_direct_access NULL | 203 | #define linear_dax_direct_access NULL |
190 | #define linear_dax_copy_from_iter NULL | 204 | #define linear_dax_copy_from_iter NULL |
205 | #define linear_dax_copy_to_iter NULL | ||
191 | #endif | 206 | #endif |
192 | 207 | ||
193 | static struct target_type linear_target = { | 208 | static struct target_type linear_target = { |
@@ -204,6 +219,7 @@ static struct target_type linear_target = { | |||
204 | .iterate_devices = linear_iterate_devices, | 219 | .iterate_devices = linear_iterate_devices, |
205 | .direct_access = linear_dax_direct_access, | 220 | .direct_access = linear_dax_direct_access, |
206 | .dax_copy_from_iter = linear_dax_copy_from_iter, | 221 | .dax_copy_from_iter = linear_dax_copy_from_iter, |
222 | .dax_copy_to_iter = linear_dax_copy_to_iter, | ||
207 | }; | 223 | }; |
208 | 224 | ||
209 | int __init dm_linear_init(void) | 225 | int __init dm_linear_init(void) |
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c index c90c7c08a77f..9ea2b0291f20 100644 --- a/drivers/md/dm-log-writes.c +++ b/drivers/md/dm-log-writes.c | |||
@@ -962,9 +962,23 @@ static size_t log_writes_dax_copy_from_iter(struct dm_target *ti, | |||
962 | dax_copy: | 962 | dax_copy: |
963 | return dax_copy_from_iter(lc->dev->dax_dev, pgoff, addr, bytes, i); | 963 | return dax_copy_from_iter(lc->dev->dax_dev, pgoff, addr, bytes, i); |
964 | } | 964 | } |
965 | |||
966 | static size_t log_writes_dax_copy_to_iter(struct dm_target *ti, | ||
967 | pgoff_t pgoff, void *addr, size_t bytes, | ||
968 | struct iov_iter *i) | ||
969 | { | ||
970 | struct log_writes_c *lc = ti->private; | ||
971 | sector_t sector = pgoff * PAGE_SECTORS; | ||
972 | |||
973 | if (bdev_dax_pgoff(lc->dev->bdev, sector, ALIGN(bytes, PAGE_SIZE), &pgoff)) | ||
974 | return 0; | ||
975 | return dax_copy_to_iter(lc->dev->dax_dev, pgoff, addr, bytes, i); | ||
976 | } | ||
977 | |||
965 | #else | 978 | #else |
966 | #define log_writes_dax_direct_access NULL | 979 | #define log_writes_dax_direct_access NULL |
967 | #define log_writes_dax_copy_from_iter NULL | 980 | #define log_writes_dax_copy_from_iter NULL |
981 | #define log_writes_dax_copy_to_iter NULL | ||
968 | #endif | 982 | #endif |
969 | 983 | ||
970 | static struct target_type log_writes_target = { | 984 | static struct target_type log_writes_target = { |
@@ -982,6 +996,7 @@ static struct target_type log_writes_target = { | |||
982 | .io_hints = log_writes_io_hints, | 996 | .io_hints = log_writes_io_hints, |
983 | .direct_access = log_writes_dax_direct_access, | 997 | .direct_access = log_writes_dax_direct_access, |
984 | .dax_copy_from_iter = log_writes_dax_copy_from_iter, | 998 | .dax_copy_from_iter = log_writes_dax_copy_from_iter, |
999 | .dax_copy_to_iter = log_writes_dax_copy_to_iter, | ||
985 | }; | 1000 | }; |
986 | 1001 | ||
987 | static int __init dm_log_writes_init(void) | 1002 | static int __init dm_log_writes_init(void) |
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index fe7fb9b1aec3..8547d7594338 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
@@ -354,9 +354,29 @@ static size_t stripe_dax_copy_from_iter(struct dm_target *ti, pgoff_t pgoff, | |||
354 | return dax_copy_from_iter(dax_dev, pgoff, addr, bytes, i); | 354 | return dax_copy_from_iter(dax_dev, pgoff, addr, bytes, i); |
355 | } | 355 | } |
356 | 356 | ||
357 | static size_t stripe_dax_copy_to_iter(struct dm_target *ti, pgoff_t pgoff, | ||
358 | void *addr, size_t bytes, struct iov_iter *i) | ||
359 | { | ||
360 | sector_t dev_sector, sector = pgoff * PAGE_SECTORS; | ||
361 | struct stripe_c *sc = ti->private; | ||
362 | struct dax_device *dax_dev; | ||
363 | struct block_device *bdev; | ||
364 | uint32_t stripe; | ||
365 | |||
366 | stripe_map_sector(sc, sector, &stripe, &dev_sector); | ||
367 | dev_sector += sc->stripe[stripe].physical_start; | ||
368 | dax_dev = sc->stripe[stripe].dev->dax_dev; | ||
369 | bdev = sc->stripe[stripe].dev->bdev; | ||
370 | |||
371 | if (bdev_dax_pgoff(bdev, dev_sector, ALIGN(bytes, PAGE_SIZE), &pgoff)) | ||
372 | return 0; | ||
373 | return dax_copy_to_iter(dax_dev, pgoff, addr, bytes, i); | ||
374 | } | ||
375 | |||
357 | #else | 376 | #else |
358 | #define stripe_dax_direct_access NULL | 377 | #define stripe_dax_direct_access NULL |
359 | #define stripe_dax_copy_from_iter NULL | 378 | #define stripe_dax_copy_from_iter NULL |
379 | #define stripe_dax_copy_to_iter NULL | ||
360 | #endif | 380 | #endif |
361 | 381 | ||
362 | /* | 382 | /* |
@@ -478,6 +498,7 @@ static struct target_type stripe_target = { | |||
478 | .io_hints = stripe_io_hints, | 498 | .io_hints = stripe_io_hints, |
479 | .direct_access = stripe_dax_direct_access, | 499 | .direct_access = stripe_dax_direct_access, |
480 | .dax_copy_from_iter = stripe_dax_copy_from_iter, | 500 | .dax_copy_from_iter = stripe_dax_copy_from_iter, |
501 | .dax_copy_to_iter = stripe_dax_copy_to_iter, | ||
481 | }; | 502 | }; |
482 | 503 | ||
483 | int __init dm_stripe_init(void) | 504 | int __init dm_stripe_init(void) |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 0a7b0107ca78..6752f1c25258 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -1089,6 +1089,30 @@ static size_t dm_dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, | |||
1089 | return ret; | 1089 | return ret; |
1090 | } | 1090 | } |
1091 | 1091 | ||
1092 | static size_t dm_dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, | ||
1093 | void *addr, size_t bytes, struct iov_iter *i) | ||
1094 | { | ||
1095 | struct mapped_device *md = dax_get_private(dax_dev); | ||
1096 | sector_t sector = pgoff * PAGE_SECTORS; | ||
1097 | struct dm_target *ti; | ||
1098 | long ret = 0; | ||
1099 | int srcu_idx; | ||
1100 | |||
1101 | ti = dm_dax_get_live_target(md, sector, &srcu_idx); | ||
1102 | |||
1103 | if (!ti) | ||
1104 | goto out; | ||
1105 | if (!ti->type->dax_copy_to_iter) { | ||
1106 | ret = copy_to_iter(addr, bytes, i); | ||
1107 | goto out; | ||
1108 | } | ||
1109 | ret = ti->type->dax_copy_to_iter(ti, pgoff, addr, bytes, i); | ||
1110 | out: | ||
1111 | dm_put_live_table(md, srcu_idx); | ||
1112 | |||
1113 | return ret; | ||
1114 | } | ||
1115 | |||
1092 | /* | 1116 | /* |
1093 | * A target may call dm_accept_partial_bio only from the map routine. It is | 1117 | * A target may call dm_accept_partial_bio only from the map routine. It is |
1094 | * allowed for all bio types except REQ_PREFLUSH and REQ_OP_ZONE_RESET. | 1118 | * allowed for all bio types except REQ_PREFLUSH and REQ_OP_ZONE_RESET. |
@@ -3134,6 +3158,7 @@ static const struct block_device_operations dm_blk_dops = { | |||
3134 | static const struct dax_operations dm_dax_ops = { | 3158 | static const struct dax_operations dm_dax_ops = { |
3135 | .direct_access = dm_dax_direct_access, | 3159 | .direct_access = dm_dax_direct_access, |
3136 | .copy_from_iter = dm_dax_copy_from_iter, | 3160 | .copy_from_iter = dm_dax_copy_from_iter, |
3161 | .copy_to_iter = dm_dax_copy_to_iter, | ||
3137 | }; | 3162 | }; |
3138 | 3163 | ||
3139 | /* | 3164 | /* |
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index e023d6aa22b5..1b8ab48365de 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c | |||
@@ -264,9 +264,16 @@ static size_t pmem_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, | |||
264 | return copy_from_iter_flushcache(addr, bytes, i); | 264 | return copy_from_iter_flushcache(addr, bytes, i); |
265 | } | 265 | } |
266 | 266 | ||
267 | static size_t pmem_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, | ||
268 | void *addr, size_t bytes, struct iov_iter *i) | ||
269 | { | ||
270 | return copy_to_iter(addr, bytes, i); | ||
271 | } | ||
272 | |||
267 | static const struct dax_operations pmem_dax_ops = { | 273 | static const struct dax_operations pmem_dax_ops = { |
268 | .direct_access = pmem_dax_direct_access, | 274 | .direct_access = pmem_dax_direct_access, |
269 | .copy_from_iter = pmem_copy_from_iter, | 275 | .copy_from_iter = pmem_copy_from_iter, |
276 | .copy_to_iter = pmem_copy_to_iter, | ||
270 | }; | 277 | }; |
271 | 278 | ||
272 | static const struct attribute_group *pmem_attribute_groups[] = { | 279 | static const struct attribute_group *pmem_attribute_groups[] = { |
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 0a312e450207..29024492b8ed 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
@@ -51,9 +51,16 @@ static size_t dcssblk_dax_copy_from_iter(struct dax_device *dax_dev, | |||
51 | return copy_from_iter(addr, bytes, i); | 51 | return copy_from_iter(addr, bytes, i); |
52 | } | 52 | } |
53 | 53 | ||
54 | static size_t dcssblk_dax_copy_to_iter(struct dax_device *dax_dev, | ||
55 | pgoff_t pgoff, void *addr, size_t bytes, struct iov_iter *i) | ||
56 | { | ||
57 | return copy_to_iter(addr, bytes, i); | ||
58 | } | ||
59 | |||
54 | static const struct dax_operations dcssblk_dax_ops = { | 60 | static const struct dax_operations dcssblk_dax_ops = { |
55 | .direct_access = dcssblk_dax_direct_access, | 61 | .direct_access = dcssblk_dax_direct_access, |
56 | .copy_from_iter = dcssblk_dax_copy_from_iter, | 62 | .copy_from_iter = dcssblk_dax_copy_from_iter, |
63 | .copy_to_iter = dcssblk_dax_copy_to_iter, | ||
57 | }; | 64 | }; |
58 | 65 | ||
59 | struct dcssblk_dev_info { | 66 | struct dcssblk_dev_info { |
@@ -1057,7 +1057,8 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data, | |||
1057 | map_len = dax_copy_from_iter(dax_dev, pgoff, kaddr, | 1057 | map_len = dax_copy_from_iter(dax_dev, pgoff, kaddr, |
1058 | map_len, iter); | 1058 | map_len, iter); |
1059 | else | 1059 | else |
1060 | map_len = copy_to_iter(kaddr, map_len, iter); | 1060 | map_len = dax_copy_to_iter(dax_dev, pgoff, kaddr, |
1061 | map_len, iter); | ||
1061 | if (map_len <= 0) { | 1062 | if (map_len <= 0) { |
1062 | ret = map_len ? map_len : -EFAULT; | 1063 | ret = map_len ? map_len : -EFAULT; |
1063 | break; | 1064 | break; |
diff --git a/include/linux/dax.h b/include/linux/dax.h index f9eb22ad341e..a43b396fb336 100644 --- a/include/linux/dax.h +++ b/include/linux/dax.h | |||
@@ -20,6 +20,9 @@ struct dax_operations { | |||
20 | /* copy_from_iter: required operation for fs-dax direct-i/o */ | 20 | /* copy_from_iter: required operation for fs-dax direct-i/o */ |
21 | size_t (*copy_from_iter)(struct dax_device *, pgoff_t, void *, size_t, | 21 | size_t (*copy_from_iter)(struct dax_device *, pgoff_t, void *, size_t, |
22 | struct iov_iter *); | 22 | struct iov_iter *); |
23 | /* copy_to_iter: required operation for fs-dax direct-i/o */ | ||
24 | size_t (*copy_to_iter)(struct dax_device *, pgoff_t, void *, size_t, | ||
25 | struct iov_iter *); | ||
23 | }; | 26 | }; |
24 | 27 | ||
25 | extern struct attribute_group dax_attribute_group; | 28 | extern struct attribute_group dax_attribute_group; |
@@ -118,6 +121,8 @@ long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages, | |||
118 | void **kaddr, pfn_t *pfn); | 121 | void **kaddr, pfn_t *pfn); |
119 | size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, | 122 | size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, |
120 | size_t bytes, struct iov_iter *i); | 123 | size_t bytes, struct iov_iter *i); |
124 | size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, | ||
125 | size_t bytes, struct iov_iter *i); | ||
121 | void dax_flush(struct dax_device *dax_dev, void *addr, size_t size); | 126 | void dax_flush(struct dax_device *dax_dev, void *addr, size_t size); |
122 | 127 | ||
123 | ssize_t dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter, | 128 | ssize_t dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter, |
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 31fef7c34185..6fb0808e87c8 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h | |||
@@ -133,7 +133,7 @@ typedef int (*dm_busy_fn) (struct dm_target *ti); | |||
133 | */ | 133 | */ |
134 | typedef long (*dm_dax_direct_access_fn) (struct dm_target *ti, pgoff_t pgoff, | 134 | typedef long (*dm_dax_direct_access_fn) (struct dm_target *ti, pgoff_t pgoff, |
135 | long nr_pages, void **kaddr, pfn_t *pfn); | 135 | long nr_pages, void **kaddr, pfn_t *pfn); |
136 | typedef size_t (*dm_dax_copy_from_iter_fn)(struct dm_target *ti, pgoff_t pgoff, | 136 | typedef size_t (*dm_dax_copy_iter_fn)(struct dm_target *ti, pgoff_t pgoff, |
137 | void *addr, size_t bytes, struct iov_iter *i); | 137 | void *addr, size_t bytes, struct iov_iter *i); |
138 | #define PAGE_SECTORS (PAGE_SIZE / 512) | 138 | #define PAGE_SECTORS (PAGE_SIZE / 512) |
139 | 139 | ||
@@ -184,7 +184,8 @@ struct target_type { | |||
184 | dm_iterate_devices_fn iterate_devices; | 184 | dm_iterate_devices_fn iterate_devices; |
185 | dm_io_hints_fn io_hints; | 185 | dm_io_hints_fn io_hints; |
186 | dm_dax_direct_access_fn direct_access; | 186 | dm_dax_direct_access_fn direct_access; |
187 | dm_dax_copy_from_iter_fn dax_copy_from_iter; | 187 | dm_dax_copy_iter_fn dax_copy_from_iter; |
188 | dm_dax_copy_iter_fn dax_copy_to_iter; | ||
188 | 189 | ||
189 | /* For internal device-mapper use. */ | 190 | /* For internal device-mapper use. */ |
190 | struct list_head list; | 191 | struct list_head list; |