nvdimm.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH] ndctl, check: Ensure mmap of BTT sections work with 64K page-size
@ 2019-07-04  2:51 Vaibhav Jain
  2019-08-02 22:30 ` Verma, Vishal L
  0 siblings, 1 reply; 5+ messages in thread
From: Vaibhav Jain @ 2019-07-04  2:51 UTC (permalink / raw)
  To: linux-nvdimm, Vishal Verma; +Cc: harish, Vaibhav Jain, Aneesh Kumar K.V

Presently on PPC64 which uses a 64K page-size, ndtl-check command
fails on a BTT device with following error:

$sudo ndctl check-namespace namespace0.0 -vv
namespace0.0: namespace_check: checking namespace0.0
namespace0.0: btt_discover_arenas: found 1 BTT arena
namespace0.0: btt_create_mappings: mmap arena[0].info [sz = 0x1000, off = 0x1000] failed: Invalid argument
error checking namespaces: Invalid argument
checked 0 namespaces

Error happens when btt_create_mappings() tries to mmap the sections of
the BTT device which are usually 4K offset aligned. However the mmap()
syscall expects the 'offset' argument to be in multiples of page-size,
hence it returns EINVAL causing the btt_create_mappings() to error
out.

As a fix for the issue this patch proposes addition of two new
functions to 'check.c' namely btt_mmap/btt_unmap that can be used to
map/unmap parts of BTT device to ndctl process address-space. The
functions tweaks the requested 'offset' argument to mmap() ensuring
that its page-size aligned and then fix-ups the returned pointer such
that it points to the requested offset within m-mapped region.

Reported-by: harish@linux.ibm.com
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
 ndctl/check.c | 71 ++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 56 insertions(+), 15 deletions(-)

diff --git a/ndctl/check.c b/ndctl/check.c
index 8a7125053865..18d259048616 100644
--- a/ndctl/check.c
+++ b/ndctl/check.c
@@ -907,6 +907,47 @@ static int btt_discover_arenas(struct btt_chk *bttc)
 	return ret;
 }
 
+/* Mmap requested btt region so it works with non 4-K page sizes */
+static void *btt_mmap(struct btt_chk *bttc, void *addr, size_t length,
+		      int prot, int flags, off_t offset)
+{
+	off_t shift;
+
+	/* Calculate the shift back needed to make offset page aligned */
+	shift = offset - rounddown(offset, bttc->sys_page_size);
+
+	/* Update the offset and length with the shift calculated above */
+	offset -= shift;
+	length += shift;
+
+	addr = mmap(addr, length, prot, flags, bttc->fd, offset);
+
+	/* If needed fixup the return pointer to correct offset request */
+	if (addr != MAP_FAILED)
+		addr = (void *) ((uintptr_t)addr + shift);
+
+	dbg(bttc, "mmap: addr=%p length=0x%lx offset=0x%lx shift=0x%lx\n",
+	    addr, length, offset, shift);
+
+	return addr;
+}
+
+static void btt_unmap(struct btt_chk *bttc, void *ptr, size_t length)
+{
+	uintptr_t addr = ptr;
+	off_t shift;
+
+	/* Calculate the shift back needed to make offset page aligned */
+	shift = addr - rounddown(addr, bttc->sys_page_size);
+
+	addr -= shift;
+	length += shift;
+
+	munmap((void *)addr, length);
+	dbg(bttc, "unmap: addr=%p length=0x%lx shift=0x%lx\n",
+	    addr, length, shift);
+}
+
 static int btt_create_mappings(struct btt_chk *bttc)
 {
 	struct arena_info *a;
@@ -921,8 +962,8 @@ static int btt_create_mappings(struct btt_chk *bttc)
 	for (i = 0; i < bttc->num_arenas; i++) {
 		a = &bttc->arena[i];
 		a->map.info_len = BTT_INFO_SIZE;
-		a->map.info = mmap(NULL, a->map.info_len, mmap_flags,
-			MAP_SHARED, bttc->fd, a->infooff);
+		a->map.info = btt_mmap(bttc, NULL, a->map.info_len, mmap_flags,
+				       MAP_SHARED, a->infooff);
 		if (a->map.info == MAP_FAILED) {
 			err(bttc, "mmap arena[%d].info [sz = %#lx, off = %#lx] failed: %s\n",
 				i, a->map.info_len, a->infooff, strerror(errno));
@@ -930,8 +971,8 @@ static int btt_create_mappings(struct btt_chk *bttc)
 		}
 
 		a->map.data_len = a->mapoff - a->dataoff;
-		a->map.data = mmap(NULL, a->map.data_len, mmap_flags,
-			MAP_SHARED, bttc->fd, a->dataoff);
+		a->map.data = btt_mmap(bttc, NULL, a->map.data_len, mmap_flags,
+				       MAP_SHARED, a->dataoff);
 		if (a->map.data == MAP_FAILED) {
 			err(bttc, "mmap arena[%d].data [sz = %#lx, off = %#lx] failed: %s\n",
 				i, a->map.data_len, a->dataoff, strerror(errno));
@@ -939,8 +980,8 @@ static int btt_create_mappings(struct btt_chk *bttc)
 		}
 
 		a->map.map_len = a->logoff - a->mapoff;
-		a->map.map = mmap(NULL, a->map.map_len, mmap_flags,
-			MAP_SHARED, bttc->fd, a->mapoff);
+		a->map.map = btt_mmap(bttc, NULL, a->map.map_len, mmap_flags,
+				      MAP_SHARED, a->mapoff);
 		if (a->map.map == MAP_FAILED) {
 			err(bttc, "mmap arena[%d].map [sz = %#lx, off = %#lx] failed: %s\n",
 				i, a->map.map_len, a->mapoff, strerror(errno));
@@ -948,8 +989,8 @@ static int btt_create_mappings(struct btt_chk *bttc)
 		}
 
 		a->map.log_len = a->info2off - a->logoff;
-		a->map.log = mmap(NULL, a->map.log_len, mmap_flags,
-			MAP_SHARED, bttc->fd, a->logoff);
+		a->map.log = btt_mmap(bttc, NULL, a->map.log_len, mmap_flags,
+				  MAP_SHARED, a->logoff);
 		if (a->map.log == MAP_FAILED) {
 			err(bttc, "mmap arena[%d].log [sz = %#lx, off = %#lx] failed: %s\n",
 				i, a->map.log_len, a->logoff, strerror(errno));
@@ -957,8 +998,8 @@ static int btt_create_mappings(struct btt_chk *bttc)
 		}
 
 		a->map.info2_len = BTT_INFO_SIZE;
-		a->map.info2 = mmap(NULL, a->map.info2_len, mmap_flags,
-			MAP_SHARED, bttc->fd, a->info2off);
+		a->map.info2 = btt_mmap(bttc, NULL, a->map.info2_len,
+					mmap_flags, MAP_SHARED, a->info2off);
 		if (a->map.info2 == MAP_FAILED) {
 			err(bttc, "mmap arena[%d].info2 [sz = %#lx, off = %#lx] failed: %s\n",
 				i, a->map.info2_len, a->info2off, strerror(errno));
@@ -977,15 +1018,15 @@ static void btt_remove_mappings(struct btt_chk *bttc)
 	for (i = 0; i < bttc->num_arenas; i++) {
 		a = &bttc->arena[i];
 		if (a->map.info)
-			munmap(a->map.info, a->map.info_len);
+			btt_unmap(bttc, a->map.info, a->map.info_len);
 		if (a->map.data)
-			munmap(a->map.data, a->map.data_len);
+			btt_unmap(bttc, a->map.data, a->map.data_len);
 		if (a->map.map)
-			munmap(a->map.map, a->map.map_len);
+			btt_unmap(bttc, a->map.map, a->map.map_len);
 		if (a->map.log)
-			munmap(a->map.log, a->map.log_len);
+			btt_unmap(bttc, a->map.log, a->map.log_len);
 		if (a->map.info2)
-			munmap(a->map.info2, a->map.info2_len);
+			btt_unmap(bttc, a->map.info2, a->map.info2_len);
 	}
 }
 
-- 
2.21.0

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-08-06  5:08 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-04  2:51 [PATCH] ndctl, check: Ensure mmap of BTT sections work with 64K page-size Vaibhav Jain
2019-08-02 22:30 ` Verma, Vishal L
2019-08-05 13:09   ` Vaibhav Jain
2019-08-05 16:26     ` Verma, Vishal L
2019-08-06  5:05       ` Vaibhav Jain

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).