Skip to contentSkip to conversation

dm log writes: Add support for inline data buffers

PATCH In review Ross Zwisler 5 participants 19 messages Oct 20, 2017 – Nov 16, 2017

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/2 dm log writes: Add support for inline data buffers

Currently dm-log-writes supports writing filesystem data via BIOs, and writing internal metadata from a flat buffer via write_metadata().

For DAX writes, though, we won't have a BIO, but will instead have an iterator that we'll want to use to fill a flat data buffer.

So, create write_inline_data() which allows us to write filesystem data using a flat buffer as a source, and wire it up in log_one_block().

---
 drivers/md/dm-log-writes.c | 90 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 86 insertions(+), 4 deletions(-)
drivers/md/dm-log-writes.c +86 -4
index 8b80a9c..c65f9d1 100644
@@ -246,27 +246,109 @@ static int write_metadata(struct log_writes_c *lc, void *entry,
 	return -1;
 }
 
+static int write_inline_data(struct log_writes_c *lc, void *entry,
+			  size_t entrylen, void *data, size_t datalen,
+			  sector_t sector)
+{
+	int num_pages, bio_pages, pg_datalen, pg_sectorlen, i;
+	struct page *page;
+	struct bio *bio;
+	size_t ret;
+	void *ptr;
+
+	while (datalen) {
+		num_pages = ALIGN(datalen, PAGE_SIZE) >> PAGE_SHIFT;
+		bio_pages = min(num_pages, BIO_MAX_PAGES);
+
+		atomic_inc(&lc->io_blocks);
+
+		bio = bio_alloc(GFP_KERNEL, bio_pages);
+		if (!bio) {
+			DMERR("Couldn't alloc inline data bio");
+			goto error;
+		}
+
+		bio->bi_iter.bi_size = 0;
+		bio->bi_iter.bi_sector = sector;
+		bio_set_dev(bio, lc->logdev->bdev);
+		bio->bi_end_io = log_end_io;
+		bio->bi_private = lc;
+		bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
+
+		for (i = 0; i < bio_pages; i++) {
+			pg_datalen = min(datalen, PAGE_SIZE);
+			pg_sectorlen = ALIGN(pg_datalen, lc->sectorsize);
+
+			page = alloc_page(GFP_KERNEL);
+			if (!page) {
+				DMERR("Couldn't alloc inline data page");
+				goto error_bio;
+			}
+
+			ptr = kmap_atomic(page);
+			memcpy(ptr, data, pg_datalen);
+			if (pg_sectorlen > pg_datalen)
+				memset(ptr + pg_datalen, 0,
+						pg_sectorlen - pg_datalen);
+			kunmap_atomic(ptr);
+
+			ret = bio_add_page(bio, page, pg_sectorlen, 0);
+			if (ret != pg_sectorlen) {
+				DMERR("Couldn't add page of inline data");
+				__free_page(page);
+				goto error_bio;
+			}
+
+			datalen -= pg_datalen;
+			data	+= pg_datalen;
+		}
+		submit_bio(bio);
+
+		sector += bio_pages * PAGE_SECTORS;
+	}
+	return 0;
+error_bio:
+	bio_free_pages(bio);
+	bio_put(bio);
+error:
+	put_io_block(lc);
+	return -1;
+}
+
 static int log_one_block(struct log_writes_c *lc,
 			 struct pending_block *block, sector_t sector)
 {
 	struct bio *bio;
 	struct log_write_entry entry;
-	size_t ret;
+	size_t metadlen, ret;
 	int i;
 
 	entry.sector = cpu_to_le64(block->sector);
 	entry.nr_sectors = cpu_to_le64(block->nr_sectors);
 	entry.flags = cpu_to_le64(block->flags);
 	entry.data_len = cpu_to_le64(block->datalen);
-	if (write_metadata(lc, &entry, sizeof(entry), block->data,
-			   block->datalen, sector)) {
+
+	metadlen = (block->flags & LOG_MARK_FLAG) ?  block->datalen : 0;
+	if (write_metadata(lc, &entry, sizeof(entry), block->data, metadlen,
+				sector)) {
 		free_pending_block(lc, block);
 		return -1;
 	}
 
+	sector += dev_to_bio_sectors(lc, 1);
+
+	if (block->datalen && metadlen == 0) {
+		if (write_inline_data(lc, &entry, sizeof(entry), block->data,
+					block->datalen, sector)) {
+			free_pending_block(lc, block);
+			return -1;
+		}
+		/* we don't support both inline data & bio data */
+		goto out;
+	}
+
 	if (!block->vec_cnt)
 		goto out;
-	sector += dev_to_bio_sectors(lc, 1);
 
 	atomic_inc(&lc->io_blocks);
 	bio = bio_alloc(GFP_KERNEL, min(block->vec_cnt, BIO_MAX_PAGES));
Signature · 6 lines
2.9.5

_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
#1 lore raw

PATCH 2/2 dm log writes: add support for DAX

Now that we have the ability log filesystem writes using a flat buffer, add support for DAX. Unfortunately we can't easily track data that has been written via mmap() now that the dax_flush() abstraction was removed by this commit:

commit c3ca015fab6d ("dax: remove the pmem_dax_ops->flush abstraction")

Otherwise we could just treat each flush as a big write, and store the data that is being synced to media. It may be worthwhile to add the dax_flush() entry point back, just as a notifier so we can do this logging.

The motivation for this support is the need for an xfstest that can test the new MAP_SYNC DAX flag. By logging the filesystem activity with dm-log-writes we can show that the MAP_SYNC page faults are writing out their metadata as they happen, instead of requiring an explicit msync/fsync.

---

Here's a link to Jan's latest MAP_SYNC set, which can be used for the fstest:

https://www.spinics.net/lists/linux-xfs/msg11852.html

MAP_SYNC is not needed for basic DAX+dm-log-writes functionality.

---
 drivers/md/dm-log-writes.c | 90 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 89 insertions(+), 1 deletion(-)
drivers/md/dm-log-writes.c +89 -1
index c65f9d1..6a8d352 100644
@@ -10,9 +10,11 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/bio.h>
+#include <linux/dax.h>
 #include <linux/slab.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
+#include <linux/uio.h>
 
 #define DM_MSG_PREFIX "log-writes"
 
@@ -609,6 +611,50 @@ static int log_mark(struct log_writes_c *lc, char *data)
 	return 0;
 }
 
+static int log_dax(struct log_writes_c *lc, sector_t sector, size_t bytes,
+		struct iov_iter *i)
+{
+	struct pending_block *block;
+
+	if (!bytes)
+		return 0;
+
+	block = kzalloc(sizeof(struct pending_block), GFP_KERNEL);
+	if (!block) {
+		DMERR("Error allocating dax pending block");
+		return -ENOMEM;
+	}
+
+	block->data = kzalloc(bytes, GFP_KERNEL);
+	if (!block->data) {
+		DMERR("Error allocating dax data space");
+		kfree(block);
+		return -ENOMEM;
+	}
+
+	/* write data provided via the iterator */
+	if (!copy_from_iter(block->data, bytes, i)) {
+		DMERR("Error copying dax data");
+		kfree(block->data);
+		kfree(block);
+		return -EIO;
+	}
+
+	/* rewind the iterator so that the block driver can use it */
+	iov_iter_revert(i, bytes);
+
+	block->datalen = bytes;
+	block->sector = bio_to_dev_sectors(lc, sector);
+	block->nr_sectors = ALIGN(bytes, lc->sectorsize) >> lc->sectorshift;
+
+	atomic_inc(&lc->pending_blocks);
+	spin_lock_irq(&lc->blocks_lock);
+	list_add_tail(&block->list, &lc->unflushed_blocks);
+	spin_unlock_irq(&lc->blocks_lock);
+	wake_up_process(lc->log_kthread);
+	return 0;
+}
+
 static void log_writes_dtr(struct dm_target *ti)
 {
 	struct log_writes_c *lc = ti->private;
@@ -874,9 +920,49 @@ static void log_writes_io_hints(struct dm_target *ti, struct queue_limits *limit
 	limits->io_min = limits->physical_block_size;
 }
 
+static long log_writes_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
+		long nr_pages, void **kaddr, pfn_t *pfn)
+{
+	struct log_writes_c *lc = ti->private;
+	struct block_device *bdev = lc->dev->bdev;
+	struct dax_device *dax_dev = lc->dev->dax_dev;
+	sector_t sector = pgoff * PAGE_SECTORS;
+	int ret;
+
+	ret = bdev_dax_pgoff(bdev, sector, nr_pages * PAGE_SIZE, &pgoff);
+	if (ret)
+		return ret;
+	return dax_direct_access(dax_dev, pgoff, nr_pages, kaddr, pfn);
+}
+
+static size_t log_writes_dax_copy_from_iter(struct dm_target *ti,
+		pgoff_t pgoff, void *addr, size_t bytes, struct iov_iter *i)
+{
+	struct log_writes_c *lc = ti->private;
+	struct block_device *bdev = lc->dev->bdev;
+	struct dax_device *dax_dev = lc->dev->dax_dev;
+	sector_t sector = pgoff * PAGE_SECTORS;
+	int err;
+
+	if (bdev_dax_pgoff(bdev, sector, ALIGN(bytes, PAGE_SIZE), &pgoff))
+		return 0;
+
+	/* Don't bother doing anything if logging has been disabled */
+	if (!lc->logging_enabled)
+		goto dax_copy;
+
+	err = log_dax(lc, sector, bytes, i);
+	if (err) {
+		DMWARN("Error %d logging DAX write", err);
+		return 0;
+	}
+dax_copy:
+	return dax_copy_from_iter(dax_dev, pgoff, addr, bytes, i);
+}
+
 static struct target_type log_writes_target = {
 	.name   = "log-writes",
-	.version = {1, 0, 0},
+	.version = {1, 0, 1},
 	.module = THIS_MODULE,
 	.ctr    = log_writes_ctr,
 	.dtr    = log_writes_dtr,
@@ -887,6 +973,8 @@ static struct target_type log_writes_target = {
 	.message = log_writes_message,
 	.iterate_devices = log_writes_iterate_devices,
 	.io_hints = log_writes_io_hints,
+	.direct_access = log_writes_dax_direct_access,
+	.dax_copy_from_iter = log_writes_dax_copy_from_iter,
 };
 
 static int __init dm_log_writes_init(void)
Signature · 6 lines
2.9.5

_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
#2 lore raw

Re: [PATCH 2/2] dm log writes: add support for DAX

Quoted 11 lines · Ross Zwisler

Now that we have the ability log filesystem writes using a flat buffer, add support for DAX. Unfortunately we can't easily track data that has been written via mmap() now that the dax_flush() abstraction was removed by this commit:

commit c3ca015fab6d ("dax: remove the pmem_dax_ops->flush abstraction")

Otherwise we could just treat each flush as a big write, and store the data that is being synced to media. It may be worthwhile to add the dax_flush() entry point back, just as a notifier so we can do this logging.

Quoted 8 lines

The motivation for this support is the need for an xfstest that can test the new MAP_SYNC DAX flag. By logging the filesystem activity with dm-log-writes we can show that the MAP_SYNC page faults are writing out their metadata as they happen, instead of requiring an explicit msync/fsync.

---

Ok this is just my ignorance of how DAX works shining through, but do we need a new flag to indicate this is DAX data? You are logging it like it's just normal data going to a certain sector, is that good enough? If it is then hooray this looks fine to me, I'm just slightly confused. Thanks,

Josef
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

#3 lore raw

Re: [PATCH 2/2] dm log writes: add support for DAX

Quoted 21 lines · Josef Bacik
Quoted 11 lines · Ross Zwisler

Now that we have the ability log filesystem writes using a flat buffer, add support for DAX. Unfortunately we can't easily track data that has been written via mmap() now that the dax_flush() abstraction was removed by this commit:

commit c3ca015fab6d ("dax: remove the pmem_dax_ops->flush abstraction")

Otherwise we could just treat each flush as a big write, and store the data that is being synced to media. It may be worthwhile to add the dax_flush() entry point back, just as a notifier so we can do this logging.

Quoted 8 lines

The motivation for this support is the need for an xfstest that can test the new MAP_SYNC DAX flag. By logging the filesystem activity with dm-log-writes we can show that the MAP_SYNC page faults are writing out their metadata as they happen, instead of requiring an explicit msync/fsync.

---

Quoted 6 lines

Ok this is just my ignorance of how DAX works shining through, but do we need a new flag to indicate this is DAX data? You are logging it like it's just normal data going to a certain sector, is that good enough? If it is then hooray this looks fine to me, I'm just slightly confused. Thanks,

Josef

I don't think we need a special flag to specify that it's DAX. Really it's just the same as a normal filesystem write, except that we actually do the work of writing the data via the FS DAX iomap code instead of bubbling it all the way down to the block driver.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

#4 lore raw

Re: [PATCH 2/2] dm log writes: add support for DAX

In reply to Ross Zwisler
Quoted 11 lines · Ross Zwisler

Now that we have the ability log filesystem writes using a flat buffer, add support for DAX. Unfortunately we can't easily track data that has been written via mmap() now that the dax_flush() abstraction was removed by this commit:

commit c3ca015fab6d ("dax: remove the pmem_dax_ops->flush abstraction")

Otherwise we could just treat each flush as a big write, and store the data that is being synced to media. It may be worthwhile to add the dax_flush() entry point back, just as a notifier so we can do this logging.

Quoted 7 lines

The motivation for this support is the need for an xfstest that can test the new MAP_SYNC DAX flag. By logging the filesystem activity with dm-log-writes we can show that the MAP_SYNC page faults are writing out their metadata as they happen, instead of requiring an explicit msync/fsync.

I've picked this up, please see:
https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=for-4.15/dm&id=ae613bbb0144e84cb3c0ebfa9f4fd4d1507c2f0e

I tweaked the header and tweaked a couple whitespace nits. Also switched version bump from 1.0.1 to 1.1.0.

Thanks,
Mike
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

#5 lore raw

Re: [PATCH 2/2] dm log writes: add support for DAX

Quoted 22 lines · Mike Snitzer
Quoted 11 lines · Ross Zwisler

Now that we have the ability log filesystem writes using a flat buffer, add support for DAX. Unfortunately we can't easily track data that has been written via mmap() now that the dax_flush() abstraction was removed by this commit:

commit c3ca015fab6d ("dax: remove the pmem_dax_ops->flush abstraction")

Otherwise we could just treat each flush as a big write, and store the data that is being synced to media. It may be worthwhile to add the dax_flush() entry point back, just as a notifier so we can do this logging.

Quoted 7 lines

The motivation for this support is the need for an xfstest that can test the new MAP_SYNC DAX flag. By logging the filesystem activity with dm-log-writes we can show that the MAP_SYNC page faults are writing out their metadata as they happen, instead of requiring an explicit msync/fsync.

Quoted 8 lines

I've picked this up, please see:
https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=for-4.15/dm&id=ae613bbb0144e84cb3c0ebfa9f4fd4d1507c2f0e

I tweaked the header and tweaked a couple whitespace nits. Also switched version bump from 1.0.1 to 1.1.0.

Thanks,
Mike

Sure, your tweaks look fine. Thanks!
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

#6 lore raw

PATCH 1/1 generic: add test for DAX MAP_SYNC support

In reply to Ross Zwisler

Add a test that exercises DAX's new MAP_SYNC flag.

This test creates a file and writes to it via an mmap(), but never syncs via fsync/msync. This process is tracked via dm-log-writes, then replayed.

If MAP_SYNC is working the dm-log-writes replay will show the test file with the same size that we wrote via the mmap() because each allocating page fault included an implicit metadata sync. If MAP_SYNC isn't working (which you can test by fiddling with the parameters to mmap()) the file will be smaller or missing entirely.

Note that dm-log-writes doesn't track the data that we write via the mmap(), so we can't do any data integrity checking. We can only verify that the metadata writes for the page faults happened.

---

For this test to run successfully you'll need both Jan's MAP_SYNC series:

https://www.spinics.net/lists/linux-xfs/msg11852.html

and my series adding DAX support to dm-log-writes:

https://lists.01.org/pipermail/linux-nvdimm/2017-October/012972.html

---
 .gitignore            |  1 +
 common/dmlogwrites    |  1 -
 src/Makefile          |  3 +-
 src/t_map_sync.c      | 74 +++++++++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466     | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466.out |  3 ++
 tests/generic/group   |  1 +
 7 files changed, 158 insertions(+), 2 deletions(-)
 create mode 100644 src/t_map_sync.c
 create mode 100755 tests/generic/466
 create mode 100644 tests/generic/466.out
.gitignore +1 -0
index 2014c08..9fc0695 100644
@@ -119,6 +119,7 @@
 /src/t_getcwd
 /src/t_holes
 /src/t_immutable
+/src/t_map_sync
 /src/t_mmap_cow_race
 /src/t_mmap_dio
 /src/t_mmap_fallocate
common/dmlogwrites +0 -1
index 247c744..5b57df9 100644
@@ -23,7 +23,6 @@ _require_log_writes()
 	[ -z "$LOGWRITES_DEV" -o ! -b "$LOGWRITES_DEV" ] && \
 		_notrun "This test requires a valid \$LOGWRITES_DEV"
 
-	_exclude_scratch_mount_option dax
 	_require_dm_target log-writes
 	_require_test_program "log-writes/replay-log"
 }
src/Makefile +2 -1
index 3eb25b1..af7e7e9 100644
@@ -13,7 +13,8 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
 	multi_open_unlink dmiperf unwritten_sync genhashnames t_holes \
 	t_mmap_writev t_truncate_cmtime dirhash_collide t_rename_overwrite \
 	holetest t_truncate_self t_mmap_dio af_unix t_mmap_stale_pmd \
-	t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro
+	t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro \
+	t_map_sync
 
 LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
 	preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
src/t_map_sync.c new file +74 -0

74 lines not on this page · raw message

tests/generic/466 new file +77 -0

77 lines not on this page · raw message

tests/generic/466.out new file +3 -0
new file mode 100644
index 0000000..4c54d7a
@@ -0,0 +1,3 @@
+QA output created by 466
+1.0M SCRATCH_MNT/test
+Silence is golden
tests/generic/group +1 -0
index fbe0a7f..65328c6 100644
@@ -468,3 +468,4 @@
 463 auto quick clone dangerous
 464 auto rw
 465 auto rw quick aio
+466 auto quick dax
Signature · 6 lines
2.9.5

_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
#7 lore raw

Re: [fstests PATCH] generic: add test for DAX MAP_SYNC support

Quoted 11 lines · Ross Zwisler

Add a test that exercises DAX's new MAP_SYNC flag.

This test creates a file and writes to it via an mmap(), but never syncs via fsync/msync. This process is tracked via dm-log-writes, then replayed.

If MAP_SYNC is working the dm-log-writes replay will show the test file with the same size that we wrote via the mmap() because each allocating page fault included an implicit metadata sync. If MAP_SYNC isn't working (which you can test by fiddling with the parameters to mmap()) the file will be smaller or missing entirely.

Quoted 5 lines

Note that dm-log-writes doesn't track the data that we write via the mmap(), so we can't do any data integrity checking. We can only verify that the metadata writes for the page faults happened.

Looks good. some nit picking...

Quoted 74 lines

---

For this test to run successfully you'll need both Jan's MAP_SYNC series:

https://www.spinics.net/lists/linux-xfs/msg11852.html

and my series adding DAX support to dm-log-writes:

https://lists.01.org/pipermail/linux-nvdimm/2017-October/012972.html

---
 .gitignore            |  1 +
 common/dmlogwrites    |  1 -
 src/Makefile          |  3 +-
 src/t_map_sync.c      | 74 +++++++++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466     | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466.out |  3 ++
 tests/generic/group   |  1 +
 7 files changed, 158 insertions(+), 2 deletions(-)
 create mode 100644 src/t_map_sync.c
 create mode 100755 tests/generic/466
 create mode 100644 tests/generic/466.out
.gitignore +1 -0
index 2014c08..9fc0695 100644
@@ -119,6 +119,7 @@
 /src/t_getcwd
 /src/t_holes
 /src/t_immutable
+/src/t_map_sync
 /src/t_mmap_cow_race
 /src/t_mmap_dio
 /src/t_mmap_fallocate
common/dmlogwrites +0 -1
index 247c744..5b57df9 100644
@@ -23,7 +23,6 @@ _require_log_writes()
        [ -z "$LOGWRITES_DEV" -o ! -b "$LOGWRITES_DEV" ] && \
                _notrun "This test requires a valid \$LOGWRITES_DEV"
 
-       _exclude_scratch_mount_option dax
        _require_dm_target log-writes
        _require_test_program "log-writes/replay-log"
 }
src/Makefile +2 -1
index 3eb25b1..af7e7e9 100644
@@ -13,7 +13,8 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
        multi_open_unlink dmiperf unwritten_sync genhashnames t_holes \
        t_mmap_writev t_truncate_cmtime dirhash_collide t_rename_overwrite \
        holetest t_truncate_self t_mmap_dio af_unix t_mmap_stale_pmd \
-       t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro
+       t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro \
+       t_map_sync
 
 LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
        preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
src/t_map_sync.c new file +7 -0
new file mode 100644
index 0000000..8190f3c
@@ -0,0 +1,74 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>

src/t_map_sync.c line 17

Quoted 10 lines
src/t_map_sync.c new file +10 -0
+#include <sys/types.h>
+#include <unistd.h>
+
+#define MiB(a) ((a)*1024*1024)
+
+/*
+ * These two defines were added to the kernel via commits entitled
+ * "mm: Define MAP_SYNC and VM_SYNC flags" and
+ * "mm: introduce MAP_SHARED_VALIDATE, a mechanism to safely define new mmap
+ * flags", respectively.

#ifndef?

Quoted 17 lines
src/t_map_sync.c new file +17 -0
+ */
+#define MAP_SYNC 0x80000
+#define MAP_SHARED_VALIDATE 0x3
+
+void err_exit(char *op)
+{
+       fprintf(stderr, "%s: %s\n", op, strerror(errno));
+       exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+       int page_size = getpagesize();
+       int len = MiB(1);
+       int i, fd, err;
+       char *data;
+

src/t_map_sync.c line 44

Quoted 10 lines
src/t_map_sync.c new file +10 -0
+       if (argc < 2) {
+               printf("Usage: %s <file>\n", basename(argv[0]));
+               exit(0);
+       }
+
+       fd = open(argv[1], O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
+       if (fd < 0)
+               err_exit("fd");
+
+       ftruncate(fd, 0);

O_TRUNC?

Quoted 10 lines
src/t_map_sync.c new file +10 -0
+       ftruncate(fd, len);
+
+       data = mmap(NULL, len, PROT_READ|PROT_WRITE,
+                       MAP_SHARED_VALIDATE|MAP_SYNC, fd, 0);
+       if (data == MAP_FAILED)
+               err_exit("mmap");
+
+       /*
+        * We intentionally don't sync 'fd' manually.  If MAP_SYNC is working
+        * these allocating page faults will cause the filesystem to sync its

src/t_map_sync.c line 64

Quoted 10 lines
src/t_map_sync.c new file +10 -0
+        * metadata so that when we replay the dm-log-writes log the test file
+        * will be 1 MiB in size.
+        *
+        * dm-log-writes doesn't track the data that we write via the mmap(),
+        * so we can't check that, we can only verify that the metadata writes
+        * happened.
+        */
+       for (i = 0; i < len; i+=page_size)
+               data[i] = 0xff;
+

Ideally, you would write the mark now (see mark_log() in fsx.c) Otherwise, what you are testing is not that page faults allocate disk blocks, but rather that page fault + munmap + close + process exit allocate disk blocks.
I realize munmap/close are not supposed to sync dirty pages, but better eliminate this noise from the test.

Quoted 66 lines
src/t_map_sync.c new file +10 -0
+       err = munmap(data, len);
+       if (err < 0)
+               err_exit("munmap");
+
+       err = close(fd);
+       if (err < 0)
+               err_exit("close");
+
+       return 0;
+}
tests/generic/466 new file +50 -0
new file mode 100755
index 0000000..f39e6dc
@@ -0,0 +1,77 @@
+#! /bin/bash
+# FS QA Test No. 466
+#
+# Use md_log_writes to verify that MAP_SYNC actually syncs metadata during
+# page faults.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2017 Intel Corporation.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1       # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+       _log_writes_cleanup
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/dmlogwrites
+
+# remove previous $seqres.full before test
+rm -f $seqres.full
+
+# real QA test starts here
+_supported_fs generic
+_supported_os Linux
+_require_log_writes
+_require_scratch_dax

tests/generic/466 line 60

Quoted 10 lines
tests/generic/466 new file +10 -0
+_require_test_program "t_map_sync"
+
+_log_writes_init
+_log_writes_mkfs >> $seqres.full 2>&1
+_log_writes_mount -o dax
+
+src/t_map_sync $SCRATCH_MNT/test
+
+# Unmount the scratch dir and tear down the log writes target
+_log_writes_mark last

Feel free to use the lousy name I chose for the pre_unmount mark ;-) but if you follow my suggestion to move the mark into t_map_sync better call it pre_munmap or something.

tests/generic/466 line 69

Quoted 9 lines
tests/generic/466 new file +9 -0
+_log_writes_unmount
+_log_writes_remove
+_check_scratch_fs
+
+# check pre umount
+_log_writes_replay_log last
+_scratch_mount
+
+# We should see $SCRATCH_MNT/test as 1MiB in size

nit: 1MiB in disk usage. it's 1MiB in size to begin with

Quoted 29 lines
tests/generic/466 new file +8 -0
+du -sh $SCRATCH_MNT/test | _filter_scratch | _filter_spaces
+
+_scratch_unmount
+_check_scratch_fs
+
+echo "Silence is golden"
+status=0
+exit
tests/generic/466.out new file +3 -0
new file mode 100644
index 0000000..4c54d7a
@@ -0,0 +1,3 @@
+QA output created by 466
+1.0M SCRATCH_MNT/test
+Silence is golden
tests/generic/group +1 -1
index fbe0a7f..65328c6 100644
@@ -468,3 +468,4 @@
 463 auto quick clone dangerous
 464 auto rw
 465 auto rw quick aio
+466 auto quick dax
--

2.9.5

Quoted 4 lines

--
To unsubscribe from this list: send the line "unsubscribe fstests" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

#8 lore raw

PATCH v2 1/1 generic: add test for DAX MAP_SYNC support

In reply to Ross Zwisler

Add a test that exercises DAX's new MAP_SYNC flag.

This test creates a file and writes to it via an mmap(), but never syncs via fsync/msync. This process is tracked via dm-log-writes, then replayed.

If MAP_SYNC is working the dm-log-writes replay will show the test file with 1MiB of on-media block allocations. This is because each allocating page fault included an implicit metadata sync. If MAP_SYNC isn't working (which you can test by fiddling with the parameters to mmap()) the file will be smaller or missing entirely.

Note that dm-log-writes doesn't track the data that we write via the mmap(), so we can't do any data integrity checking. We can only verify that the metadata writes for the page faults happened.

---

Changes since v1:
- Addressed review feedback from Amir. Thank you for the review!

---
 .gitignore            |  1 +
 common/dmlogwrites    |  1 -
 src/Makefile          |  3 +-
 src/t_map_sync.c      | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466     | 76 ++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466.out |  3 ++
 tests/generic/group   |  1 +
 7 files changed, 175 insertions(+), 2 deletions(-)
 create mode 100644 src/t_map_sync.c
 create mode 100755 tests/generic/466
 create mode 100644 tests/generic/466.out
.gitignore +1 -0
index 2014c08..9fc0695 100644
@@ -119,6 +119,7 @@
 /src/t_getcwd
 /src/t_holes
 /src/t_immutable
+/src/t_map_sync
 /src/t_mmap_cow_race
 /src/t_mmap_dio
 /src/t_mmap_fallocate
common/dmlogwrites +0 -1
index 247c744..5b57df9 100644
@@ -23,7 +23,6 @@ _require_log_writes()
 	[ -z "$LOGWRITES_DEV" -o ! -b "$LOGWRITES_DEV" ] && \
 		_notrun "This test requires a valid \$LOGWRITES_DEV"
 
-	_exclude_scratch_mount_option dax
 	_require_dm_target log-writes
 	_require_test_program "log-writes/replay-log"
 }
src/Makefile +2 -1
index 3eb25b1..af7e7e9 100644
@@ -13,7 +13,8 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
 	multi_open_unlink dmiperf unwritten_sync genhashnames t_holes \
 	t_mmap_writev t_truncate_cmtime dirhash_collide t_rename_overwrite \
 	holetest t_truncate_self t_mmap_dio af_unix t_mmap_stale_pmd \
-	t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro
+	t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro \
+	t_map_sync
 
 LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
 	preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
src/t_map_sync.c new file +92 -0

92 lines not on this page · raw message

tests/generic/466 new file +76 -0

76 lines not on this page · raw message

tests/generic/466.out new file +3 -0
new file mode 100644
index 0000000..4c54d7a
@@ -0,0 +1,3 @@
+QA output created by 466
+1.0M SCRATCH_MNT/test
+Silence is golden
tests/generic/group +1 -0
index fbe0a7f..65328c6 100644
@@ -468,3 +468,4 @@
 463 auto quick clone dangerous
 464 auto rw
 465 auto rw quick aio
+466 auto quick dax
Signature · 6 lines
2.9.5

_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
#9 lore raw

Re: [fstests PATCH v2] generic: add test for DAX MAP_SYNC support

Quoted 15 lines · Ross Zwisler

Add a test that exercises DAX's new MAP_SYNC flag.

This test creates a file and writes to it via an mmap(), but never syncs via fsync/msync. This process is tracked via dm-log-writes, then replayed.

If MAP_SYNC is working the dm-log-writes replay will show the test file with 1MiB of on-media block allocations. This is because each allocating page fault included an implicit metadata sync. If MAP_SYNC isn't working (which you can test by fiddling with the parameters to mmap()) the file will be smaller or missing entirely.

Note that dm-log-writes doesn't track the data that we write via the mmap(), so we can't do any data integrity checking. We can only verify that the metadata writes for the page faults happened.

Quoted 6 lines

---

Changes since v1:
- Addressed review feedback from Amir. Thank you for the review!

Looks good.

Quoted 251 lines
---
 .gitignore            |  1 +
 common/dmlogwrites    |  1 -
 src/Makefile          |  3 +-
 src/t_map_sync.c      | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466     | 76 ++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466.out |  3 ++
 tests/generic/group   |  1 +
 7 files changed, 175 insertions(+), 2 deletions(-)
 create mode 100644 src/t_map_sync.c
 create mode 100755 tests/generic/466
 create mode 100644 tests/generic/466.out
.gitignore +1 -0
index 2014c08..9fc0695 100644
@@ -119,6 +119,7 @@
 /src/t_getcwd
 /src/t_holes
 /src/t_immutable
+/src/t_map_sync
 /src/t_mmap_cow_race
 /src/t_mmap_dio
 /src/t_mmap_fallocate
common/dmlogwrites +0 -1
index 247c744..5b57df9 100644
@@ -23,7 +23,6 @@ _require_log_writes()
        [ -z "$LOGWRITES_DEV" -o ! -b "$LOGWRITES_DEV" ] && \
                _notrun "This test requires a valid \$LOGWRITES_DEV"
 
-       _exclude_scratch_mount_option dax
        _require_dm_target log-writes
        _require_test_program "log-writes/replay-log"
 }
src/Makefile +2 -1
index 3eb25b1..af7e7e9 100644
@@ -13,7 +13,8 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
        multi_open_unlink dmiperf unwritten_sync genhashnames t_holes \
        t_mmap_writev t_truncate_cmtime dirhash_collide t_rename_overwrite \
        holetest t_truncate_self t_mmap_dio af_unix t_mmap_stale_pmd \
-       t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro
+       t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro \
+       t_map_sync
 
 LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
        preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
src/t_map_sync.c new file +92 -0
new file mode 100644
index 0000000..29b546a
@@ -0,0 +1,92 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define MiB(a) ((a)*1024*1024)
+
+/*
+ * These two defines were added to the kernel via commits entitled
+ * "mm: Define MAP_SYNC and VM_SYNC flags" and
+ * "mm: introduce MAP_SHARED_VALIDATE, a mechanism to safely define new mmap
+ * flags", respectively.
+ */
+#ifndef MAP_SYNC
+#define MAP_SYNC 0x80000
+#endif
+
+#ifndef MAP_SHARED_VALIDATE
+#define MAP_SHARED_VALIDATE 0x3
+#endif
+
+void err_exit(char *op)
+{
+       fprintf(stderr, "%s: %s\n", op, strerror(errno));
+       exit(1);
+}
+
+void mark_log(char *logwrites_name, char *mark_name)
+{
+       char command[256];
+
+       snprintf(command, 256, "dmsetup message %s 0 mark %s",
+                       logwrites_name, mark_name);
+
+       if (system(command))
+               err_exit("mark_log");
+}
+
+int main(int argc, char *argv[])
+{
+       int page_size = getpagesize();
+       int len = MiB(1);
+       int i, fd, err;
+       char *data;
+
+       if (argc < 4) {
+               printf("Usage: %s <file> <logwrites_name> <mark_name>\n",
+                               basename(argv[0]));
+               exit(0);
+       }
+
+       fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
+       if (fd < 0)
+               err_exit("fd");
+
+       ftruncate(fd, len);
+
+       data = mmap(NULL, len, PROT_READ|PROT_WRITE,
+                       MAP_SHARED_VALIDATE|MAP_SYNC, fd, 0);
+       if (data == MAP_FAILED)
+               err_exit("mmap");
+
+       /*
+        * We intentionally don't sync 'fd' manually.  If MAP_SYNC is working
+        * these allocating page faults will cause the filesystem to sync its
+        * metadata so that when we replay the dm-log-writes log the test file
+        * will have 1 MiB worth of block allocations.
+        *
+        * dm-log-writes doesn't track the data that we write via the mmap(),
+        * so we can't check that, we can only verify that the metadata writes
+        * happened.
+        */
+       for (i = 0; i < len; i+=page_size)
+               data[i] = 0xff;
+
+       mark_log(argv[2], argv[3]);
+
+       err = munmap(data, len);
+       if (err < 0)
+               err_exit("munmap");
+
+       err = close(fd);
+       if (err < 0)
+               err_exit("close");
+
+       return 0;
+}
tests/generic/466 new file +76 -0
new file mode 100755
index 0000000..592213f
@@ -0,0 +1,76 @@
+#! /bin/bash
+# FS QA Test No. 466
+#
+# Use md_log_writes to verify that MAP_SYNC actually syncs metadata during
+# page faults.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2017 Intel Corporation.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1       # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+       _log_writes_cleanup
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/dmlogwrites
+
+# remove previous $seqres.full before test
+rm -f $seqres.full
+
+# real QA test starts here
+_supported_fs generic
+_supported_os Linux
+_require_log_writes
+_require_scratch_dax
+_require_test_program "t_map_sync"
+
+_log_writes_init
+_log_writes_mkfs >> $seqres.full 2>&1
+_log_writes_mount -o dax
+
+src/t_map_sync $SCRATCH_MNT/test $LOGWRITES_NAME pre_unmap
+
+# Unmount the scratch dir and tear down the log writes target
+_log_writes_unmount
+_log_writes_remove
+_check_scratch_fs
+
+# check pre-unmap state
+_log_writes_replay_log pre_unmap
+_scratch_mount
+
+# We should see $SCRATCH_MNT/test as having 1MiB in block allocations
+du -sh $SCRATCH_MNT/test | _filter_scratch | _filter_spaces
+
+_scratch_unmount
+_check_scratch_fs
+
+echo "Silence is golden"
+status=0
+exit
tests/generic/466.out new file +3 -0
new file mode 100644
index 0000000..4c54d7a
@@ -0,0 +1,3 @@
+QA output created by 466
+1.0M SCRATCH_MNT/test
+Silence is golden
tests/generic/group +1 -1
index fbe0a7f..65328c6 100644
@@ -468,3 +468,4 @@
 463 auto quick clone dangerous
 464 auto rw
 465 auto rw quick aio
+466 auto quick dax
--
Quoted 2 lines

2.9.5

_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

#10 lore raw

Re: [fstests PATCH v2] generic: add test for DAX MAP_SYNC support

Quoted 60 lines · Amir Goldstein
Quoted 15 lines · Ross Zwisler

Add a test that exercises DAX's new MAP_SYNC flag.

This test creates a file and writes to it via an mmap(), but never syncs via fsync/msync. This process is tracked via dm-log-writes, then replayed.

If MAP_SYNC is working the dm-log-writes replay will show the test file with 1MiB of on-media block allocations. This is because each allocating page fault included an implicit metadata sync. If MAP_SYNC isn't working (which you can test by fiddling with the parameters to mmap()) the file will be smaller or missing entirely.

Note that dm-log-writes doesn't track the data that we write via the mmap(), so we can't do any data integrity checking. We can only verify that the metadata writes for the page faults happened.

Quoted 6 lines

---

Changes since v1:
- Addressed review feedback from Amir. Thank you for the review!

Looks good.

Quoted 34 lines
---
 .gitignore            |  1 +
 common/dmlogwrites    |  1 -
 src/Makefile          |  3 +-
 src/t_map_sync.c      | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466     | 76 ++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466.out |  3 ++
 tests/generic/group   |  1 +
 7 files changed, 175 insertions(+), 2 deletions(-)
 create mode 100644 src/t_map_sync.c
 create mode 100755 tests/generic/466
 create mode 100644 tests/generic/466.out
.gitignore +1 -0
index 2014c08..9fc0695 100644
@@ -119,6 +119,7 @@
 /src/t_getcwd
 /src/t_holes
 /src/t_immutable
+/src/t_map_sync
 /src/t_mmap_cow_race
 /src/t_mmap_dio
 /src/t_mmap_fallocate
common/dmlogwrites +0 -0
index 247c744..5b57df9 100644
@@ -23,7 +23,6 @@ _require_log_writes()
        [ -z "$LOGWRITES_DEV" -o ! -b "$LOGWRITES_DEV" ] && \
                _notrun "This test requires a valid \$LOGWRITES_DEV"
 
Quoted 1 line

common/dmlogwrites _require_log_writes() · line 26

Quoted 1 line
common/dmlogwrites +0 -1
-       _exclude_scratch_mount_option dax

Wait. It this really ok to relax no dax from _require_log_writes()? Shouldn't you check log-write target version or something to verify that log-writes+dax is really supported?
I think you should.

Quoted 3 lines

common/dmlogwrites _require_log_writes() · line 28

Quoted 3 lines
common/dmlogwrites +0 -0
        _require_dm_target log-writes
        _require_test_program "log-writes/replay-log"
 }

_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

#11 lore raw

Re: [fstests PATCH v2] generic: add test for DAX MAP_SYNC support

Quoted 61 lines · Amir Goldstein
Quoted 60 lines · Amir Goldstein
Quoted 15 lines · Ross Zwisler

Add a test that exercises DAX's new MAP_SYNC flag.

This test creates a file and writes to it via an mmap(), but never syncs via fsync/msync. This process is tracked via dm-log-writes, then replayed.

If MAP_SYNC is working the dm-log-writes replay will show the test file with 1MiB of on-media block allocations. This is because each allocating page fault included an implicit metadata sync. If MAP_SYNC isn't working (which you can test by fiddling with the parameters to mmap()) the file will be smaller or missing entirely.

Note that dm-log-writes doesn't track the data that we write via the mmap(), so we can't do any data integrity checking. We can only verify that the metadata writes for the page faults happened.

Quoted 6 lines

---

Changes since v1:
- Addressed review feedback from Amir. Thank you for the review!

Looks good.

Quoted 34 lines
---
 .gitignore            |  1 +
 common/dmlogwrites    |  1 -
 src/Makefile          |  3 +-
 src/t_map_sync.c      | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466     | 76 ++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466.out |  3 ++
 tests/generic/group   |  1 +
 7 files changed, 175 insertions(+), 2 deletions(-)
 create mode 100644 src/t_map_sync.c
 create mode 100755 tests/generic/466
 create mode 100644 tests/generic/466.out
.gitignore +1 -0
index 2014c08..9fc0695 100644
@@ -119,6 +119,7 @@
 /src/t_getcwd
 /src/t_holes
 /src/t_immutable
+/src/t_map_sync
 /src/t_mmap_cow_race
 /src/t_mmap_dio
 /src/t_mmap_fallocate
common/dmlogwrites +0 -0
index 247c744..5b57df9 100644
@@ -23,7 +23,6 @@ _require_log_writes()
        [ -z "$LOGWRITES_DEV" -o ! -b "$LOGWRITES_DEV" ] && \
                _notrun "This test requires a valid \$LOGWRITES_DEV"
 
Quoted 6 lines
Quoted 1 line

common/dmlogwrites _require_log_writes() · line 26

Quoted 1 line
common/dmlogwrites +0 -1
-       _exclude_scratch_mount_option dax

Wait. It this really ok to relax no dax from _require_log_writes()? Shouldn't you check log-write target version or something to verify that log-writes+dax is really supported?
I think you should.

Ah, yep, that makes sense. I'll update for v3.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

#12 lore raw

PATCH v3 1/1 generic: add test for DAX MAP_SYNC support

In reply to Amir Goldstein

Add a test that exercises DAX's new MAP_SYNC flag.

This test creates a file and writes to it via an mmap(), but never syncs via fsync/msync. This process is tracked via dm-log-writes, then replayed.

If MAP_SYNC is working the dm-log-writes replay will show the test file with 1MiB of on-media block allocations. This is because each allocating page fault included an implicit metadata sync. If MAP_SYNC isn't working (which you can test by fiddling with the parameters to mmap()) the file will be smaller or missing entirely.

Note that dm-log-writes doesn't track the data that we write via the mmap(), so we can't do any data integrity checking. We can only verify that the metadata writes for the page faults happened.

---

Changes since v2:
- Fixed _require_log_writes() so that DAX will be disallowed if the version of the dm-log-writes target is older than v1.1.0. (Amir)

---
 .gitignore            |  1 +
 common/dmlogwrites    |  4 ++-
 common/rc             |  6 ++--
 src/Makefile          |  3 +-
 src/t_map_sync.c      | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466     | 76 ++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466.out |  3 ++
 tests/generic/group   |  1 +
 8 files changed, 182 insertions(+), 4 deletions(-)
 create mode 100644 src/t_map_sync.c
 create mode 100755 tests/generic/466
 create mode 100644 tests/generic/466.out
.gitignore +1 -0
index 2014c08..9fc0695 100644
@@ -119,6 +119,7 @@
 /src/t_getcwd
 /src/t_holes
 /src/t_immutable
+/src/t_map_sync
 /src/t_mmap_cow_race
 /src/t_mmap_dio
 /src/t_mmap_fallocate
common/dmlogwrites +3 -1
index 247c744..71d008d 100644
@@ -23,8 +23,10 @@ _require_log_writes()
 	[ -z "$LOGWRITES_DEV" -o ! -b "$LOGWRITES_DEV" ] && \
 		_notrun "This test requires a valid \$LOGWRITES_DEV"
 
-	_exclude_scratch_mount_option dax
 	_require_dm_target log-writes
+	if [[ ${DMTARGET_VER[0]} == 1 && ${DMTARGET_VER[1]} < 1 ]]; then
+		_exclude_scratch_mount_option dax
+	fi
 	_require_test_program "log-writes/replay-log"
 }
 
common/rc +4 -2
index e2a8229..df438c3 100644
@@ -1792,8 +1792,10 @@ _require_dm_target()
 
 	modprobe dm-$_target >/dev/null 2>&1
 
-	$DMSETUP_PROG targets 2>&1 | grep -q ^$_target
-	if [ $? -ne 0 ]; then
+	_version=$($DMSETUP_PROG targets 2>&1 | grep ^$_target)
+	if [[ $_version =~ .*v([0-9]+).([0-9]+).([0-9]+) ]]; then
+		DMTARGET_VER=(${BASH_REMATCH[@]:1})
+	else
 		_notrun "This test requires dm $_target support"
 	fi
 }
src/Makefile +2 -1
index 3eb25b1..af7e7e9 100644
@@ -13,7 +13,8 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
 	multi_open_unlink dmiperf unwritten_sync genhashnames t_holes \
 	t_mmap_writev t_truncate_cmtime dirhash_collide t_rename_overwrite \
 	holetest t_truncate_self t_mmap_dio af_unix t_mmap_stale_pmd \
-	t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro
+	t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro \
+	t_map_sync
 
 LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
 	preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
src/t_map_sync.c new file +92 -0

92 lines not on this page · raw message

tests/generic/466 new file +76 -0

76 lines not on this page · raw message

tests/generic/466.out new file +3 -0
new file mode 100644
index 0000000..4c54d7a
@@ -0,0 +1,3 @@
+QA output created by 466
+1.0M SCRATCH_MNT/test
+Silence is golden
tests/generic/group +1 -0
index fbe0a7f..65328c6 100644
@@ -468,3 +468,4 @@
 463 auto quick clone dangerous
 464 auto rw
 465 auto rw quick aio
+466 auto quick dax
Signature · 6 lines
2.9.5

_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
#13 lore raw

Re: [fstests PATCH v3] generic: add test for DAX MAP_SYNC support

Quoted 16 lines · Ross Zwisler

Add a test that exercises DAX's new MAP_SYNC flag.

This test creates a file and writes to it via an mmap(), but never syncs via fsync/msync. This process is tracked via dm-log-writes, then replayed.

If MAP_SYNC is working the dm-log-writes replay will show the test file with 1MiB of on-media block allocations. This is because each allocating page fault included an implicit metadata sync. If MAP_SYNC isn't working (which you can test by fiddling with the parameters to mmap()) the file will be smaller or missing entirely.

Note that dm-log-writes doesn't track the data that we write via the mmap(), so we can't do any data integrity checking. We can only verify that the metadata writes for the page faults happened.

.....

Quoted 18 lines
src/t_map_sync.c new file +15 -0
@@ -0,0 +1,92 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define MiB(a) ((a)*1024*1024)
+
+/*
+ * These two defines were added to the kernel via commits entitled
+ * "mm: Define MAP_SYNC and VM_SYNC flags" and

src/t_map_sync.c line 25

Quoted 10 lines
src/t_map_sync.c new file +10 -0
+ * "mm: introduce MAP_SHARED_VALIDATE, a mechanism to safely define new mmap
+ * flags", respectively.
+ */
+#ifndef MAP_SYNC
+#define MAP_SYNC 0x80000
+#endif
+
+#ifndef MAP_SHARED_VALIDATE
+#define MAP_SHARED_VALIDATE 0x3
+#endif

Autoconf rules for detecting supported functionality, please...

Quoted 31 lines
src/t_map_sync.c new file +31 -0
+
+void err_exit(char *op)
+{
+	fprintf(stderr, "%s: %s\n", op, strerror(errno));
+	exit(1);
+}
+
+void mark_log(char *logwrites_name, char *mark_name)
+{
+	char command[256];
+
+	snprintf(command, 256, "dmsetup message %s 0 mark %s",
+			logwrites_name, mark_name);
+
+	if (system(command))
+		err_exit("mark_log");
+}
+
+int main(int argc, char *argv[])
+{
+	int page_size = getpagesize();
+	int len = MiB(1);
+	int i, fd, err;
+	char *data;
+
+	if (argc < 4) {
+		printf("Usage: %s <file> <logwrites_name> <mark_name>\n",
+				basename(argv[0]));
+		exit(0);
+	}
+

src/t_map_sync.c line 66

Quoted 10 lines
src/t_map_sync.c new file +10 -0
+	fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
+	if (fd < 0)
+		err_exit("fd");
+
+	ftruncate(fd, len);
+
+	data = mmap(NULL, len, PROT_READ|PROT_WRITE,
+			MAP_SHARED_VALIDATE|MAP_SYNC, fd, 0);
+	if (data == MAP_FAILED)
+		err_exit("mmap");

As I say to all these sorts of one-off test prgrams: please add the new MAP_SYNC flag to xfs_io rather than writing a one-off test program to set it and write some data.

And if we're going to be adding special custom tests just because we need to insert dm-log marks, add that functionality to xfs_io, too.

That way we can create complex custom dm logwrite tests without needing one-off test programs for them all...

src/t_map_sync.c line 70

Quoted 4 lines
src/t_map_sync.c new file +4 -0
+#! /bin/bash
+# FS QA Test No. 466
+#
+# Use md_log_writes to verify that MAP_SYNC actually syncs metadata during

dm_log_writes?

src/t_map_sync.c line 72

Quoted 2 lines
src/t_map_sync.c new file +2 -0
+# We should see $SCRATCH_MNT/test as having 1MiB in block allocations
+du -sh $SCRATCH_MNT/test | _filter_scratch | _filter_spaces

Perhaps stat -c %b $SCRATCH_MNT/test ?

Cheers,

Dave.

Signature · 6 lines
Dave Chinner
[email protected]
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
#14 lore raw

Re: [fstests PATCH v3] generic: add test for DAX MAP_SYNC support

Quoted 40 lines · Dave Chinner
Quoted 16 lines · Ross Zwisler

Add a test that exercises DAX's new MAP_SYNC flag.

This test creates a file and writes to it via an mmap(), but never syncs via fsync/msync. This process is tracked via dm-log-writes, then replayed.

If MAP_SYNC is working the dm-log-writes replay will show the test file with 1MiB of on-media block allocations. This is because each allocating page fault included an implicit metadata sync. If MAP_SYNC isn't working (which you can test by fiddling with the parameters to mmap()) the file will be smaller or missing entirely.

Note that dm-log-writes doesn't track the data that we write via the mmap(), so we can't do any data integrity checking. We can only verify that the metadata writes for the page faults happened.

.....

Quoted 22 lines
src/t_map_sync.c new file +19 -0
@@ -0,0 +1,92 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define MiB(a) ((a)*1024*1024)
+
+/*
+ * These two defines were added to the kernel via commits entitled
+ * "mm: Define MAP_SYNC and VM_SYNC flags" and
+ * "mm: introduce MAP_SHARED_VALIDATE, a mechanism to safely define new mmap
+ * flags", respectively.
+ */
+#ifndef MAP_SYNC
Quoted 8 lines

src/t_map_sync.c line 25

Quoted 6 lines
src/t_map_sync.c new file +6 -0
+#define MAP_SYNC 0x80000
+#endif
+
+#ifndef MAP_SHARED_VALIDATE
+#define MAP_SHARED_VALIDATE 0x3
+#endif

Autoconf rules for detecting supported functionality, please...

Yep, that's better. As you've suggested down below I'm adding this functionality to xfs_io instead, and I've added autoconf rules there.

Quoted 46 lines
Quoted 31 lines
src/t_map_sync.c new file +31 -0
+
+void err_exit(char *op)
+{
+	fprintf(stderr, "%s: %s\n", op, strerror(errno));
+	exit(1);
+}
+
+void mark_log(char *logwrites_name, char *mark_name)
+{
+	char command[256];
+
+	snprintf(command, 256, "dmsetup message %s 0 mark %s",
+			logwrites_name, mark_name);
+
+	if (system(command))
+		err_exit("mark_log");
+}
+
+int main(int argc, char *argv[])
+{
+	int page_size = getpagesize();
+	int len = MiB(1);
+	int i, fd, err;
+	char *data;
+
+	if (argc < 4) {
+		printf("Usage: %s <file> <logwrites_name> <mark_name>\n",
+				basename(argv[0]));
+		exit(0);
+	}
+

src/t_map_sync.c line 66

Quoted 10 lines
src/t_map_sync.c new file +10 -0
+	fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
+	if (fd < 0)
+		err_exit("fd");
+
+	ftruncate(fd, len);
+
+	data = mmap(NULL, len, PROT_READ|PROT_WRITE,
+			MAP_SHARED_VALIDATE|MAP_SYNC, fd, 0);
+	if (data == MAP_FAILED)
+		err_exit("mmap");

As I say to all these sorts of one-off test prgrams: please add the new MAP_SYNC flag to xfs_io rather than writing a one-off test program to set it and write some data.

Quoted 6 lines

And if we're going to be adding special custom tests just because we need to insert dm-log marks, add that functionality to xfs_io, too.

That way we can create complex custom dm logwrite tests without needing one-off test programs for them all...

Yep, that was a better path. I've got things working - need to clean up and I'll send out soon.

Quoted 6 lines

src/t_map_sync.c line 70

Quoted 4 lines
src/t_map_sync.c new file +4 -0
+#! /bin/bash
+# FS QA Test No. 466
+#
+# Use md_log_writes to verify that MAP_SYNC actually syncs metadata during

dm_log_writes?

Fixed.

Quoted 4 lines

src/t_map_sync.c line 72

Quoted 2 lines
src/t_map_sync.c new file +2 -0
+# We should see $SCRATCH_MNT/test as having 1MiB in block allocations
+du -sh $SCRATCH_MNT/test | _filter_scratch | _filter_spaces

Perhaps stat -c %b $SCRATCH_MNT/test ?

Maybe, but doesn't the output of 'stat -c %b' depend on the block size the filesystem is using? I think to use stat I'd have to check both %b and %B, and account for different block sizes, or do some shell math. I think it may be easier to just use du.

Thank you for the review, sorry for the delayed response.
_______________________________________________
Linux-nvdimm mailing list [email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

#15 lore raw

Re: [fstests PATCH v3] generic: add test for DAX MAP_SYNC support

Quoted 7 lines · Ross Zwisler
Quoted 1 line · Dave Chinner

Perhaps stat -c %b $SCRATCH_MNT/test ?

Maybe, but doesn't the output of 'stat -c %b' depend on the block size the filesystem is using? I think to use stat I'd have to check both %b and %B, and account for different block sizes, or do some shell math. I think it may be easier to just use du.

Ah, never mind, I think you meant 'stat -c %s' - that's cleaner, will switch.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

#16 lore raw

Re: [fstests PATCH v3] generic: add test for DAX MAP_SYNC support

In reply to Ross Zwisler
Quoted 15 lines · Ross Zwisler

Add a test that exercises DAX's new MAP_SYNC flag.

This test creates a file and writes to it via an mmap(), but never syncs via fsync/msync. This process is tracked via dm-log-writes, then replayed.

If MAP_SYNC is working the dm-log-writes replay will show the test file with 1MiB of on-media block allocations. This is because each allocating page fault included an implicit metadata sync. If MAP_SYNC isn't working (which you can test by fiddling with the parameters to mmap()) the file will be smaller or missing entirely.

Note that dm-log-writes doesn't track the data that we write via the mmap(), so we can't do any data integrity checking. We can only verify that the metadata writes for the page faults happened.

Quoted 7 lines

---

Changes since v2:
- Fixed _require_log_writes() so that DAX will be disallowed if the version of the dm-log-writes target is older than v1.1.0. (Amir)

It seems like your kernel patch bumped the version to 1.0.1...

Quoted 32 lines
---
 .gitignore            |  1 +
 common/dmlogwrites    |  4 ++-
 common/rc             |  6 ++--
 src/Makefile          |  3 +-
 src/t_map_sync.c      | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466     | 76 ++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466.out |  3 ++
 tests/generic/group   |  1 +
 8 files changed, 182 insertions(+), 4 deletions(-)
 create mode 100644 src/t_map_sync.c
 create mode 100755 tests/generic/466
 create mode 100644 tests/generic/466.out
.gitignore +1 -0
index 2014c08..9fc0695 100644
@@ -119,6 +119,7 @@
 /src/t_getcwd
 /src/t_holes
 /src/t_immutable
+/src/t_map_sync
 /src/t_mmap_cow_race
 /src/t_mmap_dio
 /src/t_mmap_fallocate
common/dmlogwrites +0 -0
index 247c744..71d008d 100644

common/dmlogwrites _require_log_writes() · line 29

Quoted 8 lines
common/dmlogwrites +3 -1
@@ -23,8 +23,10 @@ _require_log_writes()
        [ -z "$LOGWRITES_DEV" -o ! -b "$LOGWRITES_DEV" ] && \
                _notrun "This test requires a valid \$LOGWRITES_DEV"
 
-       _exclude_scratch_mount_option dax
        _require_dm_target log-writes
+       if [[ ${DMTARGET_VER[0]} == 1 && ${DMTARGET_VER[1]} < 1 ]]; then
+               _exclude_scratch_mount_option dax
+       fi

IMO, this would be better as:

local z=0
_scratch_has_mount_option dax && z=1
_require_dm_target log-writes 1 0 $z

Or something like that
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

#17 lore raw

Re: [fstests PATCH v3] generic: add test for DAX MAP_SYNC support

Quoted 19 lines · Amir Goldstein
Quoted 17 lines · Ross Zwisler

Add a test that exercises DAX's new MAP_SYNC flag.

This test creates a file and writes to it via an mmap(), but never syncs via fsync/msync. This process is tracked via dm-log-writes, then replayed.

If MAP_SYNC is working the dm-log-writes replay will show the test file with 1MiB of on-media block allocations. This is because each allocating page fault included an implicit metadata sync. If MAP_SYNC isn't working (which you can test by fiddling with the parameters to mmap()) the file will be smaller or missing entirely.

Note that dm-log-writes doesn't track the data that we write via the mmap(), so we can't do any data integrity checking. We can only verify that the metadata writes for the page faults happened.

Quoted 7 lines
Quoted 5 lines

---

Changes since v2:
- Fixed _require_log_writes() so that DAX will be disallowed if the version of the dm-log-writes target is older than v1.1.0. (Amir)

It seems like your kernel patch bumped the version to 1.0.1...

Ah, yep, that's the version number that I submitted but Mike changed it to v1.1.0 in his tree. Here's the patch that was merged for v4.15-rc1:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers?id=98d82f48f1983ceef5c8d2f6c87bfee2918790ee

Quoted 43 lines
Quoted 32 lines
---
 .gitignore            |  1 +
 common/dmlogwrites    |  4 ++-
 common/rc             |  6 ++--
 src/Makefile          |  3 +-
 src/t_map_sync.c      | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466     | 76 ++++++++++++++++++++++++++++++++++++++++++
 tests/generic/466.out |  3 ++
 tests/generic/group   |  1 +
 8 files changed, 182 insertions(+), 4 deletions(-)
 create mode 100644 src/t_map_sync.c
 create mode 100755 tests/generic/466
 create mode 100644 tests/generic/466.out
.gitignore +1 -0
index 2014c08..9fc0695 100644
@@ -119,6 +119,7 @@
 /src/t_getcwd
 /src/t_holes
 /src/t_immutable
+/src/t_map_sync
 /src/t_mmap_cow_race
 /src/t_mmap_dio
 /src/t_mmap_fallocate
common/dmlogwrites +0 -0
index 247c744..71d008d 100644

common/dmlogwrites _require_log_writes() · line 29

Quoted 8 lines
common/dmlogwrites +3 -1
@@ -23,8 +23,10 @@ _require_log_writes()
        [ -z "$LOGWRITES_DEV" -o ! -b "$LOGWRITES_DEV" ] && \
                _notrun "This test requires a valid \$LOGWRITES_DEV"
 
-       _exclude_scratch_mount_option dax
        _require_dm_target log-writes
+       if [[ ${DMTARGET_VER[0]} == 1 && ${DMTARGET_VER[1]} < 1 ]]; then
+               _exclude_scratch_mount_option dax
+       fi

IMO, this would be better as:

Quoted 5 lines

local z=0
_scratch_has_mount_option dax && z=1
_require_dm_target log-writes 1 0 $z

Or something like that

Yep, this is nicer. Fixed.

Thanks for the review.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

#18 lore raw
In reply to Ross Zwisler
Quoted 10 lines · Ross Zwisler

Currently dm-log-writes supports writing filesystem data via BIOs, and writing internal metadata from a flat buffer via write_metadata().

For DAX writes, though, we won't have a BIO, but will instead have an iterator that we'll want to use to fill a flat data buffer.

So, create write_inline_data() which allows us to write filesystem data using a flat buffer as a source, and wire it up in log_one_block().

Hi,

I picked this up but tweaked some whitespace and couple style nits, see:
https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=for-4.15/dm&id=6a697d036324c7fbe63fb49599027269006161e7

Thanks,
Mike
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm