aboutsummaryrefslogtreecommitdiff
path: root/alloc.c
diff options
context:
space:
mode:
authorMel Gorman <mel@csn.ul.ie>2009-01-08 11:38:24 +0000
committerEric B Munson <ebmunson@us.ibm.com>2009-01-08 12:54:10 +0000
commitcdf5c1b132991c00202fb4cb71348a20226a23f1 (patch)
tree93ba8e05f62ad061880d762ea3b640d4d3deb1e0 /alloc.c
parente6d8bd1a9be72a2a9780836a48624b0211a3c95a (diff)
downloadlibhugetlbfs-cdf5c1b132991c00202fb4cb71348a20226a23f1.tar.gz
Do not free the first hpage-aligned region found in free_hugepage_region()2.1.2
free_hugepage_region() does not necessarily free aligned addresses. Hence, it checks page-aligned and hpage-aligned addresses when reading /proc/self/maps. The problem is that it is reasonable to encounter a hpage-aligned address being used by something else entirely and then accidentally freeing it. When reading /proc/pid/maps, just record that a hpage-aligned address was found. If no exact or page-aligned address is found, then the hpage-aligned address is freed instead. This is a candidate for backporting to 2.1.x. Signed-off-by: Mel Gorman <mel@csn.ul.ie> Acked-by: Eric B Munson <ebmunson@us.ibm.com> Signed-off-by: Eric B Munson <ebmunson@us.ibm.com>
Diffstat (limited to 'alloc.c')
-rw-r--r--alloc.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/alloc.c b/alloc.c
index c357827..15e4d29 100644
--- a/alloc.c
+++ b/alloc.c
@@ -130,6 +130,7 @@ static void __free_huge_pages(void *ptr, int aligned)
char line[MAPS_BUF_SZ];
unsigned long start = 0, end = 0;
unsigned long palign = 0, hpalign = 0;
+ unsigned long hpalign_end = 0;
/*
* /proc/self/maps is used to determine the length of the original
@@ -174,17 +175,39 @@ static void __free_huge_pages(void *ptr, int aligned)
break;
}
- /* Check the unaligned possibilities */
- if (!aligned && (start == palign || start == hpalign)) {
+ /* If the passed address is aligned, just move along */
+ if (aligned)
+ continue;
+
+ /*
+ * If an address is hpage-aligned, record it but keep looking.
+ * We might find a page-aligned or exact address later
+ */
+ if (start == hpalign) {
+ hpalign_end = strtoull(bufptr, NULL, 16);
+ continue;
+ }
+
+ /* If an address is page-aligned, free it */
+ if (start == palign) {
end = strtoull(bufptr, NULL, 16);
munmap((void *)start, end - start);
break;
}
+
}
- /* Print a warning if the ptr appeared to point nowhere */
- if (end == 0)
- ERROR("hugepages_free using invalid or double free\n");
+ /*
+ * If no exact or page-aligned address was found, check for a
+ * hpage-aligned address. If found, free it, otherwise warn that
+ * the ptr pointed nowhere
+ */
+ if (end == 0) {
+ if (hpalign_end == 0)
+ ERROR("hugepages_free using invalid or double free\n");
+ else
+ munmap((void *)hpalign, hpalign_end - hpalign);
+ }
fclose(fd);
}