[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250825145719.29455-7-linyongting@bytedance.com>
Date: Mon, 25 Aug 2025 22:57:09 +0800
From: Yongting Lin <linyongting@...edance.com>
To: anthony.yznaga@...cle.com,
khalid@...nel.org,
shuah@...nel.org,
linyongting@...edance.com
Cc: linux-kernel@...r.kernel.org,
linux-kselftest@...r.kernel.org,
akpm@...ux-foundation.org,
linux-mm@...ck.org
Subject: [PATCH 6/8] mshare: selftests: Add some helper functions for reading and controlling cgroup
Before verify some complicated memory functionalities such as swap memory
and THP, we need add some helper functions to controlling the cgroup
(specifically, memcg).
These helper functions consist:
Create and destroy individual cgroup for test cases
attach and dettach the test process to specified cgroup
Read swap size and thp size from testing cgroup
Signed-off-by: Yongting Lin <linyongting@...edance.com>
---
tools/testing/selftests/mshare/util.c | 128 ++++++++++++++++++++++++++
1 file changed, 128 insertions(+)
diff --git a/tools/testing/selftests/mshare/util.c b/tools/testing/selftests/mshare/util.c
index 75f6ff25aa2c..94fddaea2c56 100644
--- a/tools/testing/selftests/mshare/util.c
+++ b/tools/testing/selftests/mshare/util.c
@@ -121,3 +121,131 @@ int mshare_ioctl_munmap(int fd, size_t size)
return ioctl(fd, MSHAREFS_UNMAP, &munmap);
}
+
+/*
+ * Helper functions for cgroup
+ */
+
+#define CGROUP_BASE "/sys/fs/cgroup/"
+#define CGROUP_TEST "mshare-test-XXXXXX"
+
+bool is_cgroup_v2;
+
+__attribute__((constructor))
+void get_cgroup_version(void)
+{
+ if (access(CGROUP_BASE "cgroup.controllers", F_OK) == 0)
+ is_cgroup_v2 = true;
+}
+
+int create_mshare_test_cgroup(char *cgroup, size_t len)
+{
+ if (is_cgroup_v2)
+ snprintf(cgroup, len, "%s/%s", CGROUP_BASE, CGROUP_TEST);
+ else
+ snprintf(cgroup, len, "%s/memory/%s", CGROUP_BASE, CGROUP_TEST);
+
+ char *path = mkdtemp(cgroup);
+
+ if (!path) {
+ perror("mkdtemp");
+ return -1;
+ }
+
+ return 0;
+}
+
+int remove_cgroup(char *cgroup)
+{
+ return rmdir(cgroup);
+}
+
+int write_data_to_cgroup(char *cgroup, char *file, char *data)
+{
+ char filename[128];
+ int fd;
+ int ret;
+
+ snprintf(filename, sizeof(filename), "%s/%s", cgroup, file);
+ fd = open(filename, O_RDWR);
+
+ if (fd == -1)
+ return -1;
+
+ ret = write(fd, data, strlen(data));
+ close(fd);
+
+ return ret;
+}
+
+int attach_to_cgroup(char *cgroup)
+{
+ char pid_str[32];
+
+ snprintf(pid_str, sizeof(pid_str), "%d", getpid());
+ return write_data_to_cgroup(cgroup, "cgroup.procs", pid_str);
+}
+
+/*
+ * Simplely, just move the pid to root memcg as avoid
+ * complicated consideration.
+ */
+int dettach_from_cgroup(char *cgroup)
+{
+ char pid_str[32];
+ char *root_memcg;
+
+ if (is_cgroup_v2)
+ root_memcg = CGROUP_BASE;
+ else
+ root_memcg = CGROUP_BASE "memory";
+
+ snprintf(pid_str, sizeof(pid_str), "%d", getpid());
+ return write_data_to_cgroup(root_memcg, "cgroup.procs", pid_str);
+}
+
+size_t read_data_from_cgroup(char *cgroup, char *file, char *field)
+{
+ char filename[128];
+ FILE *fp;
+ char line[80];
+ size_t size = -1;
+
+ snprintf(filename, sizeof(filename), "%s/%s", cgroup, file);
+ fp = fopen(filename, "r");
+ if (!fp) {
+ perror("fopen");
+ return -1;
+ }
+
+ while (fgets(line, sizeof(line), fp)) {
+ if (!strncmp(line, field, strlen(field))) {
+ char *value = line + strlen(field) + 1;
+
+ size = atol(value);
+ break;
+ }
+ }
+
+ fclose(fp);
+
+ return size;
+}
+
+size_t read_swap_from_cgroup(char *cgroup)
+{
+ if (is_cgroup_v2)
+ return read_data_from_cgroup(cgroup, "memory.stat", "pswpout");
+ else
+ return read_data_from_cgroup(cgroup, "memory.stat", "swap");
+}
+
+size_t read_huge_from_cgroup(char *cgroup)
+{
+ if (is_cgroup_v2)
+ return read_data_from_cgroup(cgroup, "memory.stat", "file_thp")
+ + read_data_from_cgroup(cgroup, "memory.stat", "anon_thp")
+ + read_data_from_cgroup(cgroup, "memory.stat", "shmem_thp");
+ else
+ return read_data_from_cgroup(cgroup, "memory.stat", "rss_huge");
+}
--
2.20.1
Powered by blists - more mailing lists