On Fri, Oct 10, 2008 at 11:00:51AM +0100, Mel Gorman wrote: > On (09/10/08 20:20), Andy Whitcroft didst pronounce: > > From: Adam Litke <[EMAIL PROTECTED]> > > > > The need to set and get pool counters for multiple huge page sizes is about > > to > > extend beyond just the libhugetlbfs tests. Move the counter code into > > hugeutils.c and make the top-level functions part of the libhugetlbfs pool > > and > > mount configuration API. This involves altering some function names and > > prologues to make them more consistent with the existing libhugetlbfs API. > > > > We create a new libtestutils.c for test case utilities that depend on > > linkage > > to libhugetlbfs. > > > > NOTE: This patch will cause the shmoverride test to fail compilation. This > > is > > fixed up by the next patch. > > > > [EMAIL PROTECTED]: consolidate makefile updates in one place] > > Signed-off-by: Adam Litke <[EMAIL PROTECTED]> > > --- > > hugetlbfs.h | 14 ++ > > hugeutils.c | 166 ++++++++++++++++++++--- > > tests/Makefile | 4 +- > > tests/alloc-instantiate-race.c | 5 +- > > tests/chunk-overcommit.c | 3 +- > > tests/counters.c | 38 +++--- > > tests/get_huge_pages.c | 14 +- > > tests/heap-overflow.c | 2 +- > > tests/hugetests.h | 20 +--- > > tests/libtestutils.c | 137 +++++++++++++++++++ > > tests/misaligned_offset.c | 20 ++-- > > tests/quota.c | 6 +- > > tests/shmoverride_unlinked.c | 8 +- > > tests/testutils.c | 252 > > +---------------------------------- > > tests/truncate_reserve_wraparound.c | 21 ++-- > > tests/truncate_sigbus_versus_oom.c | 3 +- > > 16 files changed, 358 insertions(+), 355 deletions(-) > > create mode 100644 tests/libtestutils.c > > > > diff --git a/hugetlbfs.h b/hugetlbfs.h > > index 48a2f68..2103515 100644 > > --- a/hugetlbfs.h > > +++ b/hugetlbfs.h > > @@ -59,4 +59,18 @@ enum { > > }; > > int hugetlbfs_test_feature(int feature_code); > > > > +/* Hugetlb pool counter operations */ > > +/* Keys for reading hugetlb pool counters */ > > +enum { /* The number of pages of a given size that > > ... */ > > + HUGEPAGES_TOTAL, /* are allocated to the pool */ > > + HUGEPAGES_FREE, /* are not in use */ > > + HUGEPAGES_RSVD, /* are reserved for possible future use */ > > + HUGEPAGES_SURP, /* are allocated to the pool on demand */ > > + HUGEPAGES_OC, /* can be allocated on demand - maximum */ > > + HUGEPAGES_MAX_COUNTERS, > > +}; > > +long get_huge_page_counter(long pagesize, unsigned int counter); > > +int set_nr_hugepages(long pagesize, unsigned long val); > > +int set_nr_overcommit_hugepages(long pagesize, unsigned long val); > > +long read_meminfo(const char *tag); > > #endif /* _HUGETLBFS_H */ > > These things are still in a header that is installed but the LDS file is > not updated. Should they be in libhugetlbfs_internal.h ? > > For what it's worth, there is some other stuff in there that shouldn't > be either like the kernel testing feature. Maybe another patch just > cleaning out hugetlbfs.h is in order and apply it after this series.
Ok. > > diff --git a/hugeutils.c b/hugeutils.c > > index d4ba088..7e730aa 100644 > > --- a/hugeutils.c > > +++ b/hugeutils.c > > @@ -118,7 +118,39 @@ long __lh_parse_page_size(const char *str) > > return size; > > } > > > > -static long read_meminfo(const char *tag) > > +struct hugetlb_pool_counter_info_t { > > + char *meminfo_key; > > + char *sysfs_file; > > +}; > > + > > +struct hugetlb_pool_counter_info_t hugetlb_counter_info[] = { > > + [HUGEPAGES_TOTAL] = { > > + .meminfo_key = "HugePages_Total:", > > + .sysfs_file = "nr_hugepages", > > + }, > > + [HUGEPAGES_FREE] = { > > + .meminfo_key = "HugePages_Free:", > > + .sysfs_file = "free_hugepages", > > + }, > > + [HUGEPAGES_RSVD] = { > > + .meminfo_key = "HugePages_Rsvd:", > > + .sysfs_file = "resv_hugepages", > > + }, > > + [HUGEPAGES_SURP] = { > > + .meminfo_key = "HugePages_Surp:", > > + .sysfs_file = "surplus_hugepages", > > + }, > > + [HUGEPAGES_OC] = { > > + .meminfo_key = NULL, > > + .sysfs_file = "nr_overcommit_hugepages" > > + }, > > +}; > > + > > +/* > > + * Read numeric data from raw and tagged kernel status files. Used to read > > + * /proc and /sys data (without a tag) and from /proc/meminfo (with a tag). > > + */ > > +long file_read_ulong(char *file, const char *tag) > > { > > int fd; > > char buf[MEMINFO_SIZE]; > > @@ -126,9 +158,9 @@ static long read_meminfo(const char *tag) > > char *p, *q; > > long val; > > > > - fd = open("/proc/meminfo", O_RDONLY); > > + fd = open(file, O_RDONLY); > > if (fd < 0) { > > - ERROR("Couldn't open /proc/meminfo (%s)\n", strerror(errno)); > > + ERROR("Couldn't open %s: %s\n", file, strerror(errno)); > > return -1; > > } > > > > @@ -136,37 +168,107 @@ static long read_meminfo(const char *tag) > > readerr = errno; > > close(fd); > > if (len < 0) { > > - ERROR("Error reading /proc/meminfo (%s)\n", strerror(readerr)); > > + ERROR("Error reading %s: %s\n", file, strerror(errno)); > > return -1; > > } > > if (len == sizeof(buf)) { > > - ERROR("/proc/meminfo is too large\n"); > > + ERROR("%s is too large\n", file); > > return -1; > > } > > buf[len] = '\0'; > > > > - p = strstr(buf, tag); > > - if (!p) > > - return -1; /* looks like the line we want isn't there */ > > + /* Search for a tag if provided */ > > + if (tag) { > > + p = strstr(buf, tag); > > + if (!p) > > + return -1; /* looks like the line we want isn't there */ > > + p += strlen(tag); > > + } else > > + p = buf; > > > > - p += strlen(tag); > > - errno = 0; > > val = strtol(p, &q, 0); > > - if (errno != 0) { > > - if (errno == ERANGE && val == LONG_MAX) > > - ERROR("Value of %s in /proc/meminfo overflows long\n", > > tag); > > - else > > - ERROR("strtol() failed (%s)\n", strerror(errno)); > > - return -1; > > - } > > if (! isspace(*q)) { > > - ERROR("Couldn't parse /proc/meminfo value\n"); > > + ERROR("Couldn't parse %s value\n", file); > > return -1; > > } > > > > return val; > > } > > > > Ok. > > > +int file_write_ulong(char *file, unsigned long val) > > +{ > > + FILE *f; > > + int ret; > > + > > + f = fopen(file, "w"); > > + if (!f) { > > + ERROR("Couldn't open %s: %s\n", file, strerror(errno)); > > + return -1; > > + } > > + > > + ret = fprintf(f, "%lu", val); > > + fclose(f); > > + return ret > 0 ? 0 : -1; > > +} > > Ok. > > > + > > +int select_pool_counter(unsigned int counter, unsigned long pagesize, > > + char *filename, char **key) > > +{ > > /* > * Return the value of a given counter (e.g. HUGEPAGES_RSVD) for the > * of the requested pagesize. This ordinarily will use a sysfile in > * /sys/kernel/mm/hugepages/hugepages-NNKB/ but in the case of the > * default pagesize may read the Hugepagesize: key in /proc/meminfo. > * The filename and key (if applicable) used is returned to the caller. > */ > Thats not quite right as it does not return the value of any counter. It only tells us the filenames and tags. How about this: /* * Pool counters are typically exposed in sysfs in modern kernels, the * counters for the default page size are exposed in procfs in all kernels * supporting hugepages. Given a specific counter (e.g. HUGEPAGES_RSVD) * and a page size return both a filename and an optional tag to locate * and extract this counter. */ > > + long default_size; > > + char *meminfo_key; > > + char *sysfs_file; > > + > > + if (counter >= HUGEPAGES_MAX_COUNTERS) { > > + ERROR("Invalid counter specified\n"); > > + return -1; > > + } > > + > > + meminfo_key = hugetlb_counter_info[counter].meminfo_key; > > + sysfs_file = hugetlb_counter_info[counter].sysfs_file; > > + if (key) > > + *key = NULL; > > + > > + /* > > + * Get the meminfo page size. > > + * This could be made more efficient if utility functions were shared > > + * between libhugetlbfs and the test suite. For now we will just > > + * read /proc/meminfo. > > + */ > > + default_size = file_read_ulong("/proc/meminfo", "Hugepagesize:"); > > + default_size *= 1024; /* Convert from kB to B */ > > + if (default_size < 0) { > > + ERROR("Cannot determine the default page size\n"); > > + return -1; > > + } > > + > > + /* Convert a pagesize of 0 to the libhugetlbfs default size */ > > + if (pagesize == 0) > > + pagesize = default_size; > > + > > + /* If the user is dealing in the default page size, we can use /proc */ > > + if (pagesize == default_size) { > > + if (meminfo_key && key) { > > + strcpy(filename, "/proc/meminfo"); > > + *key = meminfo_key; > > + } else > > + sprintf(filename, "/proc/sys/vm/%s", sysfs_file); > > + } else /* Use the sysfs interface */ > > + sprintf(filename, "/sys/kernel/mm/hugepages/hugepages-%lukB/%s", > > + pagesize / 1024, sysfs_file); > > + return 0; > > +} > > + > > Ok. > > > +int set_pool_counter(unsigned long pagesize, unsigned int counter, > > + unsigned long val) > > +{ > > + char file[PATH_MAX+1]; > > + > > + if (select_pool_counter(counter, pagesize, file, NULL)) > > + return -1; > > + > > + return file_write_ulong(file, val); > > +} > > + > > static int hpage_size_to_index(unsigned long size) > > { > > int i; > > @@ -197,7 +299,7 @@ static void probe_default_hpage_size(void) > > if (env && strlen(env) > 0) > > size = __lh_parse_page_size(env); > > else { > > - size = read_meminfo("Hugepagesize:"); > > + size = file_read_ulong("/proc/meminfo", "Hugepagesize:"); > > size *= 1024; /* convert from kB to B */ > > } > > > > @@ -510,6 +612,27 @@ int __lh_hugetlbfs_prefault(int fd, void *addr, size_t > > length) > > return 0; > > } > > > > +long get_huge_page_counter(long pagesize, unsigned int counter) > > +{ > > + char file[PATH_MAX+1]; > > + char *key; > > + > > + if (select_pool_counter(counter, pagesize, file, &key)) > > + return -1; > > + > > + return file_read_ulong(file, key); > > +} > > + > > +int set_nr_hugepages(long pagesize, unsigned long val) > > +{ > > + return set_pool_counter(pagesize, HUGEPAGES_TOTAL, val); > > +} > > + > > +int set_nr_overcommit_hugepages(long pagesize, unsigned long val) > > +{ > > + return set_pool_counter(pagesize, HUGEPAGES_OC, val); > > +} > > + > > All Ok. > > > /********************************************************************/ > > /* Library user visible DIAGNOSES/DEBUGGING ONLY functions */ > > /********************************************************************/ > > @@ -545,3 +668,8 @@ long __lh_dump_proc_pid_maps() > > fclose(f); > > return 0; > > } > > + > > +long read_meminfo(const char *tag) > > +{ > > + return file_read_ulong("/proc/meminfo", tag); > > +} > > diff --git a/tests/Makefile b/tests/Makefile > > index c8d47a5..beee18e 100644 > > --- a/tests/Makefile > > +++ b/tests/Makefile > > @@ -100,11 +100,11 @@ obj64/libheapshrink.so: obj64/heapshrink-helper-pic.o > > @mkdir -p obj64 > > $(CC64) -Wl,-soname,$(notdir $@) -shared -o $@ $^ > > > > -$(LIB_TESTS:%=obj32/%): %: %.o obj32/testutils.o > > +$(LIB_TESTS:%=obj32/%): %: %.o obj32/testutils.o obj32/libtestutils.o > > @$(VECHO) LD32 "(lib test)" $@ > > $(CC32) $(LDFLAGS) $(LDFLAGS32) -o $@ $^ $(LDLIBS) -lhugetlbfs > > > > -$(LIB_TESTS:%=obj64/%) $(LIB_TESTS_64:%=obj64/%): %: %.o obj64/testutils.o > > +$(LIB_TESTS:%=obj64/%) $(LIB_TESTS_64:%=obj64/%): %: %.o obj64/testutils.o > > obj64/libtestutils.o > > @$(VECHO) LD64 "(lib test)" $@ > > $(CC64) $(LDFLAGS) $(LDFLAGS64) -o $@ $^ $(LDLIBS) -lhugetlbfs > > > > diff --git a/tests/alloc-instantiate-race.c b/tests/alloc-instantiate-race.c > > index 698fa2f..0929924 100644 > > --- a/tests/alloc-instantiate-race.c > > +++ b/tests/alloc-instantiate-race.c > > @@ -233,7 +233,8 @@ int main(int argc, char *argv[]) > > if (argc != 2) > > CONFIG("Usage: alloc-instantiate-race <private|shared>"); > > > > - totpages = get_pool_counter(HUGEPAGES_FREE, 0); > > + hpage_size = check_hugepagesize(); > > + totpages = get_huge_page_counter(hpage_size, HUGEPAGES_FREE); > > > > if (strcmp(argv[1], "shared") == 0) { > > race_type = MAP_SHARED; > > @@ -243,8 +244,6 @@ int main(int argc, char *argv[]) > > CONFIG("Usage: alloc-instantiate-race <private|shared>"); > > } > > > > - hpage_size = check_hugepagesize(); > > - > > fd = hugetlbfs_unlinked_fd(); > > if (fd < 0) > > FAIL("hugetlbfs_unlinked_fd()"); > > diff --git a/tests/chunk-overcommit.c b/tests/chunk-overcommit.c > > index 9c6f0a8..e8f20e0 100644 > > --- a/tests/chunk-overcommit.c > > +++ b/tests/chunk-overcommit.c > > @@ -59,9 +59,8 @@ int main(int argc, char *argv[]) > > > > test_init(argc, argv); > > > > - totpages = get_pool_counter(HUGEPAGES_FREE, 0); > > - > > hpage_size = check_hugepagesize(); > > + totpages = get_huge_page_counter(hpage_size, HUGEPAGES_FREE); > > > > fd = hugetlbfs_unlinked_fd(); > > if (fd < 0) > > diff --git a/tests/counters.c b/tests/counters.c > > index f97d68a..522a00d 100644 > > --- a/tests/counters.c > > +++ b/tests/counters.c > > @@ -45,8 +45,8 @@ extern int errno; > > > > /* Global test configuration */ > > #define DYNAMIC_SYSCTL "/proc/sys/vm/nr_overcommit_hugepages" > > -static long saved_nr_hugepages; > > -static long saved_oc_hugepages; > > +static long saved_nr_hugepages = -1; > > +static long saved_oc_hugepages = -1; > > static long hpage_size; > > static int private_resv; > > > > @@ -70,17 +70,20 @@ static long prev_surp; > > > > /* Restore original nr_hugepages */ > > void cleanup(void) { > > - set_pool_counter(HUGEPAGES_TOTAL, saved_nr_hugepages, 0); > > + if (hpage_size <= 0) > > + return; > > + if (saved_nr_hugepages >= 0) > > + set_nr_hugepages(hpage_size, saved_nr_hugepages); > > if (saved_oc_hugepages >= 0) > > - set_pool_counter(HUGEPAGES_OC, saved_oc_hugepages, 0); > > + set_nr_overcommit_hugepages(hpage_size, saved_oc_hugepages); > > } > > > > void verify_dynamic_pool_support(void) > > { > > - saved_oc_hugepages = get_pool_counter(HUGEPAGES_OC, 0); > > + saved_oc_hugepages = get_huge_page_counter(hpage_size, HUGEPAGES_OC); > > if (saved_oc_hugepages < 0) > > FAIL("Kernel appears to lack dynamic hugetlb pool support"); > > - set_pool_counter(HUGEPAGES_OC, 10, 0); > > + set_nr_overcommit_hugepages(hpage_size, 10); > > } > > > > void bad_value(int line, const char *name, long expect, long actual) > > @@ -96,10 +99,10 @@ void verify_counters(int line, long et, long ef, long > > er, long es) > > { > > long t, f, r, s; > > > > - t = get_pool_counter(HUGEPAGES_TOTAL, 0); > > - f = get_pool_counter(HUGEPAGES_FREE, 0); > > - r = get_pool_counter(HUGEPAGES_RSVD, 0); > > - s = get_pool_counter(HUGEPAGES_SURP, 0); > > + t = get_huge_page_counter(hpage_size, HUGEPAGES_TOTAL); > > + f = get_huge_page_counter(hpage_size, HUGEPAGES_FREE); > > + r = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD); > > + s = get_huge_page_counter(hpage_size, HUGEPAGES_SURP); > > > > /* Invariant checks */ > > if (t < 0 || f < 0 || r < 0 || s < 0) > > @@ -136,7 +139,7 @@ void _set_nr_hugepages(unsigned long count, int line) > > long min_size; > > long et, ef, er, es; > > > > - if (set_pool_counter(HUGEPAGES_TOTAL, count, 0)) > > + if (set_nr_hugepages(hpage_size, count)) > > FAIL("Cannot set nr_hugepages"); > > > > /* The code below is based on set_max_huge_pages in mm/hugetlb.c */ > > @@ -361,19 +364,16 @@ void run_test(char *desc, int base_nr) > > > > int main(int argc, char ** argv) > > { > > - int fd, base_nr; > > + int base_nr; > > > > test_init(argc, argv); > > - check_must_be_root(); > > - saved_nr_hugepages = get_pool_counter(HUGEPAGES_TOTAL, 0); > > + hpage_size = check_hugepagesize(); > > + saved_nr_hugepages = get_huge_page_counter(hpage_size, HUGEPAGES_TOTAL); > > verify_dynamic_pool_support(); > > + check_must_be_root(); > > > > - fd = hugetlbfs_unlinked_fd(); > > - if ((private_resv = kernel_has_private_reservations(fd)) == -1) > > + if ((private_resv = kernel_has_private_reservations()) == -1) > > FAIL("kernel_has_private_reservations() failed\n"); > > - close(fd); > > - > > - hpage_size = check_hugepagesize(); > > > > /* > > * This test case should require a maximum of 3 huge pages. > > diff --git a/tests/get_huge_pages.c b/tests/get_huge_pages.c > > index c55be8e..62b27ea 100644 > > --- a/tests/get_huge_pages.c > > +++ b/tests/get_huge_pages.c > > @@ -25,13 +25,14 @@ > > > > #include "hugetests.h" > > > > +long hpage_size; > > long oc_hugepages = -1; > > > > /* Restore nr_overcommit_hugepages */ > > void cleanup(void) > > { > > if (oc_hugepages != -1) > > - set_pool_counter(HUGEPAGES_OC, oc_hugepages, 0); > > + set_nr_overcommit_hugepages(hpage_size, oc_hugepages); > > } > > > > /* Confirm a region really frees, only really important for GHP_FALLBACK */ > > @@ -45,7 +46,6 @@ void free_and_confirm_region_free(void *p, int line) { > > void test_get_huge_pages(int num_hugepages) > > { > > int err; > > - long hpage_size = check_hugepagesize(); > > void *p = get_huge_pages(num_hugepages * hpage_size, GHP_DEFAULT); > > if (p == NULL) > > FAIL("get_huge_pages() for %d hugepages", num_hugepages); > > @@ -65,14 +65,13 @@ void test_get_huge_pages(int num_hugepages) > > void test_GHP_FALLBACK(void) > > { > > int err; > > - long hpage_size = check_hugepagesize(); > > - long rsvd_hugepages = get_pool_counter(HUGEPAGES_RSVD, 0); > > - long num_hugepages = get_pool_counter(HUGEPAGES_TOTAL, 0) > > + long rsvd_hugepages = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD); > > + long num_hugepages = get_huge_page_counter(hpage_size, HUGEPAGES_TOTAL) > > - rsvd_hugepages; > > > > /* We must disable overcommitted huge pages to test this */ > > - oc_hugepages = get_pool_counter(HUGEPAGES_OC, 0); > > - set_pool_counter(HUGEPAGES_OC, 0, 0); > > + oc_hugepages = get_huge_page_counter(hpage_size, HUGEPAGES_OC); > > + set_nr_overcommit_hugepages(hpage_size, 0); > > > > /* We should be able to allocate the whole pool */ > > void *p = get_huge_pages(num_hugepages * hpage_size, GHP_DEFAULT); > > @@ -118,6 +117,7 @@ void test_GHP_FALLBACK(void) > > int main(int argc, char *argv[]) > > { > > test_init(argc, argv); > > + hpage_size = gethugepagesize(); > > check_free_huge_pages(4); > > test_get_huge_pages(1); > > test_get_huge_pages(4); > > diff --git a/tests/heap-overflow.c b/tests/heap-overflow.c > > index 7d1b9ba..0f1029c 100644 > > --- a/tests/heap-overflow.c > > +++ b/tests/heap-overflow.c > > @@ -41,7 +41,7 @@ int main(int argc, char **argv) > > > > hpagesize = check_hugepagesize(); > > > > - freepages = get_pool_counter(HUGEPAGES_FREE, 0); > > + freepages = get_huge_page_counter(hpagesize, HUGEPAGES_FREE); > > if (freepages < 3) > > CONFIG("Must have at least 3 free hugepages"); > > > > diff --git a/tests/hugetests.h b/tests/hugetests.h > > index 71a1e21..bb1146e 100644 > > --- a/tests/hugetests.h > > +++ b/tests/hugetests.h > > @@ -127,27 +127,9 @@ static inline long check_hugepagesize() > > return hpage_size; > > } > > > > -/* Keys for reading hugetlb pool counters */ > > -enum { > > - HUGEPAGES_TOTAL, > > - HUGEPAGES_FREE, > > - HUGEPAGES_RSVD, > > - HUGEPAGES_SURP, > > - HUGEPAGES_OC, > > - HUGEPAGES_MAX_COUNTERS, > > -}; > > -struct hugetlb_pool_counter_info_t { > > - char *meminfo_key; > > - char *sysfs_file; > > -}; > > -extern struct hugetlb_pool_counter_info_t hugetlb_counter_info[]; > > -long get_pool_counter(unsigned int counter, unsigned long pagesize); > > -int set_pool_counter(unsigned int counter, unsigned long val, > > - unsigned long pagesize); > > - > > int using_system_hpage_size(const char *mount); > > > > /* WARNING: Racy -- use for test cases only! */ > > -int kernel_has_private_reservations(int fd); > > +int kernel_has_private_reservations(void); > > > > #endif /* _HUGETESTS_H */ > > diff --git a/tests/libtestutils.c b/tests/libtestutils.c > > new file mode 100644 > > index 0000000..93388a9 > > --- /dev/null > > +++ b/tests/libtestutils.c > > @@ -0,0 +1,137 @@ > > +/* > > + * libhugetlbfs - Easy use of Linux hugepages > > + * Copyright (C) 2008 David Gibson & Adam Litke, IBM Corporation. > > + * > > + * This library is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU Lesser General Public License > > + * as published by the Free Software Foundation; either version 2.1 of > > + * the License, or (at your option) any later version. > > + * > > + * This library is distributed in the hope that it will be useful, but > > + * WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + * Lesser General Public License for more details. > > + * > > + * You should have received a copy of the GNU Lesser General Public > > + * License along with this library; if not, write to the Free Software > > + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA > > + */ > > + > > +#define _LARGEFILE64_SOURCE > > +#define _GNU_SOURCE > > + > > +#include <stdio.h> > > +#include <stdlib.h> > > +#include <limits.h> > > +#include <string.h> > > +#include <errno.h> > > +#include <ctype.h> > > +#include <unistd.h> > > +#include <signal.h> > > +#include <sys/types.h> > > +#include <sys/vfs.h> > > +#include <sys/ipc.h> > > +#include <sys/shm.h> > > +#include <sys/stat.h> > > +#include <sys/mman.h> > > +#include <fcntl.h> > > + > > +#include "hugetlbfs.h" > > +#include "hugetests.h" > > + > > +void check_free_huge_pages(int nr_pages_needed) > > +{ > > + long hpage_size = gethugepagesize(); > > + int freepages = get_huge_page_counter(hpage_size, HUGEPAGES_FREE); > > + if (freepages < nr_pages_needed) > > + CONFIG("Must have at least %i free hugepages", nr_pages_needed); > > +} > > + > > Ok. > > > +int using_system_hpage_size(const char *mount) > > +{ > > + struct statfs64 sb; > > + int err; > > + long meminfo_size, mount_size; > > + > > + if (!mount) > > + FAIL("using_system_hpage_size: hugetlbfs is not mounted\n"); > > + > > + err = statfs64(mount, &sb); > > + if (err) > > + FAIL("statfs64: %s\n", strerror(errno)); > > + > > + meminfo_size = read_meminfo("Hugepagesize:"); > > + if (meminfo_size < 0) > > + FAIL("using_system_hpage_size: Failed to read /proc/meminfo\n"); > > + > > + mount_size = sb.f_bsize / 1024; /* Compare to meminfo in kB */ > > + if (mount_size == meminfo_size) > > + return 1; > > + else > > + return 0; > > +} > > Ok. > > > + > > +/* WARNING: This function relies on the hugetlb pool counters in a way that > > + * is known to be racy. Due to the expected usage of hugetlbfs test > > cases, the > > + * risk of a race is acceptible. This function should NOT be used for real > > + * applications. > > + */ > > +int kernel_has_private_reservations(void) > > +{ > > + int fd; > > + long t, f, r, s; > > + long nt, nf, nr, ns; > > + long hpage_size = gethugepagesize(); > > + void *map; > > + > > + /* Read pool counters */ > > + t = get_huge_page_counter(hpage_size, HUGEPAGES_TOTAL); > > + f = get_huge_page_counter(hpage_size, HUGEPAGES_FREE); > > + r = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD); > > + s = get_huge_page_counter(hpage_size, HUGEPAGES_SURP); > > + > > + fd = hugetlbfs_unlinked_fd(); > > + if (fd < 0) { > > + ERROR("kernel_has_private_reservations: hugetlbfs_unlinked_fd: " > > + "%s\n", strerror(errno)); > > + return -1; > > + } > > + map = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); > > + if (map == MAP_FAILED) { > > + ERROR("kernel_has_private_reservations: mmap: %s\n", > > + strerror(errno)); > > + return -1; > > + } > > + > > + /* Recheck the counters */ > > + nt = get_huge_page_counter(hpage_size, HUGEPAGES_TOTAL); > > + nf = get_huge_page_counter(hpage_size, HUGEPAGES_FREE); > > + nr = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD); > > + ns = get_huge_page_counter(hpage_size, HUGEPAGES_SURP); > > + > > + munmap(map, hpage_size); > > + close(fd); > > + > > + /* > > + * There are only three valid cases: > > + * 1) If a surplus page was allocated to create a reservation, all > > + * four pool counters increment > > + * 2) All counters remain the same except for Hugepages_Rsvd, then > > + * a reservation was created using an existing pool page. > > + * 3) All counters remain the same, indicates that no reservation has > > + * been created > > + */ > > + if ((nt == t + 1) && (nf == f + 1) && (ns == s + 1) && (nr == r + 1)) { > > + return 1; > > + } else if ((nt == t) && (nf == f) && (ns == s)) { > > + if (nr == r + 1) > > + return 1; > > + else if (nr == r) > > + return 0; > > + } else { > > + ERROR("kernel_has_private_reservations: bad counter state - " > > + "T:%li F:%li R:%li S:%li -> T:%li F:%li R:%li S:%li\n", > > + t, f, r, s, nt, nf, nr, ns); > > + } > > + return -1; > > +} > > diff --git a/tests/misaligned_offset.c b/tests/misaligned_offset.c > > index 4b1eb8f..e82ffe1 100644 > > --- a/tests/misaligned_offset.c > > +++ b/tests/misaligned_offset.c > > @@ -44,11 +44,6 @@ > > * 856fc29505556cf263f3dcda2533cf3766c14ab6. > > */ > > > > -static unsigned long read_free(void) > > -{ > > - return get_pool_counter(HUGEPAGES_FREE, 0); > > -} > > - > > #define RANDOM_CONSTANT 0x1234ABCD > > > > int main(int argc, char *argv[]) > > @@ -80,7 +75,8 @@ int main(int argc, char *argv[]) > > * backout path for the bogus mapping is buggy, which it was > > * in some kernels. */ > > > > - verbose_printf("Free hugepages: %lu\n", read_free()); > > + verbose_printf("Free hugepages: %lu\n", > > + get_huge_page_counter(hpage_size, HUGEPAGES_FREE)); > > > > verbose_printf("Mapping reference map..."); > > /* First get arena of three hpages size, at file offset 4GB */ > > @@ -89,7 +85,8 @@ int main(int argc, char *argv[]) > > FAIL("mmap() offset 4GB: %s", strerror(errno)); > > verbose_printf("%p-%p\n", p, p+2*hpage_size-1); > > > > - verbose_printf("Free hugepages: %lu\n", read_free()); > > + verbose_printf("Free hugepages: %lu\n", > > + get_huge_page_counter(hpage_size, HUGEPAGES_FREE)); > > > > /* Instantiate the pages */ > > verbose_printf("Instantiating..."); > > @@ -98,7 +95,8 @@ int main(int argc, char *argv[]) > > *pi = RANDOM_CONSTANT; > > verbose_printf("done.\n"); > > > > - verbose_printf("Free hugepages: %lu\n", read_free()); > > + verbose_printf("Free hugepages: %lu\n", > > + get_huge_page_counter(hpage_size, HUGEPAGES_FREE)); > > > > /* Toggle the permissions on the first page. This forces TLB > > * entries (including hash page table on powerpc) to be > > @@ -123,13 +121,15 @@ int main(int argc, char *argv[]) > > strerror(errno), strerror(EINVAL)); > > verbose_printf("%s\n", strerror(errno)); > > > > - verbose_printf("Free hugepages: %lu\n", read_free()); > > + verbose_printf("Free hugepages: %lu\n", > > + get_huge_page_counter(hpage_size, HUGEPAGES_FREE)); > > > > if (*pi != RANDOM_CONSTANT) > > FAIL("Pre-existing mapping clobbered: %x instead of %x", > > *pi, RANDOM_CONSTANT); > > > > - verbose_printf("Free hugepages: %lu\n", read_free()); > > + verbose_printf("Free hugepages: %lu\n", > > + get_huge_page_counter(hpage_size, HUGEPAGES_FREE)); > > > > /* The real test is whether we got a bad_pud() or similar > > * during the run. The check above, combined with the earlier > > diff --git a/tests/quota.c b/tests/quota.c > > index 3dc9dcd..4961371 100644 > > --- a/tests/quota.c > > +++ b/tests/quota.c > > @@ -207,7 +207,7 @@ void _spawn(int l, int expected_result, unsigned long > > size, int mmap_flags, > > > > int main(int argc, char ** argv) > > { > > - int fd, private_resv; > > + int private_resv; > > int bad_priv_resv; > > > > test_init(argc, argv); > > @@ -221,9 +221,7 @@ int main(int argc, char ** argv) > > check_must_be_root(); > > check_free_huge_pages(1); > > > > - fd = hugetlbfs_unlinked_fd(); > > - private_resv = kernel_has_private_reservations(fd); > > - close(fd); > > + private_resv = kernel_has_private_reservations(); > > if (private_resv == -1) > > FAIL("kernel_has_private_reservations() failed\n"); > > bad_priv_resv = private_resv ? BAD_EXIT : BAD_SIG; > > diff --git a/tests/shmoverride_unlinked.c b/tests/shmoverride_unlinked.c > > index 2721b92..a8af228 100644 > > --- a/tests/shmoverride_unlinked.c > > +++ b/tests/shmoverride_unlinked.c > > @@ -94,7 +94,7 @@ void _shmunmap(int s, int line) > > } > > #define shmunmap(s) _shmunmap(s, __LINE__) > > > > -void set_nr_hugepages(unsigned long count) > > +void setup_hugetlb_pool(unsigned long count) > > { > > FILE *fd; > > unsigned long poolsize; > > @@ -116,7 +116,7 @@ void run_test(char *desc, int hpages, int bpages, int > > pool_nr, int expect_diff) > > { > > long resv_before, resv_after; > > verbose_printf("%s...\n", desc); > > - set_nr_hugepages(pool_nr); > > + setup_hugetlb_pool(pool_nr); > > > > /* untouched, shared mmap */ > > resv_before = read_meminfo("HugePages_Rsvd:"); > > @@ -135,7 +135,7 @@ void run_test(char *desc, int hpages, int bpages, int > > pool_nr, int expect_diff) > > void cleanup(void) > > { > > if (saved_nr_hugepages >= 0) > > - set_nr_hugepages(saved_nr_hugepages); > > + setup_hugetlb_pool(saved_nr_hugepages); > > } > > > > int main(int argc, char **argv) > > @@ -166,7 +166,7 @@ int main(int argc, char **argv) > > run_test("override-requested-unaligned", 1, 1, POOL_SIZE, 2); > > > > /* Run the test with no pool but requested large pages */ > > - set_nr_hugepages(0); > > + setup_hugetlb_pool(0); > > run_test("override-requested-aligned-nopool", 1, 0, 0, 0); > > > > PASS(); > > diff --git a/tests/testutils.c b/tests/testutils.c > > index 6534e9c..b8a1bf2 100644 > > --- a/tests/testutils.c > > +++ b/tests/testutils.c > > @@ -36,6 +36,7 @@ > > #include <sys/mman.h> > > #include <fcntl.h> > > > > +#include "hugetlbfs.h" > > #include "hugetests.h" > > > > #define HUGETLBFS_MAGIC 0x958458f6 > > @@ -45,13 +46,6 @@ > > int verbose_test = 1; > > char *test_name; > > > > -void check_free_huge_pages(int nr_pages_needed) > > -{ > > - int freepages = get_pool_counter(HUGEPAGES_FREE, 0); > > - if (freepages < nr_pages_needed) > > - CONFIG("Must have at least %i free hugepages", nr_pages_needed); > > -} > > - > > void check_must_be_root(void) > > { > > uid_t uid = getuid(); > > @@ -205,164 +199,6 @@ int test_addr_huge(void *p) > > return (sb.f_type == HUGETLBFS_MAGIC); > > } > > > > -struct hugetlb_pool_counter_info_t hugetlb_counter_info[] = { > > - [HUGEPAGES_TOTAL] = { > > - .meminfo_key = "HugePages_Total:", > > - .sysfs_file = "nr_hugepages", > > - }, > > - [HUGEPAGES_FREE] = { > > - .meminfo_key = "HugePages_Free:", > > - .sysfs_file = "free_hugepages", > > - }, > > - [HUGEPAGES_RSVD] = { > > - .meminfo_key = "HugePages_Rsvd:", > > - .sysfs_file = "resv_hugepages", > > - }, > > - [HUGEPAGES_SURP] = { > > - .meminfo_key = "HugePages_Surp:", > > - .sysfs_file = "surplus_hugepages", > > - }, > > - [HUGEPAGES_OC] = { > > - .meminfo_key = NULL, > > - .sysfs_file = "nr_overcommit_hugepages" > > - }, > > -}; > > - > > -long file_read_ulong(char *file, const char *tag) > > -{ > > - int fd; > > - char buf[MEMINFO_SZ]; > > - int len, readerr; > > - char *p, *q; > > - long val; > > - > > - fd = open(file, O_RDONLY); > > - if (fd < 0) { > > - ERROR("Couldn't open %s: %s\n", file, strerror(errno)); > > - return -1; > > - } > > - > > - len = read(fd, buf, sizeof(buf)); > > - readerr = errno; > > - close(fd); > > - if (len < 0) { > > - ERROR("Error reading %s: %s\n", file, strerror(errno)); > > - return -1; > > - } > > - if (len == sizeof(buf)) { > > - ERROR("%s is too large\n", file); > > - return -1; > > - } > > - buf[len] = '\0'; > > - > > - /* Search for a tag if provided */ > > - if (tag) { > > - p = strstr(buf, tag); > > - if (!p) > > - return -1; /* looks like the line we want isn't there */ > > - p += strlen(tag); > > - } else > > - p = buf; > > - > > - val = strtol(p, &q, 0); > > - if (! isspace(*q)) { > > - ERROR("Couldn't parse %s value\n", file); > > - return -1; > > - } > > - > > - return val; > > -} > > - > > -int file_write_ulong(char *file, unsigned long val) > > -{ > > - FILE *f; > > - int ret; > > - > > - f = fopen(file, "w"); > > - if (!f) { > > - ERROR("Couldn't open %s: %s\n", file, strerror(errno)); > > - return -1; > > - } > > - > > - ret = fprintf(f, "%lu", val); > > - fclose(f); > > - return ret > 0 ? 0 : -1; > > -} > > - > > -int select_pool_counter(unsigned int counter, unsigned long pagesize, > > - char *filename, char **key) > > -{ > > - long default_size; > > - char *meminfo_key; > > - char *sysfs_file; > > - > > - if (counter >= HUGEPAGES_MAX_COUNTERS) { > > - ERROR("Invalid counter specified\n"); > > - return -1; > > - } > > - > > - meminfo_key = hugetlb_counter_info[counter].meminfo_key; > > - sysfs_file = hugetlb_counter_info[counter].sysfs_file; > > - if (key) > > - *key = NULL; > > - > > - /* > > - * Get the meminfo page size. > > - * This could be made more efficient if utility functions were shared > > - * between libhugetlbfs and the test suite. For now we will just > > - * read /proc/meminfo. > > - */ > > - default_size = file_read_ulong("/proc/meminfo", "Hugepagesize:"); > > - default_size *= 1024; /* Convert from kB to B */ > > - if (default_size < 0) { > > - ERROR("Cannot determine the default page size\n"); > > - return -1; > > - } > > - > > - /* Convert a pagesize of 0 to the libhugetlbfs default size */ > > - if (pagesize == 0) > > - pagesize = default_size; > > - > > - /* If the user is dealing in the default page size, we can use /proc */ > > - if (pagesize == default_size) { > > - if (meminfo_key && key) { > > - strcpy(filename, "/proc/meminfo"); > > - *key = meminfo_key; > > - } else > > - sprintf(filename, "/proc/sys/vm/%s", sysfs_file); > > - } else /* Use the sysfs interface */ > > - sprintf(filename, "/sys/kernel/mm/hugepages/hugepages-%lukB/%s", > > - pagesize / 1024, sysfs_file); > > - return 0; > > -} > > - > > -long get_pool_counter(unsigned int counter, unsigned long pagesize) > > -{ > > - char file[PATH_MAX+1]; > > - char *key; > > - > > - if (select_pool_counter(counter, pagesize, file, &key)) > > - return -1; > > - > > - return file_read_ulong(file, key); > > -} > > - > > -int set_pool_counter(unsigned int counter, unsigned long val, > > - unsigned long pagesize) > > -{ > > - char file[PATH_MAX+1]; > > - > > - if (select_pool_counter(counter, pagesize, file, NULL)) > > - return -1; > > - > > - return file_write_ulong(file, val); > > -} > > - > > -long read_meminfo(const char *tag) > > -{ > > - return file_read_ulong("/proc/meminfo", tag); > > -} > > - > > ino_t get_addr_inode(void *p) > > { > > char name[256]; > > @@ -406,89 +242,3 @@ int remove_shmid(int shmid) > > } > > return 0; > > } > > - > > -/* WARNING: This function relies on the hugetlb pool counters in a way that > > - * is known to be racy. Due to the expected usage of hugetlbfs test > > cases, the > > - * risk of a race is acceptible. This function should NOT be used for real > > - * applications. > > - */ > > -int kernel_has_private_reservations(int fd) > > -{ > > - long t, f, r, s; > > - long nt, nf, nr, ns; > > - void *map; > > - > > - /* Read pool counters */ > > - t = get_pool_counter(HUGEPAGES_TOTAL, 0); > > - f = get_pool_counter(HUGEPAGES_FREE, 0); > > - r = get_pool_counter(HUGEPAGES_RSVD, 0); > > - s = get_pool_counter(HUGEPAGES_SURP, 0); > > - > > - > > - if (fd < 0) { > > - ERROR("kernel_has_private_reservations: hugetlbfs_unlinked_fd: " > > - "%s\n", strerror(errno)); > > - return -1; > > - } > > - map = mmap(NULL, gethugepagesize(), PROT_READ|PROT_WRITE, MAP_PRIVATE, > > fd, 0); > > - if (map == MAP_FAILED) { > > - ERROR("kernel_has_private_reservations: mmap: %s\n", > > - strerror(errno)); > > - return -1; > > - } > > - > > - /* Recheck the counters */ > > - nt = get_pool_counter(HUGEPAGES_TOTAL, 0); > > - nf = get_pool_counter(HUGEPAGES_FREE, 0); > > - nr = get_pool_counter(HUGEPAGES_RSVD, 0); > > - ns = get_pool_counter(HUGEPAGES_SURP, 0); > > - > > - munmap(map, gethugepagesize()); > > - > > - /* > > - * There are only three valid cases: > > - * 1) If a surplus page was allocated to create a reservation, all > > - * four pool counters increment > > - * 2) All counters remain the same except for Hugepages_Rsvd, then > > - * a reservation was created using an existing pool page. > > - * 3) All counters remain the same, indicates that no reservation has > > - * been created > > - */ > > - if ((nt == t + 1) && (nf == f + 1) && (ns == s + 1) && (nr == r + 1)) { > > - return 1; > > - } else if ((nt == t) && (nf == f) && (ns == s)) { > > - if (nr == r + 1) > > - return 1; > > - else if (nr == r) > > - return 0; > > - } else { > > - ERROR("kernel_has_private_reservations: bad counter state - " > > - "T:%li F:%li R:%li S:%li -> T:%li F:%li R:%li S:%li\n", > > - t, f, r, s, nt, nf, nr, ns); > > - } > > - return -1; > > -} > > - > > -int using_system_hpage_size(const char *mount) > > -{ > > - struct statfs64 sb; > > - int err; > > - long meminfo_size, mount_size; > > - > > - if (!mount) > > - FAIL("using_system_hpage_size: hugetlbfs is not mounted\n"); > > - > > - err = statfs64(mount, &sb); > > - if (err) > > - FAIL("statfs64: %s\n", strerror(errno)); > > - > > - meminfo_size = file_read_ulong("/proc/meminfo", "Hugepagesize:"); > > - if (meminfo_size < 0) > > - FAIL("using_system_hpage_size: Failed to read /proc/meminfo\n"); > > - > > - mount_size = sb.f_bsize / 1024; /* Compare to meminfo in kB */ > > - if (mount_size == meminfo_size) > > - return 1; > > - else > > - return 0; > > -} > > diff --git a/tests/truncate_reserve_wraparound.c > > b/tests/truncate_reserve_wraparound.c > > index f7af96b..d1da59f 100644 > > --- a/tests/truncate_reserve_wraparound.c > > +++ b/tests/truncate_reserve_wraparound.c > > @@ -50,11 +50,6 @@ static void sigbus_handler(int signum, siginfo_t *si, > > void *uc) > > siglongjmp(sig_escape, 17); > > } > > > > -static unsigned long read_reserved(void) > > -{ > > - return get_pool_counter(HUGEPAGES_RSVD, 0); > > -} > > - > > int main(int argc, char *argv[]) > > { > > long hpage_size; > > @@ -77,7 +72,7 @@ int main(int argc, char *argv[]) > > if (fd < 0) > > FAIL("hugetlbfs_unlinked_fd()"); > > > > - initial_rsvd = read_reserved(); > > + initial_rsvd = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD); > > verbose_printf("Reserve count before map: %lu\n", initial_rsvd); > > > > p = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED, > > @@ -86,16 +81,18 @@ int main(int argc, char *argv[]) > > FAIL("mmap(): %s", strerror(errno)); > > q = p; > > > > - verbose_printf("Reserve count after map: %lu\n", read_reserved()); > > + verbose_printf("Reserve count after map: %lu\n", > > + get_huge_page_counter(hpage_size, HUGEPAGES_RSVD)); > > > > *q = 0; > > - verbose_printf("Reserve count after touch: %lu\n", read_reserved()); > > + verbose_printf("Reserve count after touch: %lu\n", > > + get_huge_page_counter(hpage_size, HUGEPAGES_RSVD)); > > > > err = ftruncate(fd, 0); > > if (err) > > FAIL("ftruncate(): %s", strerror(errno)); > > > > - rsvd = read_reserved(); > > + rsvd = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD); > > verbose_printf("Reserve count after truncate: %lu\n", rsvd); > > if (rsvd != initial_rsvd) > > FAIL("Reserved count is not restored after truncate: %lu > > instead of %lu", > > @@ -113,7 +110,7 @@ int main(int argc, char *argv[]) > > if (sigbus_count != 1) > > FAIL("Didn't SIGBUS after truncate"); > > > > - rsvd = read_reserved(); > > + rsvd = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD); > > verbose_printf("Reserve count after SIGBUS fault: %lu\n", rsvd); > > if (rsvd != initial_rsvd) > > FAIL("Reserved count is altered by SIGBUS fault: %lu instead of > > %lu", > > @@ -122,12 +119,12 @@ int main(int argc, char *argv[]) > > munmap(p, hpage_size); > > > > verbose_printf("Reserve count after munmap(): %lu\n", > > - read_reserved()); > > + get_huge_page_counter(hpage_size, HUGEPAGES_RSVD)); > > > > close(fd); > > > > verbose_printf("Reserve count after close(): %lu\n", > > - read_reserved()); > > + get_huge_page_counter(hpage_size, HUGEPAGES_RSVD)); > > > > PASS(); > > } > > diff --git a/tests/truncate_sigbus_versus_oom.c > > b/tests/truncate_sigbus_versus_oom.c > > index ab7d90c..7aa2fe5 100644 > > --- a/tests/truncate_sigbus_versus_oom.c > > +++ b/tests/truncate_sigbus_versus_oom.c > > @@ -58,9 +58,8 @@ int main(int argc, char *argv[]) > > > > test_init(argc, argv); > > > > - totpages = get_pool_counter(HUGEPAGES_FREE, 0); > > - > > hpage_size = check_hugepagesize(); > > + totpages = get_huge_page_counter(hpage_size, HUGEPAGES_TOTAL); > > > > fd = hugetlbfs_unlinked_fd(); > > if (fd < 0) > > Addition of comment is optional. > > Acked-by: Mel Gorman <[EMAIL PROTECTED]> -apw ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ _______________________________________________ Libhugetlbfs-devel mailing list Libhugetlbfs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libhugetlbfs-devel