This patch adds support for dax zero_page_range operation to dm targets.
Unified · Split
| @@ -201,10 +201,27 @@ static size_t linear_dax_copy_to_iter(struct dm_target *ti, pgoff_t pgoff, · 200 unmodified lines | ||
| 201 | 201 | return dax_copy_to_iter(dax_dev, pgoff, addr, bytes, i); |
| 202 | 202 | } |
| 203 | 203 | |
| 204 | +static int linear_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff, | |
| 205 | + size_t nr_pages) | |
| 206 | +{ | |
| 207 | + int ret; | |
| 208 | + struct linear_c *lc = ti->private; | |
| 209 | + struct block_device *bdev = lc->dev->bdev; | |
| 210 | + struct dax_device *dax_dev = lc->dev->dax_dev; | |
| 211 | + sector_t dev_sector, sector = pgoff * PAGE_SECTORS; | |
| 212 | + | |
| 213 | + dev_sector = linear_map_sector(ti, sector); | |
| 214 | + ret = bdev_dax_pgoff(bdev, dev_sector, nr_pages << PAGE_SHIFT, &pgoff); | |
| 215 | + if (ret) | |
| 216 | + return ret; | |
| 217 | + return dax_zero_page_range(dax_dev, pgoff, nr_pages); | |
| 218 | +} | |
| 219 | + | |
| 204 | 220 | #else |
| 205 | 221 | #define linear_dax_direct_access NULL |
| 206 | 222 | #define linear_dax_copy_from_iter NULL |
| 207 | 223 | #define linear_dax_copy_to_iter NULL |
| 224 | +#define linear_dax_zero_page_range NULL | |
| 208 | 225 | #endif |
| 209 | 226 | |
| 210 | 227 | static struct target_type linear_target = { |
| @@ -226,6 +243,7 @@ static struct target_type linear_target = { · 15 unmodified lines | ||
| 226 | 243 | .direct_access = linear_dax_direct_access, |
| 227 | 244 | .dax_copy_from_iter = linear_dax_copy_from_iter, |
| 228 | 245 | .dax_copy_to_iter = linear_dax_copy_to_iter, |
| 246 | + .dax_zero_page_range = linear_dax_zero_page_range, | |
| 229 | 247 | }; |
| 230 | 248 | |
| 231 | 249 | int __init dm_linear_init(void) |
| @@ -994,10 +994,26 @@ static size_t log_writes_dax_copy_to_iter(struct dm_target *ti, · 993 unmodified lines | ||
| 994 | 994 | return dax_copy_to_iter(lc->dev->dax_dev, pgoff, addr, bytes, i); |
| 995 | 995 | } |
| 996 | 996 | |
| 997 | +static int log_writes_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff, | |
| 998 | + size_t nr_pages) | |
| 999 | +{ | |
| 1000 | + int ret; | |
| 1001 | + struct log_writes_c *lc = ti->private; | |
| 1002 | + sector_t sector = pgoff * PAGE_SECTORS; | |
| 1003 | + | |
| 1004 | + ret = bdev_dax_pgoff(lc->dev->bdev, sector, nr_pages << PAGE_SHIFT, | |
| 1005 | + &pgoff); | |
| 1006 | + if (ret) | |
| 1007 | + return ret; | |
| 1008 | + return dax_zero_page_range(lc->dev->dax_dev, pgoff, | |
| 1009 | + nr_pages << PAGE_SHIFT); | |
| 1010 | +} | |
| 1011 | + | |
| 997 | 1012 | #else |
| 998 | 1013 | #define log_writes_dax_direct_access NULL |
| 999 | 1014 | #define log_writes_dax_copy_from_iter NULL |
| 1000 | 1015 | #define log_writes_dax_copy_to_iter NULL |
| 1016 | +#define log_writes_dax_zero_page_range NULL | |
| 1001 | 1017 | #endif |
| 1002 | 1018 | |
| 1003 | 1019 | static struct target_type log_writes_target = { |
| @@ -1016,6 +1032,7 @@ static struct target_type log_writes_target = { · 12 unmodified lines | ||
| 1016 | 1032 | .direct_access = log_writes_dax_direct_access, |
| 1017 | 1033 | .dax_copy_from_iter = log_writes_dax_copy_from_iter, |
| 1018 | 1034 | .dax_copy_to_iter = log_writes_dax_copy_to_iter, |
| 1035 | + .dax_zero_page_range = log_writes_dax_zero_page_range, | |
| 1019 | 1036 | }; |
| 1020 | 1037 | |
| 1021 | 1038 | static int __init dm_log_writes_init(void) |
| @@ -360,10 +360,32 @@ static size_t stripe_dax_copy_to_iter(struct dm_target *ti, pgoff_t pgoff, · 359 unmodified lines | ||
| 360 | 360 | return dax_copy_to_iter(dax_dev, pgoff, addr, bytes, i); |
| 361 | 361 | } |
| 362 | 362 | |
| 363 | +static int stripe_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff, | |
| 364 | + size_t nr_pages) | |
| 365 | +{ | |
| 366 | + int ret; | |
| 367 | + sector_t dev_sector, sector = pgoff * PAGE_SECTORS; | |
| 368 | + struct stripe_c *sc = ti->private; | |
| 369 | + struct dax_device *dax_dev; | |
| 370 | + struct block_device *bdev; | |
| 371 | + uint32_t stripe; | |
| 372 | + | |
| 373 | + stripe_map_sector(sc, sector, &stripe, &dev_sector); | |
| 374 | + dev_sector += sc->stripe[stripe].physical_start; | |
| 375 | + dax_dev = sc->stripe[stripe].dev->dax_dev; | |
| 376 | + bdev = sc->stripe[stripe].dev->bdev; | |
| 377 | + | |
| 378 | + ret = bdev_dax_pgoff(bdev, dev_sector, nr_pages << PAGE_SHIFT, &pgoff); | |
| 379 | + if (ret) | |
| 380 | + return ret; | |
| 381 | + return dax_zero_page_range(dax_dev, pgoff, nr_pages); | |
| 382 | +} | |
| 383 | + | |
| 363 | 384 | #else |
| 364 | 385 | #define stripe_dax_direct_access NULL |
| 365 | 386 | #define stripe_dax_copy_from_iter NULL |
| 366 | 387 | #define stripe_dax_copy_to_iter NULL |
| 388 | +#define stripe_dax_zero_page_range NULL | |
| 367 | 389 | #endif |
| 368 | 390 | |
| 369 | 391 | /* |
| @@ -486,6 +508,7 @@ static struct target_type stripe_target = { · 116 unmodified lines | ||
| 486 | 508 | .direct_access = stripe_dax_direct_access, |
| 487 | 509 | .dax_copy_from_iter = stripe_dax_copy_from_iter, |
| 488 | 510 | .dax_copy_to_iter = stripe_dax_copy_to_iter, |
| 511 | + .dax_zero_page_range = stripe_dax_zero_page_range, | |
| 489 | 512 | }; |
| 490 | 513 | |
| 491 | 514 | int __init dm_stripe_init(void) |
| @@ -1198,6 +1198,35 @@ static size_t dm_dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, · 1197 unmodified lines | ||
| 1198 | 1198 | return ret; |
| 1199 | 1199 | } |
| 1200 | 1200 | |
| 1201 | +static int dm_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, | |
| 1202 | + size_t nr_pages) | |
| 1203 | +{ | |
| 1204 | + struct mapped_device *md = dax_get_private(dax_dev); | |
| 1205 | + sector_t sector = pgoff * PAGE_SECTORS; | |
| 1206 | + struct dm_target *ti; | |
| 1207 | + int ret = -EIO; | |
| 1208 | + int srcu_idx; | |
| 1209 | + | |
| 1210 | + ti = dm_dax_get_live_target(md, sector, &srcu_idx); | |
| 1211 | + | |
| 1212 | + if (!ti) | |
| 1213 | + goto out; | |
| 1214 | + if (WARN_ON(!ti->type->dax_zero_page_range)) { | |
| 1215 | + /* | |
| 1216 | + * ->zero_page_range() is mandatory dax operation. If we are | |
| 1217 | + * here, something is wrong. | |
| 1218 | + */ | |
| 1219 | + dm_put_live_table(md, srcu_idx); | |
| 1220 | + goto out; | |
| 1221 | + } | |
| 1222 | + ret = ti->type->dax_zero_page_range(ti, pgoff, nr_pages); | |
| 1223 | + | |
| 1224 | + out: | |
| 1225 | + dm_put_live_table(md, srcu_idx); | |
| 1226 | + | |
| 1227 | + return ret; | |
| 1228 | +} | |
| 1229 | + | |
| 1201 | 1230 | /* |
| 1202 | 1231 | * A target may call dm_accept_partial_bio only from the map routine. It is |
| 1203 | 1232 | * allowed for all bio types except REQ_PREFLUSH, REQ_OP_ZONE_RESET, |
| @@ -3199,6 +3228,7 @@ static const struct dax_operations dm_dax_ops = { · 1995 unmodified lines | ||
| 3199 | 3228 | .dax_supported = dm_dax_supported, |
| 3200 | 3229 | .copy_from_iter = dm_dax_copy_from_iter, |
| 3201 | 3230 | .copy_to_iter = dm_dax_copy_to_iter, |
| 3231 | + .zero_page_range = dm_dax_zero_page_range, | |
| 3202 | 3232 | }; |
| 3203 | 3233 | |
| 3204 | 3234 | /* |
| @@ -141,6 +141,8 @@ typedef long (*dm_dax_direct_access_fn) (struct dm_target *ti, pgoff_t pgoff, · 140 unmodified lines | ||
| 141 | 141 | long nr_pages, void **kaddr, pfn_t *pfn); |
| 142 | 142 | typedef size_t (*dm_dax_copy_iter_fn)(struct dm_target *ti, pgoff_t pgoff, |
| 143 | 143 | void *addr, size_t bytes, struct iov_iter *i); |
| 144 | +typedef int (*dm_dax_zero_page_range_fn)(struct dm_target *ti, pgoff_t pgoff, | |
| 145 | + size_t nr_pages); | |
| 144 | 146 | #define PAGE_SECTORS (PAGE_SIZE / 512) |
| 145 | 147 | |
| 146 | 148 | void dm_error(const char *message); |
| @@ -195,6 +197,7 @@ struct target_type { · 48 unmodified lines | ||
| 195 | 197 | dm_dax_direct_access_fn direct_access; |
| 196 | 198 | dm_dax_copy_iter_fn dax_copy_from_iter; |
| 197 | 199 | dm_dax_copy_iter_fn dax_copy_to_iter; |
| 200 | + dm_dax_zero_page_range_fn dax_zero_page_range; | |
| 198 | 201 | |
| 199 | 202 | /* For internal device-mapper use. */ |
| 200 | 203 | struct list_head list; |