On (15/07/08 15:15), Adam Litke didst pronounce:
> The private reservations feature in new kernels changes the semantics of
> private huge page mappings in ways that are recognizable by the libhugetlbfs
> test suite.  So far, counters and quota are effected.  Reserved private
> mappings now affect the pool counters in the same way as shared mappings.  FS
> quota is now allocated up-front (mmap time) for private mappings so going over
> quota will now cause the mmap to fail rather than a SIGBUS at page
> instantiation time.
> 
> To preserve backwards compatibility, the test suite must correctly test 
> kernels
> with and without private reservation support.  To achieve this, a function to
> check the running kernel's semantics is needed.  This patch adds a function
> that attempts to check for private reservations.  Use of the pool counters in
> the manner employed is racy but since this is a test suite and meant to be run
> by itself, the counters method should work.  The function is clearly commented
> to warn against using it for real programs.
> 
> Signed-off-by: Adam Litke <[EMAIL PROTECTED]>
> ---
> 
>  tests/counters.c  |   26 +++++++++++++++-------
>  tests/hugetests.h |    3 +++
>  tests/quota.c     |   18 +++++++++++++++
>  tests/testutils.c |   62 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 100 insertions(+), 9 deletions(-)
> 
> 
> diff --git a/tests/counters.c b/tests/counters.c
> index e3a804b..8abfe19 100644
> --- a/tests/counters.c
> +++ b/tests/counters.c
> @@ -47,6 +47,7 @@ extern int errno;
>  #define DYNAMIC_SYSCTL "/proc/sys/vm/nr_overcommit_hugepages"
>  static long saved_nr_hugepages;
>  static long hpage_size;
> +static int private_resv;
>  
>  /* State arrays for our mmaps */
>  #define NR_SLOTS     2
> @@ -222,8 +223,12 @@ void _map(int s, int hpages, int flags, int line)
>        * satisfy the reservation, surplus pages are added to the pool.
>        * NOTE: This code assumes that the whole mapping needs to be
>        * reserved and hence, will not work with partial reservations.
> +      *
> +      * If the kernel supports private reservations, then MAP_PRIVATE
> +      * mappings behave like MAP_SHARED at mmap time.  Otherwise,
> +      * no counter updates will occur.
>        */
> -     if (flags & MAP_SHARED) {
> +     if ((flags & MAP_SHARED) || private_resv) {
>               unsigned long shortfall = 0;
>               if (hpages + prev_resv > prev_free)
>                       shortfall = hpages - prev_free + prev_resv;
> @@ -232,7 +237,6 @@ void _map(int s, int hpages, int flags, int line)
>               er = prev_resv + hpages;
>               es = prev_surp + shortfall;
>       }
> -     /* MAP_PRIVATE mappings do not alter the counters in any way. */
>  
>       verify_counters(line, et, ef, er, es);
>  }
> @@ -273,7 +277,7 @@ void _unmap(int s, int hpages, int flags, int line)
>        * reservation.  If those pages were not touched, then they will
>        * not have been freed by the code above.  Free them here.
>        */
> -     if (flags & MAP_SHARED) {
> +     if ((flags & MAP_SHARED) || private_resv) {
>               int unused_surplus = min(hpages - touched[s], es);
>               et -= unused_surplus;
>               ef -= unused_surplus;
> @@ -304,15 +308,15 @@ void _touch(int s, int hpages, int flags, int line)
>       touched[s] = max(touched[s], hpages);
>  
>       /*
> -      * Shared mappings consume resv pages that were previously
> -      * allocated.  Also deduct them from the free count.
> +      * Shared (and private when supported) mappings and consume resv pages 
> +      * that were previously allocated. Also deduct them from the free count.
>        *
> -      * Private mappings may need to allocate surplus pages to
> +      * Unreserved private mappings may need to allocate surplus pages to
>        * satisfy the fault.  The surplus pages become part of the pool
>        * which could elevate total, free, and surplus counts.  resv is
>        * unchanged but free must be decreased.
>        */
> -     if (flags & MAP_SHARED) {
> +     if (flags & MAP_SHARED || private_resv) {
>               et = prev_total;
>               ef = prev_free - hpages;
>               er = prev_resv - hpages;
> @@ -375,12 +379,18 @@ void run_test(char *desc, int base_nr)
>  
>  int main(int argc, char ** argv)
>  {
> -     int base_nr;
> +     int fd, base_nr;
>  
>       test_init(argc, argv);
>       check_must_be_root();
>       saved_nr_hugepages = read_meminfo("HugePages_Total:");
>       verify_dynamic_pool_support();
> +
> +     fd = hugetlbfs_unlinked_fd();
> +     if ((private_resv = kernel_has_private_reservations(fd)) == -1)
> +             FAIL("kernel_has_private_reservations() failed\n");
> +     close(fd);
> +
>       hpage_size = check_hugepagesize();
>  
>       /*
> diff --git a/tests/hugetests.h b/tests/hugetests.h
> index 3b2d81d..61f339b 100644
> --- a/tests/hugetests.h
> +++ b/tests/hugetests.h
> @@ -127,4 +127,7 @@ static inline long check_hugepagesize()
>       return hpage_size;
>  }
>  
> +/* WARNING: Racy -- use for test cases only! */
> +int kernel_has_private_reservations(int fd);
> +
>  #endif /* _HUGETESTS_H */
> diff --git a/tests/quota.c b/tests/quota.c
> index 00566bc..832c980 100644
> --- a/tests/quota.c
> +++ b/tests/quota.c
> @@ -183,13 +183,21 @@ void _spawn(int l, int expected_result, unsigned long 
> size, int flags,
>  
>  int main(int argc, char ** argv)
>  {
> +     int fd, private_resv;
> +
>       test_init(argc, argv);
>       check_must_be_root();
>       mountpoint[0] = '\0';
>       hpage_size = check_hugepagesize();
>  
> +     check_free_huge_pages(1);
>       get_quota_fs(hpage_size);
>  
> +     fd = hugetlbfs_unlinked_fd();
> +     if ((private_resv = kernel_has_private_reservations(fd)) == -1)
> +             FAIL("kernel_has_private_reservations() failed\n");
> +     close(fd);
> +
>       /*
>        * Check that simple page instantiation works within quota limits
>        * for private and shared mappings.
> @@ -202,7 +210,15 @@ int main(int argc, char ** argv)
>        * over quota.
>        */
>       spawn(BAD_EXIT, 2 * hpage_size, MAP_SHARED, 0);
> -     spawn(BAD_SIG, 2 * hpage_size, MAP_PRIVATE, 0);
> +
> +     /*
> +      * If private mappings are reserved, the quota is checked up front
> +      * (as is the case for shared mappings).
> +      */
> +     if (private_resv)
> +             spawn(BAD_EXIT, 2 * hpage_size, MAP_PRIVATE, 0);
> +     else
> +             spawn(BAD_SIG, 2 * hpage_size, MAP_PRIVATE, 0);
>  
>       /*
>        * COW should not be allowed if doing so puts the fs over quota.
> diff --git a/tests/testutils.c b/tests/testutils.c
> index 9d48482..6953314 100644
> --- a/tests/testutils.c
> +++ b/tests/testutils.c
> @@ -33,6 +33,7 @@
>  #include <sys/ipc.h>
>  #include <sys/shm.h>
>  #include <sys/stat.h>
> +#include <sys/mman.h>
>  #include <fcntl.h>
>  
>  #include "hugetests.h"
> @@ -287,3 +288,64 @@ 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 = read_meminfo("HugePages_Total:");
> +     f = read_meminfo("HugePages_Free:");
> +     r = read_meminfo("HugePages_Rsvd:");
> +     s = read_meminfo("HugePages_Surp:");
> +
> +     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;
> +     }

Why is this an error? It implies that the kernel supports private
reservations bu the pool is empty.

> +
> +     /* Recheck the counters */
> +     nt = read_meminfo("HugePages_Total:");
> +     nf = read_meminfo("HugePages_Free:");
> +     nr = read_meminfo("HugePages_Rsvd:");
> +     ns = read_meminfo("HugePages_Surp:");
> +
> +     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;
> +}
> 
> 
> -------------------------------------------------------------------------
> 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
> 

-- 
Mel Gorman
Part-time Phd Student                          Linux Technology Center
University of Limerick                         IBM Dublin Software Lab

-------------------------------------------------------------------------
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

Reply via email to