[LTP] [PATCH v3 04/16] API/cgroup: Implement tst_cg_load_config

Luke Nowakowski-Krijger luke.nowakowskikrijger@canonical.com
Sat Mar 5 00:18:14 CET 2022


Implement tst_cg_load_config which consumes the state given by
tst_cg_print_config to update the internal test state to reflect
the given config.

This allows for programs using the cgroup C API to load and reload
state, allowing functionality such as calling tst_cg_require and
tst_cg_cleanup to function properly between programs or between
invocations of a binary using the C API.

Signed-off-by: Luke Nowakowski-Krijger <luke.nowakowskikrijger@canonical.com>
---
v2: Add root null check in parse_root_config.
    Remove checking for ltp_drain_dir key from config as it was
    redundant.
    Remove unsued variable in parse_ctrl_config.
    Cleanup some compiler warnings.
v3: Rewrite to consume each line of the config with a scanf to make
    the parsing much simpler while using new config variables.

 include/tst_cgroup.h |  7 +++++
 lib/tst_cgroup.c     | 62 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/include/tst_cgroup.h b/include/tst_cgroup.h
index 87e55f4df..9bad0d366 100644
--- a/include/tst_cgroup.h
+++ b/include/tst_cgroup.h
@@ -121,6 +121,13 @@ void tst_cg_scan(void);
  */
 void tst_cg_print_config(void);
 
+/* Load the config printed out by tst_cg_print_config and configure the internal
+ * libary state to match the config. Used to allow tst_cg_cleanup to properly
+ * cleanup mounts and directories created by tst_cg_require between program
+ * invocations.
+ */
+void tst_cg_load_config(const char *const config);
+
 /* Ensure the specified controller is available in the test's default
  * CGroup, mounting/enabling it if necessary. Usually this is not
  * necesary use tst_test.needs_cgroup_controllers instead.
diff --git a/lib/tst_cgroup.c b/lib/tst_cgroup.c
index 8f95064b3..90d91d94e 100644
--- a/lib/tst_cgroup.c
+++ b/lib/tst_cgroup.c
@@ -366,6 +366,68 @@ static struct cgroup_root *cgroup_find_root(const char *const mnt_path)
 	return NULL;
 }
 
+static void parse_config(const char *const config_entry)
+{
+	const char ctrl_name[32], mnt_path[PATH_MAX], test_dir_name[NAME_MAX + 1];
+	int ver, we_require_it, we_mounted_it, ltp_dir_we_created_it;
+	struct cgroup_root *root;
+	struct cgroup_ctrl *ctrl;
+
+	sscanf(config_entry, CONFIG_FORMAT,
+		ctrl_name, &ver, &we_require_it, mnt_path, &we_mounted_it,
+		&ltp_dir_we_created_it, test_dir_name);
+
+	if (!(ctrl = cgroup_find_ctrl(ctrl_name)))
+		tst_brk(TBROK, "Could not find ctrl from config. Ctrls changing between calls?");
+
+	ctrl->we_require_it = we_require_it;
+
+	if (!(root = cgroup_find_root(mnt_path)))
+		tst_brk(TBROK, "Could not find root from config. Config possibly malformed?");
+
+	if (we_mounted_it)
+		root->we_mounted_it = 1;
+
+	if (!root->ltp_dir.dir_name) {
+		cgroup_dir_mk(&root->mnt_dir, cgroup_ltp_dir, &root->ltp_dir);
+		cgroup_dir_mk(&root->ltp_dir, cgroup_ltp_drain_dir, &root->drain_dir);
+		if (ltp_dir_we_created_it) {
+			root->ltp_dir.we_created_it = 1;
+			root->drain_dir.we_created_it = 1;
+		}
+	}
+
+	if (!root->test_dir.dir_name && strcmp(test_dir_name, "NULL")) {
+		strncpy(cgroup_test_dir, test_dir_name, NAME_MAX);
+		cgroup_dir_mk(&root->ltp_dir, cgroup_test_dir, &root->test_dir);
+		root->test_dir.we_created_it = 1;
+	}
+}
+
+/* Load the test state config provided by tst_cg_print_config
+ *
+ * This will reload some internal tst_cgroup state given by the config
+ * that might otherwise have been lost between calls or between different
+ * processes. In particular this is used by testcases/lib/tst_cgctl to
+ * provide access to this C api to shell scripts.
+ *
+ * The config keeps track of the minimal state needed for tst_cg_cleanup
+ * to cleanup mounts and directories created by tst_cg_require.
+ */
+void tst_cg_load_config(const char *const config)
+{
+	char temp_config[BUFSIZ];
+	char *line;
+
+	if (strlen(config) >= BUFSIZ)
+		tst_brk(TBROK, "Config has exceeded buffer size?");
+	strncpy(temp_config, config, BUFSIZ);
+
+	line = strtok(temp_config, "\n");
+	/* Make sure to consume the header. */
+	for (line = strtok(NULL, "\n"); line; line = strtok(NULL, "\n"))
+		parse_config(line);
+}
 
 /* Determine if a mounted cgroup hierarchy is unique and record it if so.
  *
-- 
2.32.0



More information about the ltp mailing list