Allow resize of specific pools via the --pool-minimum-adjust and
--pool-maximum-adjust commands.  The first affects the number of static
pages in the pool, the second affects the number of overcommit pages
for the pool.  These are exposed as lower and upper bound on the pool
to match the display in --pool-list.  Adjustments are either absolute,
or relative with a + or - prefix.  For example the following incantion
increases the 2MB page pool minimum by 10 pages.

        --pool-minimum-adjust 2048kb:+10

Note we must handle the possiblity that the pool minimum may not increase
to the value requested should memory not be available.  In this case we must
recalculate the overcommit.

Signed-off-by: Andy Whitcroft <[EMAIL PROTECTED]>
Acked-by: Mel Gorman <[EMAIL PROTECTED]>
---
 hugeadm.c               |  138 ++++++++++++++++++++++++++++++++++++++++++++++-
 hugeutils.c             |    7 ++-
 libhugetlbfs_internal.h |    1 +
 3 files changed, 141 insertions(+), 5 deletions(-)

diff --git a/hugeadm.c b/hugeadm.c
index 89f30d9..703e724 100644
--- a/hugeadm.c
+++ b/hugeadm.c
@@ -35,6 +35,7 @@
 
 #define REPORT_UTIL "hugeadm"
 #include "libhugetlbfs_internal.h"
+#include "hugetlbfs.h"
 
 extern int optind;
 extern char *optarg;
@@ -48,6 +49,10 @@ void print_usage()
        fprintf(stderr, "options:\n");
 
        OPTION("--pool-list", "List all pools");
+       OPTION("--pool-pages-min <size>:[+|-]<count>", "");
+       CONT("Adjust pool 'size' lower bound");
+       OPTION("--pool-pages-max <size>:[+|-]<count>", "");
+       CONT("Adjust pool 'size' upper bound");
 
        OPTION("--help, -h", "Prints this message");
 }
@@ -57,8 +62,10 @@ int opt_dry_run = 0;
 /*
  * getopts return values for options which are long only.
  */
-#define LONG_POOL      ('p' << 8)
-#define LONG_POOL_LIST (LONG_POOL|'l')
+#define LONG_POOL              ('p' << 8)
+#define LONG_POOL_LIST         (LONG_POOL|'l')
+#define LONG_POOL_MIN_ADJ      (LONG_POOL|'m')
+#define LONG_POOL_MAX_ADJ      (LONG_POOL|'M')
 
 #define MAX_POOLS      32
 
@@ -90,6 +97,123 @@ void pool_list(void)
        }
 }
 
+enum {
+       POOL_MIN,
+       POOL_MAX,
+};
+
+static long value_adjust(char *adjust_str, long base)
+{
+       long adjust;
+       char *iter;
+
+       /* Convert and validate the adjust. */
+       adjust = strtol(adjust_str, &iter, 0);
+       if (*iter) {
+               ERROR("%s: invalid adjustment\n", adjust_str);
+               exit(EXIT_FAILURE);
+       }
+
+       if (adjust_str[0] != '+' && adjust_str[0] != '-')
+               base = 0;
+
+       /* Ensure we neither go negative nor exceed LONG_MAX. */
+       if (adjust < 0 && -adjust > base) {
+               adjust = -base;
+       }
+       if (adjust > 0 && (base + adjust) < base) {
+               adjust = LONG_MAX - base;
+       }
+       base += adjust;
+
+       return base;
+}
+
+
+void pool_adjust(char *cmd, unsigned int counter)
+{
+       struct hpage_pool pools[MAX_POOLS];
+       int pos;
+       int cnt;
+
+       char *iter = NULL;
+       char *page_size_str = NULL;
+       char *adjust_str = NULL;
+       long page_size;
+
+       unsigned long min;
+       unsigned long max;
+
+       /* Extract the pagesize and adjustment. */
+       page_size_str = strtok_r(cmd, ":", &iter);
+       if (page_size_str)
+               adjust_str = strtok_r(NULL, ":", &iter);
+
+       if (!page_size_str || !adjust_str) {
+               ERROR("%s: invalid resize specificiation\n", cmd);
+               exit(EXIT_FAILURE);
+       }
+       DEBUG("page_size<%s> adjust<%s> counter<%d>\n",
+                                       page_size_str, adjust_str, counter);
+
+       /* Convert and validate the page_size. */
+       page_size = __lh_parse_page_size(page_size_str);
+
+       cnt = __lh_hpool_sizes(pools, MAX_POOLS);
+       if (cnt < 0) {
+               ERROR("unable to obtain pools list");
+               exit(EXIT_FAILURE);
+       }
+       for (pos = 0; cnt--; pos++) {
+               if (pools[pos].pagesize == page_size)
+                       break;
+       }
+       if (cnt < 0) {
+               ERROR("%s: unknown page size\n", page_size_str);
+               exit(EXIT_FAILURE);
+       }
+
+       min = pools[pos].minimum;
+       max = pools[pos].maximum;
+
+       if (counter == POOL_MIN) {
+               min = value_adjust(adjust_str, min);
+               if (min > max)
+                       max = min;
+       } else {
+               max = value_adjust(adjust_str, max);
+               if (max < min)
+                       min = max;
+       }
+
+       DEBUG("%ld, %ld -> %ld, %ld\n", pools[pos].minimum, pools[pos].maximum,
+               min, max);
+       
+       if ((pools[pos].maximum - pools[pos].minimum) < (max - min)) {
+               DEBUG("setting HUGEPAGES_OC to %ld\n", (max - min));
+               set_huge_page_counter(page_size, HUGEPAGES_OC, (max - min));
+       }
+       if (pools[pos].minimum != min) {
+               DEBUG("setting HUGEPAGES_TOTAL to %ld\n", min);
+               set_huge_page_counter(page_size, HUGEPAGES_TOTAL, min);
+       }
+       /*
+        * HUGEPAGES_TOTAL is not guarenteed to check to exactly the figure
+        * requested should there be insufficient pages.  Check the new
+        * value and adjust HUGEPAGES_OC accordingly.
+        */
+       __lh_get_pool_size(page_size, &pools[pos]);
+       if (pools[pos].minimum != min) {
+               ERROR("failed to set pool minimum to %ld became %ld\n",
+                       min, pools[pos].minimum);
+               min = pools[pos].minimum;
+       }
+       if (pools[pos].maximum != max) {
+               DEBUG("setting HUGEPAGES_OC to %ld\n", (max - min));
+               set_huge_page_counter(page_size, HUGEPAGES_OC, (max - min));
+       }
+}
+
 int main(int argc, char** argv)
 {
        char opts[] = "+h";
@@ -98,6 +222,8 @@ int main(int argc, char** argv)
                {"help",       no_argument, NULL, 'h'},
 
                {"pool-list", no_argument, NULL, LONG_POOL_LIST},
+               {"pool-pages-min", required_argument, NULL, LONG_POOL_MIN_ADJ},
+               {"pool-pages-max", required_argument, NULL, LONG_POOL_MAX_ADJ},
 
                {0},
        };
@@ -122,6 +248,14 @@ int main(int argc, char** argv)
                        pool_list();
                        break;
 
+               case LONG_POOL_MIN_ADJ:
+                       pool_adjust(optarg, POOL_MIN);
+                       break;
+
+               case LONG_POOL_MAX_ADJ:
+                       pool_adjust(optarg, POOL_MAX);
+                       break;
+
                default:
                        WARNING("unparsed option %08x\n", ret);
                        ret = -1;
diff --git a/hugeutils.c b/hugeutils.c
index 5209f55..3c78788 100644
--- a/hugeutils.c
+++ b/hugeutils.c
@@ -445,7 +445,7 @@ void __lh_setup_mounts(void)
                debug_show_page_sizes();
 }
 
-static int get_pool_size(long size, struct hpage_pool *pool)
+int __lh_get_pool_size(long size, struct hpage_pool *pool)
 {
        long nr_over = 0;
        long nr_used = 0;
@@ -503,7 +503,7 @@ int __lh_hpool_sizes(struct hpage_pool *pools, int pcnt)
        default_size = size_to_smaller_unit(file_read_ulong(MEMINFO,
                                                        "Hugepagesize:"));
        if (default_size >= 0 && which < pcnt)
-               if (get_pool_size(default_size, &pools[which])) {
+               if (__lh_get_pool_size(default_size, &pools[which])) {
                        pools[which].is_default = 1;
                        which++;
                }
@@ -523,7 +523,7 @@ int __lh_hpool_sizes(struct hpage_pool *pools, int pcnt)
                        if (size < 0 || size == default_size)
                                continue;
 
-                       if (get_pool_size(size, &pools[which]))
+                       if (__lh_get_pool_size(size, &pools[which]))
                                which++;
                }
                closedir(dir);
@@ -727,6 +727,7 @@ int set_nr_hugepages(long pagesize, unsigned long val)
 
 int set_nr_overcommit_hugepages(long pagesize, unsigned long val)
 {
+       DEBUG("setting HUGEPAGES_OC to %ld\n", val);
        return set_huge_page_counter(pagesize, HUGEPAGES_OC, val);
 }
 
diff --git a/libhugetlbfs_internal.h b/libhugetlbfs_internal.h
index 5c1e788..e07787f 100644
--- a/libhugetlbfs_internal.h
+++ b/libhugetlbfs_internal.h
@@ -98,6 +98,7 @@ struct hpage_pool {
 };
 
 extern int __lh_hpool_sizes(struct hpage_pool *, int);
+extern int __lh_get_pool_size(long, struct hpage_pool *);
 
 /* Arch-specific callbacks */
 extern int direct_syscall(int sysnum, ...);
-- 
1.6.0.1.451.gc8d31


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