From fa38c431b0fc5ecdc4af68357d10d7398abd7220 Mon Sep 17 00:00:00 2001
From: "Mark A. Grondona" <mgrondona@llnl.gov>
Date: Sat, 1 Oct 2011 15:03:51 -0700
Subject: [PATCH] cgroups: Allow percent values in cgroup.conf to be floating
 point

The use of whole percent values for cgroup.conf parameters such
as AllowedRAMSpace, MaxRAMPercent, AllowedSwapSpace and MaxSwapPercent
may be too coarse grained on systems with large amounts of memory.
(e.g. 1% of 64G is over 650MB).

This patch allows these percentage values to be arbitrary floating
point numbers to allow finer grained tuning of these limits and
parameters.
---
 src/common/xcgroup_read_config.c             | 74 ++++++++++++++------
 src/common/xcgroup_read_config.h             | 10 +--
 src/plugins/task/cgroup/task_cgroup_memory.c |  6 +-
 3 files changed, 60 insertions(+), 30 deletions(-)

diff --git a/src/common/xcgroup_read_config.c b/src/common/xcgroup_read_config.c
index 41386c93ad7..9a45dd40610 100644
--- a/src/common/xcgroup_read_config.c
+++ b/src/common/xcgroup_read_config.c
@@ -93,6 +93,34 @@ static void _clear_slurm_cgroup_conf(slurm_cgroup_conf_t *slurm_cgroup_conf)
 	}
 }
 
+/*
+ *   Parse a floating point value in s and return in val
+ *    Return -1 on error and leave *val unchanged.
+ */
+static int str_to_float (char *s, float *val)
+{
+	float f;
+	char *p;
+
+	errno = 0;
+	f = strtof (s, &p);
+
+	if ((*p != '\0') || (errno != 0))
+		return (-1);
+
+	*val = f;
+	return (0);
+}
+
+static void conf_get_float (s_p_hashtbl_t *t, char *name, float *fp)
+{
+	char *str;
+	if (!s_p_get_string(&str, name, t))
+		return;
+	if (str_to_float (str, fp) < 0)
+		fatal ("cgroup.conf: Invalid value '%s' for %s", str, name);
+}
+
 /*
  * read_slurm_cgroup_conf - load the Slurm cgroup configuration from the
  *	cgroup.conf file.
@@ -108,14 +136,14 @@ extern int read_slurm_cgroup_conf(slurm_cgroup_conf_t *slurm_cgroup_conf)
 		{"ConstrainCores", S_P_BOOLEAN},
 		{"TaskAffinity", S_P_BOOLEAN},
 		{"ConstrainRAMSpace", S_P_BOOLEAN},
-		{"AllowedRAMSpace", S_P_UINT32},
-		{"MaxRAMPercent", S_P_UINT32},
+		{"AllowedRAMSpace", S_P_STRING},
+		{"MaxRAMPercent", S_P_STRING},
 		{"ConstrainSwapSpace", S_P_BOOLEAN},
-		{"AllowedSwapSpace", S_P_UINT32},
-		{"MaxSwapPercent", S_P_UINT32},
+		{"AllowedSwapSpace", S_P_STRING},
+		{"MaxSwapPercent", S_P_STRING},
 		{"ConstrainCores", S_P_BOOLEAN},
 		{"MemoryLimitEnforcement", S_P_BOOLEAN},
-		{"MemoryLimitThreshold", S_P_UINT32},
+		{"MemoryLimitThreshold", S_P_STRING},
 		{"ConstrainDevices", S_P_BOOLEAN},
 		{"AllowedDevicesFile", S_P_STRING},
 		{NULL} };
@@ -173,33 +201,35 @@ extern int read_slurm_cgroup_conf(slurm_cgroup_conf_t *slurm_cgroup_conf)
 		if (!s_p_get_boolean(&slurm_cgroup_conf->constrain_ram_space,
 				     "ConstrainRAMSpace", tbl))
 			slurm_cgroup_conf->constrain_ram_space = false;
-		if (!s_p_get_uint32(&slurm_cgroup_conf->allowed_ram_space,
-				    "AllowedRAMSpace", tbl))
-			slurm_cgroup_conf->allowed_ram_space = 100;
+
+		conf_get_float (tbl,
+				"AllowedRAMSpace",
+				&slurm_cgroup_conf->allowed_ram_space);
+
+		conf_get_float (tbl,
+				"MaxRAMPercent",
+				&slurm_cgroup_conf->max_ram_percent);
+
 		if (!s_p_get_boolean(&slurm_cgroup_conf->constrain_swap_space,
 				     "ConstrainSwapSpace", tbl))
 			slurm_cgroup_conf->constrain_swap_space = false;
-		if (!s_p_get_uint32(&slurm_cgroup_conf->allowed_swap_space,
-				    "AllowedSwapSpace", tbl))
-			slurm_cgroup_conf->allowed_swap_space = 0;
 
-		if (s_p_get_uint32(&slurm_cgroup_conf->max_ram_percent,
-				    "MaxRAMPercent", tbl)
-		   && (slurm_cgroup_conf->max_ram_percent > 100))
-			fatal ("%s: Invalid MaxRAMPercent\n", conf_path);
+		conf_get_float (tbl,
+				"AllowedSwapSpace",
+				&slurm_cgroup_conf->allowed_swap_space);
 
-		if (s_p_get_uint32(&slurm_cgroup_conf->max_swap_percent,
-				    "MaxSwapPercent", tbl)
-		   && (slurm_cgroup_conf->max_swap_percent > 100))
-			fatal ("%s: Invalid MaxSwapPercent\n", conf_path);
+		conf_get_float (tbl,
+				"MaxSwapPercent",
+				&slurm_cgroup_conf->max_swap_percent);
 
 		/* Memory limits */
 		if (!s_p_get_boolean(&slurm_cgroup_conf->memlimit_enforcement,
 				     "MemoryLimitEnforcement", tbl))
 			slurm_cgroup_conf->memlimit_enforcement = false;
-		if (!s_p_get_uint32(&slurm_cgroup_conf->memlimit_threshold,
-				    "MemoryLimitThreshold", tbl))
-			slurm_cgroup_conf->memlimit_threshold = 0;
+
+		conf_get_float (tbl,
+				"MemoryLimitThreshold",
+				&slurm_cgroup_conf->memlimit_threshold);
 
 		/* Devices constraint related conf items */
 		if (!s_p_get_boolean(&slurm_cgroup_conf->constrain_devices,
diff --git a/src/common/xcgroup_read_config.h b/src/common/xcgroup_read_config.h
index 032129b11e5..afdd4f05419 100644
--- a/src/common/xcgroup_read_config.h
+++ b/src/common/xcgroup_read_config.h
@@ -63,15 +63,15 @@ typedef struct slurm_cgroup_conf {
 	bool      task_affinity;
 
 	bool      constrain_ram_space;
-	uint32_t  allowed_ram_space;
-	uint32_t  max_ram_percent;       /* Upper bound on memory as % of RAM*/
+	float     allowed_ram_space;
+	float     max_ram_percent;       /* Upper bound on memory as % of RAM*/
 
 	bool      constrain_swap_space;
-	uint32_t  allowed_swap_space;
-	uint32_t  max_swap_percent;      /* Upper bound on swap as % of RAM  */
+	float     allowed_swap_space;
+	float     max_swap_percent;      /* Upper bound on swap as % of RAM  */
 
 	bool      memlimit_enforcement;
-	uint32_t  memlimit_threshold;
+	float     memlimit_threshold;
 
 	bool      constrain_devices;
 	char *    allowed_devices_file;
diff --git a/src/plugins/task/cgroup/task_cgroup_memory.c b/src/plugins/task/cgroup/task_cgroup_memory.c
index 1db40e636c9..bb5de6e60a2 100644
--- a/src/plugins/task/cgroup/task_cgroup_memory.c
+++ b/src/plugins/task/cgroup/task_cgroup_memory.c
@@ -66,14 +66,14 @@ static xcgroup_t user_memory_cg;
 static xcgroup_t job_memory_cg;
 static xcgroup_t step_memory_cg;
 
-static int allowed_ram_space;
-static int allowed_swap_space;
+static float allowed_ram_space;   /* Allowed RAM in percent       */
+static float allowed_swap_space;  /* Allowed Swap percent         */
 
 static uint64_t max_ram;        /* Upper bound for memory.limit_in_bytes  */
 static uint64_t max_swap;       /* Upper bound for swap                   */
 static uint64_t totalram;       /* Total real memory available on node    */
 
-static uint64_t percent_in_bytes (uint64_t mb, uint32_t percent)
+static uint64_t percent_in_bytes (uint64_t mb, float percent)
 {
 	return ((mb * 1024 * 1024) * (percent / 100.0));
 }
-- 
GitLab