diff --git a/src/libpmem2/deep_flush_linux.c b/src/libpmem2/deep_flush_linux.c
index 3d8431a3286606a383709ce25745f8c347766e25..567174b4253bfb0bddb6316e22b54fa664594c21 100644
--- a/src/libpmem2/deep_flush_linux.c
+++ b/src/libpmem2/deep_flush_linux.c
@@ -83,6 +83,19 @@ pmem2_deep_flush_dax(struct pmem2_map *map, void *ptr, size_t size)
 	enum pmem2_file_type type = map->source.value.ftype;
 
 	if (type == PMEM2_FTYPE_REG) {
+		/*
+		 * Flushing using OS-provided mechanisms requires that
+		 * the address be a multiple of the page size.
+		 * Align address down and change len so that [addr, addr + len)
+		 * still contains the initial range.
+		 */
+
+		/* round address down to page boundary */
+		uintptr_t new_addr = ALIGN_DOWN((uintptr_t)ptr, Pagesize);
+		/* increase len by the amount we gain when we round addr down */
+		size += (uintptr_t)ptr - new_addr;
+		ptr = (void *)new_addr;
+
 		ret = pmem2_flush_file_buffers_os(map, ptr, size, 0);
 		if (ret) {
 			LOG(1, "cannot flush buffers addr %p len %zu",
diff --git a/src/test/pmem2_integration/TESTS.py b/src/test/pmem2_integration/TESTS.py
index e8178e32f81c1acbcc455063b8c9c7518f3fda85..24ba2991c8a6d06b0187d7f046fb82e71eb9212c 100755
--- a/src/test/pmem2_integration/TESTS.py
+++ b/src/test/pmem2_integration/TESTS.py
@@ -282,3 +282,8 @@ class TEST36(PMEM2_INTEGRATION_DEV_DAXES):
 class TEST37(PMEM2_INTEGRATION_DEV_DAXES):
     """test deep flush with overlaping part"""
     test_case = "test_deep_flush_overlap"
+
+
+class TEST38(PMEM2_INTEGRATION):
+    """test for unaligned persists"""
+    test_case = "test_unaligned_persist"
diff --git a/src/test/pmem2_integration/pmem2_integration.c b/src/test/pmem2_integration/pmem2_integration.c
index 68f3654ae38ac71bdf0fea3fe1d9e77303257412..fe50d073568e1b12007619e1d9927bd93134a48c 100644
--- a/src/test/pmem2_integration/pmem2_integration.c
+++ b/src/test/pmem2_integration/pmem2_integration.c
@@ -736,6 +736,47 @@ test_deep_flush_overlap(const struct test_case *tc, int argc, char *argv[])
 	return 1;
 }
 
+/*
+ * test_unaligned_persist -- try flushing on non-page-aligned addresses
+ */
+static int
+test_unaligned_persist(const struct test_case *tc, int argc, char *argv[])
+{
+	char *file = argv[0];
+	int fd = OPEN(file, O_RDWR);
+
+#define FLUSH_OFFSET 256
+
+	struct pmem2_config *cfg;
+	struct pmem2_source *src;
+	PMEM2_PREPARE_CONFIG_INTEGRATION(&cfg, &src, fd,
+						PMEM2_GRANULARITY_PAGE);
+
+	size_t len;
+	PMEM2_SOURCE_SIZE(src, &len);
+
+	struct pmem2_map *map = map_valid(cfg, src, len);
+
+	size_t map_size = pmem2_map_get_size(map);
+	char *addr = pmem2_map_get_address(map);
+	pmem2_persist_fn persist_fn = pmem2_get_persist_fn(map);
+	memset(addr, 0, len);
+	persist_fn(addr + FLUSH_OFFSET, len - FLUSH_OFFSET);
+
+	int ret = pmem2_deep_flush(map, addr + FLUSH_OFFSET,
+		map_size - FLUSH_OFFSET);
+	UT_PMEM2_EXPECT_RETURN(ret, 0);
+
+	pmem2_unmap(&map);
+	PMEM2_CONFIG_DELETE(&cfg);
+	PMEM2_SOURCE_DELETE(&src);
+	CLOSE(fd);
+
+#undef FLUSH_OFFSET
+
+	return 1;
+}
+
 /*
  * test_source_anon -- tests map/config/source functions in combination
  *	with anonymous source.
@@ -880,6 +921,7 @@ static struct test_case test_cases[] = {
 	TEST_CASE(test_source_anon_page),
 	TEST_CASE(test_source_anon_too_small),
 	TEST_CASE(test_source_anon_zero_len),
+	TEST_CASE(test_unaligned_persist),
 };
 
 #define NTESTS (sizeof(test_cases) / sizeof(test_cases[0]))