diff options
-rw-r--r-- | drivers/md/dm-log-writes.c | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c index 34b9b4146021..189badbeddaf 100644 --- a/drivers/md/dm-log-writes.c +++ b/drivers/md/dm-log-writes.c | |||
@@ -10,9 +10,11 @@ | |||
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/blkdev.h> | 11 | #include <linux/blkdev.h> |
12 | #include <linux/bio.h> | 12 | #include <linux/bio.h> |
13 | #include <linux/dax.h> | ||
13 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
14 | #include <linux/kthread.h> | 15 | #include <linux/kthread.h> |
15 | #include <linux/freezer.h> | 16 | #include <linux/freezer.h> |
17 | #include <linux/uio.h> | ||
16 | 18 | ||
17 | #define DM_MSG_PREFIX "log-writes" | 19 | #define DM_MSG_PREFIX "log-writes" |
18 | 20 | ||
@@ -608,6 +610,51 @@ static int log_mark(struct log_writes_c *lc, char *data) | |||
608 | return 0; | 610 | return 0; |
609 | } | 611 | } |
610 | 612 | ||
613 | static int log_dax(struct log_writes_c *lc, sector_t sector, size_t bytes, | ||
614 | struct iov_iter *i) | ||
615 | { | ||
616 | struct pending_block *block; | ||
617 | |||
618 | if (!bytes) | ||
619 | return 0; | ||
620 | |||
621 | block = kzalloc(sizeof(struct pending_block), GFP_KERNEL); | ||
622 | if (!block) { | ||
623 | DMERR("Error allocating dax pending block"); | ||
624 | return -ENOMEM; | ||
625 | } | ||
626 | |||
627 | block->data = kzalloc(bytes, GFP_KERNEL); | ||
628 | if (!block->data) { | ||
629 | DMERR("Error allocating dax data space"); | ||
630 | kfree(block); | ||
631 | return -ENOMEM; | ||
632 | } | ||
633 | |||
634 | /* write data provided via the iterator */ | ||
635 | if (!copy_from_iter(block->data, bytes, i)) { | ||
636 | DMERR("Error copying dax data"); | ||
637 | kfree(block->data); | ||
638 | kfree(block); | ||
639 | return -EIO; | ||
640 | } | ||
641 | |||
642 | /* rewind the iterator so that the block driver can use it */ | ||
643 | iov_iter_revert(i, bytes); | ||
644 | |||
645 | block->datalen = bytes; | ||
646 | block->sector = bio_to_dev_sectors(lc, sector); | ||
647 | block->nr_sectors = ALIGN(bytes, lc->sectorsize) >> lc->sectorshift; | ||
648 | |||
649 | atomic_inc(&lc->pending_blocks); | ||
650 | spin_lock_irq(&lc->blocks_lock); | ||
651 | list_add_tail(&block->list, &lc->unflushed_blocks); | ||
652 | spin_unlock_irq(&lc->blocks_lock); | ||
653 | wake_up_process(lc->log_kthread); | ||
654 | |||
655 | return 0; | ||
656 | } | ||
657 | |||
611 | static void log_writes_dtr(struct dm_target *ti) | 658 | static void log_writes_dtr(struct dm_target *ti) |
612 | { | 659 | { |
613 | struct log_writes_c *lc = ti->private; | 660 | struct log_writes_c *lc = ti->private; |
@@ -873,9 +920,46 @@ static void log_writes_io_hints(struct dm_target *ti, struct queue_limits *limit | |||
873 | limits->io_min = limits->physical_block_size; | 920 | limits->io_min = limits->physical_block_size; |
874 | } | 921 | } |
875 | 922 | ||
923 | static long log_writes_dax_direct_access(struct dm_target *ti, pgoff_t pgoff, | ||
924 | long nr_pages, void **kaddr, pfn_t *pfn) | ||
925 | { | ||
926 | struct log_writes_c *lc = ti->private; | ||
927 | sector_t sector = pgoff * PAGE_SECTORS; | ||
928 | int ret; | ||
929 | |||
930 | ret = bdev_dax_pgoff(lc->dev->bdev, sector, nr_pages * PAGE_SIZE, &pgoff); | ||
931 | if (ret) | ||
932 | return ret; | ||
933 | return dax_direct_access(lc->dev->dax_dev, pgoff, nr_pages, kaddr, pfn); | ||
934 | } | ||
935 | |||
936 | static size_t log_writes_dax_copy_from_iter(struct dm_target *ti, | ||
937 | pgoff_t pgoff, void *addr, size_t bytes, | ||
938 | struct iov_iter *i) | ||
939 | { | ||
940 | struct log_writes_c *lc = ti->private; | ||
941 | sector_t sector = pgoff * PAGE_SECTORS; | ||
942 | int err; | ||
943 | |||
944 | if (bdev_dax_pgoff(lc->dev->bdev, sector, ALIGN(bytes, PAGE_SIZE), &pgoff)) | ||
945 | return 0; | ||
946 | |||
947 | /* Don't bother doing anything if logging has been disabled */ | ||
948 | if (!lc->logging_enabled) | ||
949 | goto dax_copy; | ||
950 | |||
951 | err = log_dax(lc, sector, bytes, i); | ||
952 | if (err) { | ||
953 | DMWARN("Error %d logging DAX write", err); | ||
954 | return 0; | ||
955 | } | ||
956 | dax_copy: | ||
957 | return dax_copy_from_iter(lc->dev->dax_dev, pgoff, addr, bytes, i); | ||
958 | } | ||
959 | |||
876 | static struct target_type log_writes_target = { | 960 | static struct target_type log_writes_target = { |
877 | .name = "log-writes", | 961 | .name = "log-writes", |
878 | .version = {1, 0, 0}, | 962 | .version = {1, 1, 0}, |
879 | .module = THIS_MODULE, | 963 | .module = THIS_MODULE, |
880 | .ctr = log_writes_ctr, | 964 | .ctr = log_writes_ctr, |
881 | .dtr = log_writes_dtr, | 965 | .dtr = log_writes_dtr, |
@@ -886,6 +970,8 @@ static struct target_type log_writes_target = { | |||
886 | .message = log_writes_message, | 970 | .message = log_writes_message, |
887 | .iterate_devices = log_writes_iterate_devices, | 971 | .iterate_devices = log_writes_iterate_devices, |
888 | .io_hints = log_writes_io_hints, | 972 | .io_hints = log_writes_io_hints, |
973 | .direct_access = log_writes_dax_direct_access, | ||
974 | .dax_copy_from_iter = log_writes_dax_copy_from_iter, | ||
889 | }; | 975 | }; |
890 | 976 | ||
891 | static int __init dm_log_writes_init(void) | 977 | static int __init dm_log_writes_init(void) |