All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH] New core test of cgroups and extended attributes
@ 2013-05-22 10:24 Alexey Kodanev
  2013-05-22 14:26 ` chrubis
  0 siblings, 1 reply; 15+ messages in thread
From: Alexey Kodanev @ 2013-05-22 10:24 UTC (permalink / raw)
  To: ltp-list; +Cc: vasily.isaenko, Alexey Kodanev

Support of extended attributes in cgroups was added in Linux 3.7.

Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
---
 runtest/controllers                                |    1 +
 .../kernel/controllers/cgroup_xattr/.gitignore     |    1 +
 testcases/kernel/controllers/cgroup_xattr/Makefile |   19 +
 testcases/kernel/controllers/cgroup_xattr/README   |   25 ++
 .../kernel/controllers/cgroup_xattr/cgroup_xattr.c |  344 ++++++++++++++++++++
 5 files changed, 390 insertions(+), 0 deletions(-)
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/.gitignore
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/Makefile
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/README
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c

diff --git a/runtest/controllers b/runtest/controllers
index b78d828..94fc185 100644
--- a/runtest/controllers
+++ b/runtest/controllers
@@ -12,3 +12,4 @@ memcg_stress		memcg_stress_test.sh
 memcg_control		PAGESIZE=$(mem_process -p);memcg_control_test.sh $PAGESIZE $PAGESIZE $((PAGESIZE * 2))
 cgroup_fj	run_cgroup_test_fj.sh
 controllers	test_controllers.sh
+cgroup_xattr	cgroup_xattr
diff --git a/testcases/kernel/controllers/cgroup_xattr/.gitignore b/testcases/kernel/controllers/cgroup_xattr/.gitignore
new file mode 100644
index 0000000..3664cc9
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/.gitignore
@@ -0,0 +1 @@
+/cgroup_xattr
diff --git a/testcases/kernel/controllers/cgroup_xattr/Makefile b/testcases/kernel/controllers/cgroup_xattr/Makefile
new file mode 100644
index 0000000..cd49588
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/Makefile
@@ -0,0 +1,19 @@
+# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/controllers/cgroup_xattr/README b/testcases/kernel/controllers/cgroup_xattr/README
new file mode 100644
index 0000000..9cc5176
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/README
@@ -0,0 +1,25 @@
+TEST SUITE:
+
+The directory cgroup_xattr contains the tests related to extended
+attributes in cgroup filesystem.
+
+WARNING:
+
+This test can cause a kernel panic due to a bug in kernels prior to 3.8.
+It was fixed by kernel upstream commit
+712317ad97f41e738e1a19aa0a6392a78a84094e:
+
+"We should store file xattrs in struct cfent instead of struct cftype,
+because cftype is a type while cfent is object instance of cftype."
+
+TESTS AIM:
+
+The aim of the tests is to check the extended attributes in cgroup
+filesystem. This feature was added in Linux 3.7 to allow attaching runtime
+meta information to cgroups and everything they model (services, apps, vms)
+and can easily be shared among applications.
+
+Test creates all available subsystems (cpu, cpuset, memory, ...) in the
+cgroup directory and in one more created hierarchy. Then sets extended
+attributes to all files in cgroup fs and subsequently reads the file's
+extended attributes back, checking values during the process.
diff --git a/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c
new file mode 100644
index 0000000..4fa2768
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author:
+ * Alexey Kodanev <alexey.kodanev@oracle.com>
+ *
+ * Test checks following preconditions:
+ * since Linux kernel 3.7 it is possible to set extended attributes
+ * to cgroup files.
+ */
+
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "test.h"
+#include "usctest.h"
+#include "safe_macros.h"
+
+char *TCID = "cgroup_xattr";
+
+static const char cgrp_point[]	= "cgroup";
+static const char cgrp_name[]	= "cgrp_test";
+static const char subdir_name[]	= "test";
+
+struct tst_key {
+	const char *name;
+	int good;
+};
+
+/* only security.* & trusted.* are valid key names */
+static const struct tst_key tkeys[] = {
+	{ .name = "trusted.test",	.good = 1,	},
+	{ .name = "security.",		.good = 1,	},
+	{ .name = "user.",		.good = 0,	},
+	{ .name = "system.",		.good = 0,	},
+};
+
+#define DEFAULT_VALUE_SIZE	8
+
+/* struct to store key's value */
+struct tst_val {
+	char *buf;
+	size_t size;
+};
+static struct tst_val val;
+
+/* it fills value's buffer */
+static char id;
+
+/* cleanup flags */
+static int cgrp_mounted;
+static int subdir_created;
+
+/*
+ * When test breaks, all open dirs should be closed
+ * otherwise umount won't succeed
+ */
+#define MAX_OPEN_DIR		32
+static DIR *odir[MAX_OPEN_DIR];
+static int odir_num;
+
+/* test options */
+static char *narg;
+static int nflag;
+static int skip_cleanup;
+static int verbose;
+static const option_t options[] = {
+	{"n:", &nflag, &narg},
+	{"s", &skip_cleanup, NULL},
+	{"v", &verbose, NULL},
+	{NULL, NULL, NULL}
+};
+
+static void help(void);
+static void setup(int argc, char *argv[]);
+static void test_run(void);
+static void cleanup(void);
+
+static int set_xattrs(const char *file);
+static int get_xattrs(const char *file);
+/*
+ * set or get xattr recursively
+ *
+ * @path: start directory
+ * @xattr_operation: can be set_xattrs() or get_xattrs()
+ */
+static int cgrp_files_walking(const char *path,
+	int (*xattr_operation)(const char *));
+
+int main(int argc, char *argv[])
+{
+	setup(argc, argv);
+
+	test_run();
+
+	cleanup();
+
+	tst_exit();
+}
+
+static void help(void)
+{
+	printf("  -n x    Write x bytes to xattr value, default is %d\n",
+		DEFAULT_VALUE_SIZE);
+	printf("  -s      Skip cleanup\n");
+	printf("  -v      Verbose\n");
+}
+
+void setup(int argc, char *argv[])
+{
+	char *msg;
+	msg = parse_opts(argc, argv, options, help);
+	if (msg != NULL)
+		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+
+	tst_require_root(NULL);
+
+	if (access("/proc/cgroups", F_OK) == -1)
+		tst_brkm(TCONF, NULL, "Kernel doesn't support for cgroups");
+
+	if (tst_kvercmp(3, 7, 0) < 0) {
+		tst_brkm(TCONF, NULL,
+			"Test must be run with kernel 3.7 or newer");
+	}
+
+	int value_size = DEFAULT_VALUE_SIZE;
+	if (nflag) {
+		if (sscanf(narg, "%i", &value_size) != 1)
+			tst_brkm(TBROK, NULL, "-n option arg is not a number");
+		if (value_size <= 0)
+			tst_brkm(TBROK, NULL, "-n option arg is less than 1");
+	}
+
+	/* initialize test value */
+	val.size = value_size;
+	val.buf = SAFE_MALLOC(NULL, value_size);
+
+	tst_sig(FORK, DEF_HANDLER, cleanup);
+
+	tst_tmpdir();
+
+	SAFE_MKDIR(cleanup, cgrp_point, 0755);
+
+	/* mount all available subsystems (cpu, cpuset, memory, ...) */
+	if (mount(cgrp_name, cgrp_point, "cgroup", 0, "xattr") == -1)
+		tst_brkm(TBROK, cleanup, "Can't mount: %s", cgrp_point);
+	cgrp_mounted = 1;
+
+	/* create new hierarchy */
+	SAFE_CHDIR(cleanup, cgrp_point);
+	SAFE_MKDIR(cleanup, subdir_name, 0755);
+	subdir_created = 1;
+}
+
+static void test_run(void)
+{
+	/* set xattr to each file in cgroup fs */
+	int set_res = cgrp_files_walking(".", set_xattrs);
+	/* reset value */
+	id = 0;
+	/* get & check xattr */
+	int get_res = cgrp_files_walking(".", get_xattrs);
+
+	/* final results */
+	tst_resm(TINFO, "All test-cases have been completed, summary:");
+	tst_resm(TINFO, "Set tests result: %s", (set_res) ? "FAIL" : "PASS");
+	tst_resm(TINFO, "Get tests result: %s", (get_res) ? "FAIL" : "PASS");
+}
+
+static void cleanup(void)
+{
+	if (val.buf != NULL)
+		free(val.buf);
+
+	if (skip_cleanup)
+		return;
+
+	/*
+	 * Kernels 3.7 can crash while unmounting cgroups with xattr,
+	 * call tst_flush() to make sure all buffered data written
+	 * before it happens
+	 */
+	tst_flush();
+
+	int i;
+	for (i = 0; i < odir_num; ++i) {
+		if (closedir(odir[i]) == -1)
+			tst_brkm(TBROK, NULL, "Failed to close dir\n");
+	}
+
+	char *cwd = get_tst_tmpdir();
+	SAFE_CHDIR(NULL, cwd);
+	free(cwd);
+
+	if (subdir_created) {
+		SAFE_CHDIR(NULL, cgrp_point);
+		if (rmdir(subdir_name) == -1)
+			tst_brkm(TBROK | TERRNO, NULL, "Can't remove dir");
+		SAFE_CHDIR(NULL, "..");
+	}
+
+	if (cgrp_mounted) {
+		if (umount(cgrp_point) == -1) {
+			tst_brkm(TBROK | TERRNO, NULL,
+				"Can't unmount: %s", cgrp_point);
+		}
+	}
+
+	tst_rmdir();
+	TEST_CLEANUP;
+}
+
+static int set_xattrs(const char *file)
+{
+	int i, err, fail, res;
+	res = 0;
+	for (i = 0; i < ARRAY_SIZE(tkeys); ++i) {
+		err = setxattr(file, tkeys[i].name,
+			(const void *)val.buf, val.size, 0) == -1;
+
+		fail = err && tkeys[i].good;
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS,
+			"Expect: %s set xattr key '%s' to file '%s'",
+			(tkeys[i].good) ? "can" : "can't",
+			tkeys[i].name, file);
+
+		if (verbose && tkeys[i].good)
+			tst_resm_hexd(TINFO, val.buf, val.size, "value:");
+	}
+	return res;
+}
+
+static int get_xattrs(const char *file)
+{
+	int i, fail, res;
+	res = 0;
+	for (i = 0; i < ARRAY_SIZE(tkeys); ++i) {
+		/* get value size */
+		ssize_t size = getxattr(file, tkeys[i].name, NULL, 0);
+		fail = (size == -1 && tkeys[i].good);
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS,
+			"Expect: %s read xattr %s of file '%s'",
+			(size == -1) ? "can't" : "can",
+			tkeys[i].name, file);
+
+		if (fail || size == -1)
+			continue;
+
+		/* get xattr value */
+		char xval[size];
+		if (getxattr(file, tkeys[i].name, (void *)xval, size) == -1) {
+			tst_brkm(TBROK, cleanup,
+				"Can't get buffer of key %s",
+				tkeys[i].name);
+		}
+		fail = val.size != size ||
+			strncmp(val.buf, xval, val.size) != 0;
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS, "Expect: values equal");
+
+		if (verbose && fail) {
+			tst_resm_hexd(TINFO, xval, size,
+				"Read  xattr  value:");
+			tst_resm_hexd(TINFO, val.buf, val.size,
+				"Expect xattr value:");
+		}
+	}
+	return res;
+}
+
+static int cgrp_files_walking(const char *path,
+	int (*xattr_operation)(const char *))
+{
+	int res = 0;
+	struct dirent *entry;
+	DIR *dir = opendir(path);
+
+	odir[odir_num] = dir;
+	if (++odir_num >= MAX_OPEN_DIR) {
+		tst_brkm(TBROK, cleanup,
+			"Unexpected num of open dirs, max: %d", MAX_OPEN_DIR);
+	}
+
+	SAFE_CHDIR(cleanup, path);
+
+	tst_resm(TINFO, "In dir %s", path);
+
+	errno = 0;
+	while ((entry = readdir(dir)) != NULL) {
+		const char *file = entry->d_name;
+		/* skip current and up directories */
+		if (!strcmp(file, "..") || !strcmp(file, "."))
+			continue;
+		struct stat stat_buf;
+		TEST(lstat(file, &stat_buf));
+		if (TEST_RETURN != -1 && S_ISDIR(stat_buf.st_mode)) {
+			/* proceed to subdir */
+			res |= cgrp_files_walking(file, xattr_operation);
+			tst_resm(TINFO, "In dir %s", path);
+		}
+		memset(val.buf, id++, val.size);
+		res |= xattr_operation(file);
+		errno = 0;
+	}
+	if (errno && !entry) {
+		tst_brkm(TWARN | TERRNO, cleanup,
+			"Error while reading dir '%s'", path);
+	}
+	if (closedir(dir) == -1)
+		tst_brkm(TWARN, cleanup, "Failed to close dir '%s'", path);
+	else
+		odir[--odir_num] = NULL;
+
+	if (strcmp(path, "."))
+		SAFE_CHDIR(cleanup, "..");
+	return res;
+}
-- 
1.7.1


------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service 
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_may
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

^ permalink raw reply related	[flat|nested] 15+ messages in thread
* [LTP] [PATCH] New core test of cgroups and extended attributes
@ 2013-05-29 10:28 Alexey Kodanev
  2013-05-30 18:55 ` chrubis
  0 siblings, 1 reply; 15+ messages in thread
From: Alexey Kodanev @ 2013-05-29 10:28 UTC (permalink / raw)
  To: ltp-list; +Cc: vasily.isaenko, Alexey Kodanev

Support of extended attributes in cgroups was added in Linux 3.7.

Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
---
 runtest/controllers                                |    1 +
 .../kernel/controllers/cgroup_xattr/.gitignore     |    1 +
 testcases/kernel/controllers/cgroup_xattr/Makefile |   19 +
 testcases/kernel/controllers/cgroup_xattr/README   |   25 ++
 .../kernel/controllers/cgroup_xattr/cgroup_xattr.c |  435 ++++++++++++++++++++
 5 files changed, 481 insertions(+), 0 deletions(-)
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/.gitignore
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/Makefile
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/README
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c

diff --git a/runtest/controllers b/runtest/controllers
index b78d828..94fc185 100644
--- a/runtest/controllers
+++ b/runtest/controllers
@@ -12,3 +12,4 @@ memcg_stress		memcg_stress_test.sh
 memcg_control		PAGESIZE=$(mem_process -p);memcg_control_test.sh $PAGESIZE $PAGESIZE $((PAGESIZE * 2))
 cgroup_fj	run_cgroup_test_fj.sh
 controllers	test_controllers.sh
+cgroup_xattr	cgroup_xattr
diff --git a/testcases/kernel/controllers/cgroup_xattr/.gitignore b/testcases/kernel/controllers/cgroup_xattr/.gitignore
new file mode 100644
index 0000000..3664cc9
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/.gitignore
@@ -0,0 +1 @@
+/cgroup_xattr
diff --git a/testcases/kernel/controllers/cgroup_xattr/Makefile b/testcases/kernel/controllers/cgroup_xattr/Makefile
new file mode 100644
index 0000000..cd49588
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/Makefile
@@ -0,0 +1,19 @@
+# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/controllers/cgroup_xattr/README b/testcases/kernel/controllers/cgroup_xattr/README
new file mode 100644
index 0000000..5aff0a8
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/README
@@ -0,0 +1,25 @@
+TEST SUITE:
+
+The directory cgroup_xattr contains the tests related to extended
+attributes in cgroup filesystem.
+
+WARNING:
+
+This test can cause a kernel panic due to a bug in kernels prior to 3.8.
+It was fixed by kernel upstream commit
+712317ad97f41e738e1a19aa0a6392a78a84094e:
+
+"We should store file xattrs in struct cfent instead of struct cftype,
+because cftype is a type while cfent is object instance of cftype."
+
+TESTS AIM:
+
+The aim of the tests is to check the extended attributes in cgroup
+filesystem. This feature was added in Linux 3.7 to allow attaching runtime
+meta information to cgroups and everything they model (services, apps, vms)
+and can easily be shared among applications.
+
+Test mounts as many subsystems as possible (cpu, cpuset, ...) in the
+cgroup tmp directory and creates one more hierarchy. Then sets extended
+attributes to all files in cgroup fs and subsequently reads the file's
+extended attributes back, checking values during the process.
diff --git a/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c
new file mode 100644
index 0000000..20473d4
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author:
+ * Alexey Kodanev <alexey.kodanev@oracle.com>
+ *
+ * Test checks following preconditions:
+ * since Linux kernel 3.7 it is possible to set extended attributes
+ * to cgroup files.
+ */
+
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "test.h"
+#include "usctest.h"
+#include "safe_macros.h"
+
+char *TCID = "cgroup_xattr";
+
+static const char subdir_name[]	= "test";
+
+#define MAX_SUBSYS		16
+#define MAX_OPTIONS_LEN		256
+#define MAX_DIR_NAME		64
+
+/* struct to store available mount options */
+struct cgrp_option {
+	char str[MAX_OPTIONS_LEN];
+	char dir[MAX_DIR_NAME];
+	int hier;
+	int mounted;
+	int subdir;
+};
+static struct cgrp_option cgrp_opt[MAX_SUBSYS];
+static int cgrp_opt_num;
+
+struct tst_key {
+	const char *name;
+	int good;
+};
+
+/* only security.* & trusted.* are valid key names */
+static const struct tst_key tkeys[] = {
+	{ .name = "trusted.test",	.good = 1,	},
+	{ .name = "security.",		.good = 1,	},
+	{ .name = "user.",		.good = 0,	},
+	{ .name = "system.",		.good = 0,	},
+};
+
+#define DEFAULT_VALUE_SIZE	8
+
+/* struct to store key's value */
+struct tst_val {
+	char *buf;
+	size_t size;
+};
+static struct tst_val val;
+
+/* it fills value's buffer */
+static char id;
+
+/*
+ * When test breaks, all open dirs should be closed
+ * otherwise umount won't succeed
+ */
+#define MAX_OPEN_DIR		32
+static DIR *odir[MAX_OPEN_DIR];
+static int odir_num;
+
+/* test options */
+static char *narg;
+static int nflag;
+static int skip_cleanup;
+static int verbose;
+static const option_t options[] = {
+	{"n:", &nflag, &narg},
+	{"s", &skip_cleanup, NULL},
+	{"v", &verbose, NULL},
+	{NULL, NULL, NULL}
+};
+
+static void help(void);
+static void setup(int argc, char *argv[]);
+static void test_run(void);
+static void cleanup(void);
+
+static int mount_cgroup(void);
+static int set_xattrs(const char *file);
+static int get_xattrs(const char *file);
+/*
+ * set or get xattr recursively
+ *
+ * @path: start directory
+ * @xattr_operation: can be set_xattrs() or get_xattrs()
+ */
+static int cgrp_files_walking(const char *path,
+	int (*xattr_operation)(const char *));
+
+int main(int argc, char *argv[])
+{
+	setup(argc, argv);
+
+	test_run();
+
+	cleanup();
+
+	tst_exit();
+}
+
+static void help(void)
+{
+	printf("  -n x    Write x bytes to xattr value, default is %d\n",
+		DEFAULT_VALUE_SIZE);
+	printf("  -s      Skip cleanup\n");
+	printf("  -v      Verbose\n");
+}
+
+void setup(int argc, char *argv[])
+{
+	char *msg;
+	msg = parse_opts(argc, argv, options, help);
+	if (msg != NULL)
+		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+
+	tst_require_root(NULL);
+
+	if (access("/proc/cgroups", F_OK) == -1)
+		tst_brkm(TCONF, NULL, "Kernel doesn't support cgroups");
+
+	if (tst_kvercmp(3, 7, 0) < 0) {
+		tst_brkm(TCONF, NULL,
+			"Test must be run with kernel 3.7 or newer");
+	}
+
+	int value_size = DEFAULT_VALUE_SIZE;
+	if (nflag) {
+		if (sscanf(narg, "%i", &value_size) != 1)
+			tst_brkm(TBROK, NULL, "-n option arg is not a number");
+		if (value_size <= 0)
+			tst_brkm(TBROK, NULL, "-n option arg is less than 1");
+	}
+
+	/* initialize test value */
+	val.size = value_size;
+	val.buf = SAFE_MALLOC(NULL, value_size);
+
+	tst_sig(FORK, DEF_HANDLER, cleanup);
+
+	tst_tmpdir();
+
+	if (!mount_cgroup())
+		tst_brkm(TCONF, cleanup, "Nothing  mounted");
+}
+
+static void test_run(void)
+{
+	int i, set_res = 0, get_res = 0;
+
+	for (i = 0; i < cgrp_opt_num; ++i) {
+		if (!cgrp_opt[i].mounted)
+			continue;
+
+		SAFE_CHDIR(cleanup, cgrp_opt[i].dir);
+		/* reset value */
+		id = 0;
+		/* set xattr to each file in cgroup fs */
+		set_res |= cgrp_files_walking(".", set_xattrs);
+
+		id = 0;
+		/* get & check xattr */
+		get_res |= cgrp_files_walking(".", get_xattrs);
+		SAFE_CHDIR(cleanup, "..");
+	}
+
+	/* final results */
+	tst_resm(TINFO, "All test-cases have been completed, summary:");
+	tst_resm(TINFO, "Set tests result: %s", (set_res) ? "FAIL" : "PASS");
+	tst_resm(TINFO, "Get tests result: %s", (get_res) ? "FAIL" : "PASS");
+}
+
+static void cleanup(void)
+{
+	if (val.buf != NULL)
+		free(val.buf);
+
+	if (skip_cleanup)
+		return;
+
+	/*
+	 * Kernels 3.7 can crash while unmounting cgroups with xattr,
+	 * call tst_flush() to make sure all buffered data written
+	 * before it happens
+	 */
+	tst_flush();
+
+	int i;
+	for (i = 0; i < odir_num; ++i) {
+		if (closedir(odir[i]) == -1)
+			tst_brkm(TBROK, NULL, "Failed to close dir\n");
+	}
+
+	char *cwd = get_tst_tmpdir();
+	SAFE_CHDIR(NULL, cwd);
+	free(cwd);
+
+	for (i = 0; i < cgrp_opt_num; ++i) {
+		if (cgrp_opt[i].subdir) {
+			SAFE_CHDIR(NULL, cgrp_opt[i].dir);
+			if (rmdir(subdir_name) == -1) {
+				tst_brkm(TBROK | TERRNO, NULL,
+					"Can't remove dir");
+			}
+			SAFE_CHDIR(NULL, "..");
+		}
+		if (cgrp_opt[i].mounted) {
+			if (umount(cgrp_opt[i].dir) == -1) {
+				tst_brkm(TBROK | TERRNO, NULL,
+					"Can't unmount: %s", cgrp_opt[i].dir);
+			}
+		}
+	}
+
+	tst_rmdir();
+	TEST_CLEANUP;
+}
+
+int mount_cgroup(void)
+{
+	FILE *fd = fopen("/proc/cgroups", "r");
+	if (fd == NULL)
+		tst_brkm(TBROK, cleanup, "Failed to read /proc/cgroups");
+	char str[MAX_DIR_NAME], name[MAX_DIR_NAME];
+	int hier = 0, num = 0, enabled = 0, first = 1;
+	/* make mount options */
+	while ((fgets(str, MAX_DIR_NAME, fd)) != NULL) {
+		/* skip first line */
+		if (first) {
+			first = 0;
+			continue;
+		}
+		if (sscanf(str, "%s\t%d\t%d\t%d",
+			name, &hier, &num, &enabled) != 4)
+			tst_brkm(TBROK, cleanup, "Can't parse /proc/cgroups");
+		if (!enabled)
+			continue;
+
+		/* BUG WORKAROUND
+		 * Only mount those subsystems, which are not mounted yet.
+		 * It's a workaround to a bug when mount doesn't return any err
+		 * code while mounting already mounted subsystems, but with
+		 * additional "xattr" option. In that case, mount will succeed,
+		 * but xattr won't be supported in the new mount anyway.
+		 * Should be removed as soon as a fix committed to upstream.
+		 */
+		if (hier != 0)
+			continue;
+
+		int i, found = 0;
+		for (i = 0; i < cgrp_opt_num; ++i) {
+			if (cgrp_opt[i].hier == hier) {
+				found = 1;
+				break;
+			}
+		}
+		if (!found) {
+			i = cgrp_opt_num++;
+			cgrp_opt[i].hier = hier;
+		}
+		char *str = cgrp_opt[i].str;
+		if (str[0] == '\0')
+			strcpy(str, "xattr");
+		snprintf(str + strlen(str), MAX_OPTIONS_LEN - strlen(str),
+			",%s", name);
+	}
+	fclose(fd);
+
+	int i, any_mounted = 0;
+	for (i = 0; i < cgrp_opt_num; ++i) {
+		char dir[MAX_DIR_NAME];
+		struct cgrp_option *opt = &cgrp_opt[i];
+		tst_resm(TINFO, "mount options %d: %s (hier = %d)",
+			i, opt->str, opt->hier);
+		snprintf(opt->dir, MAX_DIR_NAME, "cgx_%d", opt->hier);
+		SAFE_MKDIR(cleanup, opt->dir, 0755);
+
+		if (mount(opt->dir, opt->dir, "cgroup", 0, opt->str) == -1) {
+			tst_resm(TINFO, "Can't mount: %s", dir);
+			continue;
+		}
+
+		any_mounted = 1;
+		opt->mounted = 1;
+
+		/* create new hierarchy */
+		SAFE_CHDIR(cleanup, opt->dir);
+		SAFE_MKDIR(cleanup, subdir_name, 0755);
+		opt->subdir = 1;
+		SAFE_CHDIR(cleanup, "..");
+	}
+	return any_mounted;
+}
+
+static int set_xattrs(const char *file)
+{
+	int i, err, fail, res = 0;
+
+	for (i = 0; i < ARRAY_SIZE(tkeys); ++i) {
+		err = setxattr(file, tkeys[i].name,
+			(const void *)val.buf, val.size, 0) == -1;
+
+		fail = err && tkeys[i].good;
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS,
+			"Expect: %s set xattr key '%s' to file '%s'",
+			(tkeys[i].good) ? "can" : "can't",
+			tkeys[i].name, file);
+
+		if (verbose && tkeys[i].good)
+			tst_resm_hexd(TINFO, val.buf, val.size, "value:");
+	}
+	return res;
+}
+
+static int get_xattrs(const char *file)
+{
+	int i, fail, res = 0;
+
+	for (i = 0; i < ARRAY_SIZE(tkeys); ++i) {
+		/* get value size */
+		ssize_t size = getxattr(file, tkeys[i].name, NULL, 0);
+		fail = (size == -1 && tkeys[i].good);
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS,
+			"Expect: %s read xattr %s of file '%s'",
+			(tkeys[i].good) ? "can" : "can't",
+			tkeys[i].name, file);
+
+		if (fail || size == -1)
+			continue;
+
+		/* get xattr value */
+		char xval[size];
+		if (getxattr(file, tkeys[i].name, xval, size) == -1) {
+			tst_brkm(TBROK, cleanup,
+				"Can't get buffer of key %s",
+				tkeys[i].name);
+		}
+		fail = val.size != size ||
+			strncmp(val.buf, xval, val.size) != 0;
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS, "Expect: values equal");
+
+		if (verbose && fail) {
+			tst_resm_hexd(TINFO, xval, size,
+				"Read  xattr  value:");
+			tst_resm_hexd(TINFO, val.buf, val.size,
+				"Expect xattr value:");
+		}
+	}
+	return res;
+}
+
+static int cgrp_files_walking(const char *path,
+	int (*xattr_operation)(const char *))
+{
+	int res = 0;
+	struct dirent *entry;
+	DIR *dir = opendir(path);
+
+	odir[odir_num] = dir;
+	if (++odir_num >= MAX_OPEN_DIR) {
+		tst_brkm(TBROK, cleanup,
+			"Unexpected num of open dirs, max: %d", MAX_OPEN_DIR);
+	}
+
+	SAFE_CHDIR(cleanup, path);
+
+	tst_resm(TINFO, "In dir %s", path);
+
+	errno = 0;
+	while ((entry = readdir(dir)) != NULL) {
+		const char *file = entry->d_name;
+		/* skip current and up directories */
+		if (!strcmp(file, "..") || !strcmp(file, "."))
+			continue;
+		struct stat stat_buf;
+		TEST(lstat(file, &stat_buf));
+		if (TEST_RETURN != -1 && S_ISDIR(stat_buf.st_mode)) {
+			/* proceed to subdir */
+			res |= cgrp_files_walking(file, xattr_operation);
+			tst_resm(TINFO, "In dir %s", path);
+		}
+		memset(val.buf, id++, val.size);
+		res |= xattr_operation(file);
+		errno = 0;
+	}
+	if (errno && !entry) {
+		tst_brkm(TWARN | TERRNO, cleanup,
+			"Error while reading dir '%s'", path);
+	}
+	if (closedir(dir) == -1)
+		tst_brkm(TWARN, cleanup, "Failed to close dir '%s'", path);
+	else
+		odir[--odir_num] = NULL;
+
+	if (strcmp(path, "."))
+		SAFE_CHDIR(cleanup, "..");
+	return res;
+}
-- 
1.7.1


------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

^ permalink raw reply related	[flat|nested] 15+ messages in thread
* [LTP] [PATCH] New core test of cgroups and extended attributes
@ 2013-05-24 12:20 Alexey Kodanev
  2013-05-28 14:37 ` chrubis
  0 siblings, 1 reply; 15+ messages in thread
From: Alexey Kodanev @ 2013-05-24 12:20 UTC (permalink / raw)
  To: ltp-list; +Cc: vasily.isaenko, Alexey Kodanev

Support of extended attributes in cgroups was added in Linux 3.7.

Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
---
 runtest/controllers                                |    1 +
 .../kernel/controllers/cgroup_xattr/.gitignore     |    1 +
 testcases/kernel/controllers/cgroup_xattr/Makefile |   19 +
 testcases/kernel/controllers/cgroup_xattr/README   |   25 +
 .../kernel/controllers/cgroup_xattr/cgroup_xattr.c |  460 ++++++++++++++++++++
 5 files changed, 506 insertions(+), 0 deletions(-)
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/.gitignore
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/Makefile
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/README
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c

diff --git a/runtest/controllers b/runtest/controllers
index b78d828..94fc185 100644
--- a/runtest/controllers
+++ b/runtest/controllers
@@ -12,3 +12,4 @@ memcg_stress		memcg_stress_test.sh
 memcg_control		PAGESIZE=$(mem_process -p);memcg_control_test.sh $PAGESIZE $PAGESIZE $((PAGESIZE * 2))
 cgroup_fj	run_cgroup_test_fj.sh
 controllers	test_controllers.sh
+cgroup_xattr	cgroup_xattr
diff --git a/testcases/kernel/controllers/cgroup_xattr/.gitignore b/testcases/kernel/controllers/cgroup_xattr/.gitignore
new file mode 100644
index 0000000..3664cc9
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/.gitignore
@@ -0,0 +1 @@
+/cgroup_xattr
diff --git a/testcases/kernel/controllers/cgroup_xattr/Makefile b/testcases/kernel/controllers/cgroup_xattr/Makefile
new file mode 100644
index 0000000..cd49588
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/Makefile
@@ -0,0 +1,19 @@
+# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/controllers/cgroup_xattr/README b/testcases/kernel/controllers/cgroup_xattr/README
new file mode 100644
index 0000000..42e294d
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/README
@@ -0,0 +1,25 @@
+TEST SUITE:
+
+The directory cgroup_xattr contains the tests related to extended
+attributes in cgroup filesystem.
+
+WARNING:
+
+This test can cause a kernel panic due to a bug in kernels prior to 3.8.
+It was fixed by kernel upstream commit
+712317ad97f41e738e1a19aa0a6392a78a84094e:
+
+"We should store file xattrs in struct cfent instead of struct cftype,
+because cftype is a type while cfent is object instance of cftype."
+
+TESTS AIM:
+
+The aim of the tests is to check the extended attributes in cgroup
+filesystem. This feature was added in Linux 3.7 to allow attaching runtime
+meta information to cgroups and everything they model (services, apps, vms)
+and can easily be shared among applications.
+
+Test creates as many subsystems as possible (cpu, cpuset, memory, ...) in
+the cgroup directory and in one more created hierarchy. Then sets extended
+attributes to all files in cgroup fs and subsequently reads the file's
+extended attributes back, checking values during the process.
diff --git a/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c
new file mode 100644
index 0000000..ebf6ca4
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author:
+ * Alexey Kodanev <alexey.kodanev@oracle.com>
+ *
+ * Test checks following preconditions:
+ * since Linux kernel 3.7 it is possible to set extended attributes
+ * to cgroup files.
+ */
+
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "test.h"
+#include "usctest.h"
+#include "safe_macros.h"
+
+char *TCID = "cgroup_xattr";
+
+static const char subdir_name[]	= "test";
+
+#define MAX_SUBSYS		16
+#define MAX_OPTIONS_LEN		256
+#define MAX_DIR_NAME		64
+
+/* struct to store available mount options */
+struct cgrp_option {
+	char opt[MAX_OPTIONS_LEN];
+	char dir[MAX_DIR_NAME];
+	int hier;
+	int mounted;
+	int subdir;
+};
+static struct cgrp_option cgrp_opt[MAX_SUBSYS];
+static int cgrp_opt_num;
+
+struct tst_key {
+	const char *name;
+	int good;
+};
+
+/* only security.* & trusted.* are valid key names */
+static const struct tst_key tkeys[] = {
+	{ .name = "trusted.test",	.good = 1,	},
+	{ .name = "security.",		.good = 1,	},
+	{ .name = "user.",		.good = 0,	},
+	{ .name = "system.",		.good = 0,	},
+};
+
+#define DEFAULT_VALUE_SIZE	8
+
+/* struct to store key's value */
+struct tst_val {
+	char *buf;
+	size_t size;
+};
+static struct tst_val val;
+
+/* it fills value's buffer */
+static char id;
+
+/*
+ * When test breaks, all open dirs should be closed
+ * otherwise umount won't succeed
+ */
+#define MAX_OPEN_DIR		32
+static DIR *odir[MAX_OPEN_DIR];
+static int odir_num;
+
+/* test options */
+static char *narg;
+static int nflag;
+static int skip_cleanup;
+static int verbose;
+static const option_t options[] = {
+	{"n:", &nflag, &narg},
+	{"s", &skip_cleanup, NULL},
+	{"v", &verbose, NULL},
+	{NULL, NULL, NULL}
+};
+
+static void help(void);
+static void setup(int argc, char *argv[]);
+static void test_run(void);
+static void cleanup(void);
+
+/*
+ * get info about mounted subsystems,
+ * make cgroup mount options
+ */
+static void make_cgroup_options(void);
+static int set_xattrs(const char *file);
+static int get_xattrs(const char *file);
+/*
+ * set or get xattr recursively
+ *
+ * @path: start directory
+ * @xattr_operation: can be set_xattrs() or get_xattrs()
+ */
+static int cgrp_files_walking(const char *path,
+	int (*xattr_operation)(const char *));
+
+int main(int argc, char *argv[])
+{
+	setup(argc, argv);
+
+	test_run();
+
+	cleanup();
+
+	tst_exit();
+}
+
+static void help(void)
+{
+	printf("  -n x    Write x bytes to xattr value, default is %d\n",
+		DEFAULT_VALUE_SIZE);
+	printf("  -s      Skip cleanup\n");
+	printf("  -v      Verbose\n");
+}
+
+void setup(int argc, char *argv[])
+{
+	char *msg;
+	msg = parse_opts(argc, argv, options, help);
+	if (msg != NULL)
+		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+
+	tst_require_root(NULL);
+
+	if (access("/proc/cgroups", F_OK) == -1)
+		tst_brkm(TCONF, NULL, "Kernel doesn't support for cgroups");
+
+	if (tst_kvercmp(3, 7, 0) < 0) {
+		tst_brkm(TCONF, NULL,
+			"Test must be run with kernel 3.7 or newer");
+	}
+
+	int value_size = DEFAULT_VALUE_SIZE;
+	if (nflag) {
+		if (sscanf(narg, "%i", &value_size) != 1)
+			tst_brkm(TBROK, NULL, "-n option arg is not a number");
+		if (value_size <= 0)
+			tst_brkm(TBROK, NULL, "-n option arg is less than 1");
+	}
+
+	/* initialize test value */
+	val.size = value_size;
+	val.buf = SAFE_MALLOC(NULL, value_size);
+
+	tst_sig(FORK, DEF_HANDLER, cleanup);
+
+	tst_tmpdir();
+
+	make_cgroup_options();
+
+	int any_mounted = 0;
+	int i;
+	for (i = 0; i < cgrp_opt_num; ++i) {
+		char dir[MAX_DIR_NAME];
+		snprintf(cgrp_opt[i].dir, MAX_DIR_NAME, "cgx_%d",
+			cgrp_opt[i].hier);
+		SAFE_MKDIR(cleanup, cgrp_opt[i].dir, 0755);
+		if (mount(cgrp_opt[i].dir, cgrp_opt[i].dir, "cgroup", 0,
+			cgrp_opt[i].opt) == -1) {
+			tst_resm(TINFO, "Can't mount: %s", dir);
+			continue;
+		}
+
+		any_mounted = 1;
+		cgrp_opt[i].mounted = 1;
+
+		/* create new hierarchy */
+		SAFE_CHDIR(cleanup, cgrp_opt[i].dir);
+		SAFE_MKDIR(cleanup, subdir_name, 0755);
+		cgrp_opt[i].subdir = 1;
+		SAFE_CHDIR(cleanup, "..");
+	}
+
+	if (!any_mounted)
+		tst_brkm(TBROK, cleanup, "Mounted nothing");
+}
+
+static void test_run(void)
+{
+	int	set_res = 0,
+		get_res = 0,
+		i;
+	for (i = 0; i < cgrp_opt_num; ++i) {
+		if (!cgrp_opt[i].mounted)
+			continue;
+
+		SAFE_CHDIR(cleanup, cgrp_opt[i].dir);
+		/* reset value */
+		id = 0;
+		/* set xattr to each file in cgroup fs */
+		set_res |= cgrp_files_walking(".", set_xattrs);
+		/* reset value */
+		id = 0;
+		/* get & check xattr */
+		get_res |= cgrp_files_walking(".", get_xattrs);
+		SAFE_CHDIR(cleanup, "..");
+	}
+
+	/* final results */
+	tst_resm(TINFO, "All test-cases have been completed, summary:");
+	tst_resm(TINFO, "Set tests result: %s", (set_res) ? "FAIL" : "PASS");
+	tst_resm(TINFO, "Get tests result: %s", (get_res) ? "FAIL" : "PASS");
+}
+
+static void cleanup(void)
+{
+	if (val.buf != NULL)
+		free(val.buf);
+
+	if (skip_cleanup)
+		return;
+
+	/*
+	 * Kernels 3.7 can crash while unmounting cgroups with xattr,
+	 * call tst_flush() to make sure all buffered data written
+	 * before it happens
+	 */
+	tst_flush();
+
+	int i;
+	for (i = 0; i < odir_num; ++i) {
+		if (closedir(odir[i]) == -1)
+			tst_brkm(TBROK, NULL, "Failed to close dir\n");
+	}
+
+	char *cwd = get_tst_tmpdir();
+	SAFE_CHDIR(NULL, cwd);
+	free(cwd);
+
+	for (i = 0; i < cgrp_opt_num; ++i) {
+		if (cgrp_opt[i].subdir) {
+			SAFE_CHDIR(NULL, cgrp_opt[i].dir);
+			if (rmdir(subdir_name) == -1) {
+				tst_brkm(TBROK | TERRNO, NULL,
+					"Can't remove dir");
+			}
+			SAFE_CHDIR(NULL, "..");
+		}
+		if (cgrp_opt[i].mounted) {
+			if (umount(cgrp_opt[i].dir) == -1) {
+				tst_brkm(TBROK | TERRNO, NULL,
+					"Can't unmount: %s", cgrp_opt[i].dir);
+			}
+		}
+	}
+
+	tst_rmdir();
+	TEST_CLEANUP;
+}
+
+void make_cgroup_options(void)
+{
+	/* detect subsystems */
+	FILE *fd = fopen("/proc/cgroups", "r");
+	if (fd == NULL)
+		tst_brkm(TBROK, cleanup, "Failed to read /proc/cgroups");
+
+	char str[MAX_DIR_NAME];
+	char name[MAX_DIR_NAME];
+	int	hier	= 0,
+		num	= 0,
+		enabled	= 0,
+		first	= 1;
+
+	while ((fgets(str, MAX_DIR_NAME, fd)) != NULL) {
+		/* skip first line */
+		if (first) {
+			first = 0;
+			continue;
+		}
+		if (sscanf(str, "%s\t%d\t%d\t%d",
+			name, &hier, &num, &enabled) != 4)
+			tst_brkm(TBROK, cleanup, "Can't parse /proc/cgroups");
+
+		if (!enabled)
+			continue;
+
+		/* BUG WORKAROUND
+		 * Only mount those subsystems, which are not mounted yet.
+		 * It's a workaround to a bug when mount doesn't
+		 * return any err code while mounting already mounted
+		 * subsystems, but with additional "xattr" option.
+		 * In that case, mount will succeed, but xattr won't be
+		 * supported in the new mount anyway.
+		 * Should be removed as soon as a fix committed to upstream.
+		 */
+		if (hier != 0)
+			continue;
+		/* end of workaround */
+
+		int found = 0;
+		int i;
+		for (i = 0; i < cgrp_opt_num; ++i) {
+			if (cgrp_opt[i].hier == hier) {
+				found = 1;
+				break;
+			}
+		}
+
+		if (!found) {
+			i = cgrp_opt_num++;
+			cgrp_opt[i].hier = hier;
+		}
+
+		int len = strlen(cgrp_opt[i].opt);
+		if (len == 0) {
+			strcpy(cgrp_opt[i].opt, "xattr");
+			len = strlen(cgrp_opt[i].opt);
+		}
+
+		sprintf(cgrp_opt[i].opt + len, ",%s", name);
+	}
+	fclose(fd);
+
+	int i;
+	for (i = 0; i < cgrp_opt_num; ++i) {
+		tst_resm(TINFO, "mount options %d: %s (hier = %d)",
+			i, cgrp_opt[i].opt, cgrp_opt[i].hier);
+	}
+}
+
+static int set_xattrs(const char *file)
+{
+	int i, err, fail, res;
+	res = 0;
+	for (i = 0; i < ARRAY_SIZE(tkeys); ++i) {
+		err = setxattr(file, tkeys[i].name,
+			(const void *)val.buf, val.size, 0) == -1;
+
+		fail = err && tkeys[i].good;
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS,
+			"Expect: %s set xattr key '%s' to file '%s'",
+			(tkeys[i].good) ? "can" : "can't",
+			tkeys[i].name, file);
+
+		if (verbose && tkeys[i].good)
+			tst_resm_hexd(TINFO, val.buf, val.size, "value:");
+	}
+	return res;
+}
+
+static int get_xattrs(const char *file)
+{
+	int i, fail, res;
+	res = 0;
+	for (i = 0; i < ARRAY_SIZE(tkeys); ++i) {
+		/* get value size */
+		ssize_t size = getxattr(file, tkeys[i].name, NULL, 0);
+		fail = (size == -1 && tkeys[i].good);
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS,
+			"Expect: %s read xattr %s of file '%s'",
+			(tkeys[i].good) ? "can" : "can't",
+			tkeys[i].name, file);
+
+		if (fail || size == -1)
+			continue;
+
+		/* get xattr value */
+		char xval[size];
+		if (getxattr(file, tkeys[i].name, xval, size) == -1) {
+			tst_brkm(TBROK, cleanup,
+				"Can't get buffer of key %s",
+				tkeys[i].name);
+		}
+		fail = val.size != size ||
+			strncmp(val.buf, xval, val.size) != 0;
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS, "Expect: values equal");
+
+		if (verbose && fail) {
+			tst_resm_hexd(TINFO, xval, size,
+				"Read  xattr  value:");
+			tst_resm_hexd(TINFO, val.buf, val.size,
+				"Expect xattr value:");
+		}
+	}
+	return res;
+}
+
+static int cgrp_files_walking(const char *path,
+	int (*xattr_operation)(const char *))
+{
+	int res = 0;
+	struct dirent *entry;
+	DIR *dir = opendir(path);
+
+	odir[odir_num] = dir;
+	if (++odir_num >= MAX_OPEN_DIR) {
+		tst_brkm(TBROK, cleanup,
+			"Unexpected num of open dirs, max: %d", MAX_OPEN_DIR);
+	}
+
+	SAFE_CHDIR(cleanup, path);
+
+	tst_resm(TINFO, "In dir %s", path);
+
+	errno = 0;
+	while ((entry = readdir(dir)) != NULL) {
+		const char *file = entry->d_name;
+		/* skip current and up directories */
+		if (!strcmp(file, "..") || !strcmp(file, "."))
+			continue;
+		struct stat stat_buf;
+		TEST(lstat(file, &stat_buf));
+		if (TEST_RETURN != -1 && S_ISDIR(stat_buf.st_mode)) {
+			/* proceed to subdir */
+			res |= cgrp_files_walking(file, xattr_operation);
+			tst_resm(TINFO, "In dir %s", path);
+		}
+		memset(val.buf, id++, val.size);
+		res |= xattr_operation(file);
+		errno = 0;
+	}
+	if (errno && !entry) {
+		tst_brkm(TWARN | TERRNO, cleanup,
+			"Error while reading dir '%s'", path);
+	}
+	if (closedir(dir) == -1)
+		tst_brkm(TWARN, cleanup, "Failed to close dir '%s'", path);
+	else
+		odir[--odir_num] = NULL;
+
+	if (strcmp(path, "."))
+		SAFE_CHDIR(cleanup, "..");
+	return res;
+}
-- 
1.7.1


------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service 
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_may
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

^ permalink raw reply related	[flat|nested] 15+ messages in thread
* [LTP] [PATCH] New core test of cgroups and extended attributes
@ 2013-05-23 16:28 Alexey Kodanev
  0 siblings, 0 replies; 15+ messages in thread
From: Alexey Kodanev @ 2013-05-23 16:28 UTC (permalink / raw)
  To: ltp-list; +Cc: vasily.isaenko, Alexey Kodanev

Support of extended attributes in cgroups was added in Linux 3.7.

Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
---
 runtest/controllers                                |    1 +
 .../kernel/controllers/cgroup_xattr/.gitignore     |    1 +
 testcases/kernel/controllers/cgroup_xattr/Makefile |   19 +
 testcases/kernel/controllers/cgroup_xattr/README   |   25 ++
 .../kernel/controllers/cgroup_xattr/cgroup_xattr.c |  402 ++++++++++++++++++++
 5 files changed, 448 insertions(+), 0 deletions(-)
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/.gitignore
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/Makefile
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/README
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c

diff --git a/runtest/controllers b/runtest/controllers
index b78d828..94fc185 100644
--- a/runtest/controllers
+++ b/runtest/controllers
@@ -12,3 +12,4 @@ memcg_stress		memcg_stress_test.sh
 memcg_control		PAGESIZE=$(mem_process -p);memcg_control_test.sh $PAGESIZE $PAGESIZE $((PAGESIZE * 2))
 cgroup_fj	run_cgroup_test_fj.sh
 controllers	test_controllers.sh
+cgroup_xattr	cgroup_xattr
diff --git a/testcases/kernel/controllers/cgroup_xattr/.gitignore b/testcases/kernel/controllers/cgroup_xattr/.gitignore
new file mode 100644
index 0000000..3664cc9
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/.gitignore
@@ -0,0 +1 @@
+/cgroup_xattr
diff --git a/testcases/kernel/controllers/cgroup_xattr/Makefile b/testcases/kernel/controllers/cgroup_xattr/Makefile
new file mode 100644
index 0000000..cd49588
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/Makefile
@@ -0,0 +1,19 @@
+# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/controllers/cgroup_xattr/README b/testcases/kernel/controllers/cgroup_xattr/README
new file mode 100644
index 0000000..9cc5176
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/README
@@ -0,0 +1,25 @@
+TEST SUITE:
+
+The directory cgroup_xattr contains the tests related to extended
+attributes in cgroup filesystem.
+
+WARNING:
+
+This test can cause a kernel panic due to a bug in kernels prior to 3.8.
+It was fixed by kernel upstream commit
+712317ad97f41e738e1a19aa0a6392a78a84094e:
+
+"We should store file xattrs in struct cfent instead of struct cftype,
+because cftype is a type while cfent is object instance of cftype."
+
+TESTS AIM:
+
+The aim of the tests is to check the extended attributes in cgroup
+filesystem. This feature was added in Linux 3.7 to allow attaching runtime
+meta information to cgroups and everything they model (services, apps, vms)
+and can easily be shared among applications.
+
+Test creates as many subsystems as possible (cpu, cpuset, ...) in the
+cgroup tmp directory and in one more created hierarchy. Then sets extended
+attributes to all files in cgroup fs and subsequently reads the file's
+extended attributes back, checking values during the process.
diff --git a/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c
new file mode 100644
index 0000000..4ef5e16
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author:
+ * Alexey Kodanev <alexey.kodanev@oracle.com>
+ *
+ * Test checks following preconditions:
+ * since Linux kernel 3.7 it is possible to set extended attributes
+ * to cgroup files.
+ */
+
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "test.h"
+#include "usctest.h"
+#include "safe_macros.h"
+
+char *TCID = "cgroup_xattr";
+
+static const char cgrp_point[]	= "cgroup";
+static const char cgrp_name[]	= "cgrp_test";
+static const char subdir_name[]	= "test";
+
+#define MAX_SUBSYS		64
+#define MAX_OPTIONS_LEN		256
+
+static char subsys[MAX_OPTIONS_LEN];
+
+struct tst_key {
+	const char *name;
+	int good;
+};
+
+/* only security.* & trusted.* are valid key names */
+static const struct tst_key tkeys[] = {
+	{ .name = "trusted.test",	.good = 1,	},
+	{ .name = "security.",		.good = 1,	},
+	{ .name = "user.",		.good = 0,	},
+	{ .name = "system.",		.good = 0,	},
+};
+
+#define DEFAULT_VALUE_SIZE	8
+
+/* struct to store key's value */
+struct tst_val {
+	char *buf;
+	size_t size;
+};
+static struct tst_val val;
+
+/* it fills value's buffer */
+static char id;
+
+/* cleanup flags */
+static int cgrp_mounted;
+static int subdir_created;
+
+/*
+ * When test breaks, all open dirs should be closed
+ * otherwise umount won't succeed
+ */
+#define MAX_OPEN_DIR		32
+static DIR *odir[MAX_OPEN_DIR];
+static int odir_num;
+
+/* test options */
+static char *narg;
+static int nflag;
+static int skip_cleanup;
+static int verbose;
+static const option_t options[] = {
+	{"n:", &nflag, &narg},
+	{"s", &skip_cleanup, NULL},
+	{"v", &verbose, NULL},
+	{NULL, NULL, NULL}
+};
+
+static void help(void);
+static void setup(int argc, char *argv[]);
+static void test_run(void);
+static void cleanup(void);
+
+/*
+ * get info about mounted subsystems,
+ * it is possible to mount only already mounted subsystems
+ * or ones not mounted, other combinations won't succeed
+ */
+static void make_cgroup_options(void);
+static int set_xattrs(const char *file);
+static int get_xattrs(const char *file);
+/*
+ * set or get xattr recursively
+ *
+ * @path: start directory
+ * @xattr_operation: can be set_xattrs() or get_xattrs()
+ */
+static int cgrp_files_walking(const char *path,
+	int (*xattr_operation)(const char *));
+
+int main(int argc, char *argv[])
+{
+	setup(argc, argv);
+
+	test_run();
+
+	cleanup();
+
+	tst_exit();
+}
+
+static void help(void)
+{
+	printf("  -n x    Write x bytes to xattr value, default is %d\n",
+		DEFAULT_VALUE_SIZE);
+	printf("  -s      Skip cleanup\n");
+	printf("  -v      Verbose\n");
+}
+
+void setup(int argc, char *argv[])
+{
+	char *msg;
+	msg = parse_opts(argc, argv, options, help);
+	if (msg != NULL)
+		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+
+	tst_require_root(NULL);
+
+	if (access("/proc/cgroups", F_OK) == -1)
+		tst_brkm(TCONF, NULL, "Kernel doesn't support for cgroups");
+
+	if (tst_kvercmp(3, 7, 0) < 0) {
+		tst_brkm(TCONF, NULL,
+			"Test must be run with kernel 3.7 or newer");
+	}
+
+	int value_size = DEFAULT_VALUE_SIZE;
+	if (nflag) {
+		if (sscanf(narg, "%i", &value_size) != 1)
+			tst_brkm(TBROK, NULL, "-n option arg is not a number");
+		if (value_size <= 0)
+			tst_brkm(TBROK, NULL, "-n option arg is less than 1");
+	}
+
+	/* initialize test value */
+	val.size = value_size;
+	val.buf = SAFE_MALLOC(NULL, value_size);
+
+	tst_sig(FORK, DEF_HANDLER, cleanup);
+
+	tst_tmpdir();
+
+	SAFE_MKDIR(cleanup, cgrp_point, 0755);
+
+	make_cgroup_options();
+
+	if (mount(cgrp_name, cgrp_point, "cgroup", 0, subsys) == -1)
+		tst_brkm(TBROK, cleanup, "Can't mount: %s", cgrp_point);
+	cgrp_mounted = 1;
+
+	/* create new hierarchy */
+	SAFE_CHDIR(cleanup, cgrp_point);
+	SAFE_MKDIR(cleanup, subdir_name, 0755);
+	subdir_created = 1;
+}
+
+static void test_run(void)
+{
+	/* set xattr to each file in cgroup fs */
+	int set_res = cgrp_files_walking(".", set_xattrs);
+	/* reset value */
+	id = 0;
+	/* get & check xattr */
+	int get_res = cgrp_files_walking(".", get_xattrs);
+
+	/* final results */
+	tst_resm(TINFO, "All test-cases have been completed, summary:");
+	tst_resm(TINFO, "Set tests result: %s", (set_res) ? "FAIL" : "PASS");
+	tst_resm(TINFO, "Get tests result: %s", (get_res) ? "FAIL" : "PASS");
+}
+
+static void cleanup(void)
+{
+	if (val.buf != NULL)
+		free(val.buf);
+
+	if (skip_cleanup)
+		return;
+
+	/*
+	 * Kernels 3.7 can crash while unmounting cgroups with xattr,
+	 * call tst_flush() to make sure all buffered data written
+	 * before it happens
+	 */
+	tst_flush();
+
+	int i;
+	for (i = 0; i < odir_num; ++i) {
+		if (closedir(odir[i]) == -1)
+			tst_brkm(TBROK, NULL, "Failed to close dir\n");
+	}
+
+	char *cwd = get_tst_tmpdir();
+	SAFE_CHDIR(NULL, cwd);
+	free(cwd);
+
+	if (subdir_created) {
+		SAFE_CHDIR(NULL, cgrp_point);
+		if (rmdir(subdir_name) == -1)
+			tst_brkm(TBROK | TERRNO, NULL, "Can't remove dir");
+		SAFE_CHDIR(NULL, "..");
+	}
+
+	if (cgrp_mounted) {
+		if (umount(cgrp_point) == -1) {
+			tst_brkm(TBROK | TERRNO, NULL,
+				"Can't unmount: %s", cgrp_point);
+		}
+	}
+
+	tst_rmdir();
+	TEST_CLEANUP;
+}
+
+void make_cgroup_options(void)
+{
+	/* detect sybsystems */
+	FILE *fd = fopen("/proc/cgroups", "r");
+	if (fd == NULL)
+		tst_brkm(TBROK, cleanup, "Failed to read /proc/cgroups");
+
+	int subsys_ynum = 0;
+	/* store not mounted subsys here*/
+	char subsys_n[MAX_OPTIONS_LEN];
+	int subsys_nnum = 0;
+
+	strcpy(subsys, "xattr");
+	strcpy(subsys_n, "xattr");
+
+	char str[MAX_SUBSYS];
+
+	int first = 1;
+
+	while ((fgets(str, MAX_SUBSYS, fd)) != NULL) {
+		/* skip first line */
+		if (first) {
+			first = 0;
+			continue;
+		}
+		int num = 0;
+		char name[MAX_SUBSYS];
+		sscanf(str, "%s\t%d", name, &num);
+
+		strcat((num > 0) ? subsys : subsys_n, ",");
+		strcat((num > 0) ? subsys : subsys_n, name);
+
+		if (num > 0)
+			++subsys_ynum;
+		else
+			++subsys_nnum;
+	}
+	fclose(fd);
+
+	/* get as many subsystems as possible */
+	if (subsys_ynum < subsys_nnum)
+		strcpy(subsys, subsys_n);
+
+	tst_resm(TINFO, "mount options: %s", subsys);
+}
+
+static int set_xattrs(const char *file)
+{
+	int i, err, fail, res;
+	res = 0;
+	for (i = 0; i < ARRAY_SIZE(tkeys); ++i) {
+		err = setxattr(file, tkeys[i].name,
+			(const void *)val.buf, val.size, 0) == -1;
+
+		fail = err && tkeys[i].good;
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS,
+			"Expect: %s set xattr key '%s' to file '%s'",
+			(tkeys[i].good) ? "can" : "can't",
+			tkeys[i].name, file);
+
+		if (verbose && tkeys[i].good)
+			tst_resm_hexd(TINFO, val.buf, val.size, "value:");
+	}
+	return res;
+}
+
+static int get_xattrs(const char *file)
+{
+	int i, fail, res;
+	res = 0;
+	for (i = 0; i < ARRAY_SIZE(tkeys); ++i) {
+		/* get value size */
+		ssize_t size = getxattr(file, tkeys[i].name, NULL, 0);
+		fail = (size == -1 && tkeys[i].good);
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS,
+			"Expect: %s read xattr %s of file '%s'",
+			(size == -1) ? "can't" : "can",
+			tkeys[i].name, file);
+
+		if (fail || size == -1)
+			continue;
+
+		/* get xattr value */
+		char xval[size];
+		if (getxattr(file, tkeys[i].name, xval, size) == -1) {
+			tst_brkm(TBROK, cleanup,
+				"Can't get buffer of key %s",
+				tkeys[i].name);
+		}
+		fail = val.size != size ||
+			strncmp(val.buf, xval, val.size) != 0;
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS, "Expect: values equal");
+
+		if (verbose && fail) {
+			tst_resm_hexd(TINFO, xval, size,
+				"Read  xattr  value:");
+			tst_resm_hexd(TINFO, val.buf, val.size,
+				"Expect xattr value:");
+		}
+	}
+	return res;
+}
+
+static int cgrp_files_walking(const char *path,
+	int (*xattr_operation)(const char *))
+{
+	int res = 0;
+	struct dirent *entry;
+	DIR *dir = opendir(path);
+
+	odir[odir_num] = dir;
+	if (++odir_num >= MAX_OPEN_DIR) {
+		tst_brkm(TBROK, cleanup,
+			"Unexpected num of open dirs, max: %d", MAX_OPEN_DIR);
+	}
+
+	SAFE_CHDIR(cleanup, path);
+
+	tst_resm(TINFO, "In dir %s", path);
+
+	errno = 0;
+	while ((entry = readdir(dir)) != NULL) {
+		const char *file = entry->d_name;
+		/* skip current and up directories */
+		if (!strcmp(file, "..") || !strcmp(file, "."))
+			continue;
+		struct stat stat_buf;
+		TEST(lstat(file, &stat_buf));
+		if (TEST_RETURN != -1 && S_ISDIR(stat_buf.st_mode)) {
+			/* proceed to subdir */
+			res |= cgrp_files_walking(file, xattr_operation);
+			tst_resm(TINFO, "In dir %s", path);
+		}
+		memset(val.buf, id++, val.size);
+		res |= xattr_operation(file);
+		errno = 0;
+	}
+	if (errno && !entry) {
+		tst_brkm(TWARN | TERRNO, cleanup,
+			"Error while reading dir '%s'", path);
+	}
+	if (closedir(dir) == -1)
+		tst_brkm(TWARN, cleanup, "Failed to close dir '%s'", path);
+	else
+		odir[--odir_num] = NULL;
+
+	if (strcmp(path, "."))
+		SAFE_CHDIR(cleanup, "..");
+	return res;
+}
-- 
1.7.1


------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service 
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_may
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

^ permalink raw reply related	[flat|nested] 15+ messages in thread
* [LTP] [PATCH] New core test of cgroups and extended attributes
@ 2013-05-23  7:09 Alexey Kodanev
  2013-05-23 13:31 ` chrubis
  0 siblings, 1 reply; 15+ messages in thread
From: Alexey Kodanev @ 2013-05-23  7:09 UTC (permalink / raw)
  To: ltp-list; +Cc: vasily.isaenko, Alexey Kodanev

Support of extended attributes in cgroups was added in Linux 3.7.

Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
---
 runtest/controllers                                |    1 +
 .../kernel/controllers/cgroup_xattr/.gitignore     |    1 +
 testcases/kernel/controllers/cgroup_xattr/Makefile |   19 +
 testcases/kernel/controllers/cgroup_xattr/README   |   25 ++
 .../kernel/controllers/cgroup_xattr/cgroup_xattr.c |  344 ++++++++++++++++++++
 5 files changed, 390 insertions(+), 0 deletions(-)
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/.gitignore
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/Makefile
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/README
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c

diff --git a/runtest/controllers b/runtest/controllers
index b78d828..94fc185 100644
--- a/runtest/controllers
+++ b/runtest/controllers
@@ -12,3 +12,4 @@ memcg_stress		memcg_stress_test.sh
 memcg_control		PAGESIZE=$(mem_process -p);memcg_control_test.sh $PAGESIZE $PAGESIZE $((PAGESIZE * 2))
 cgroup_fj	run_cgroup_test_fj.sh
 controllers	test_controllers.sh
+cgroup_xattr	cgroup_xattr
diff --git a/testcases/kernel/controllers/cgroup_xattr/.gitignore b/testcases/kernel/controllers/cgroup_xattr/.gitignore
new file mode 100644
index 0000000..3664cc9
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/.gitignore
@@ -0,0 +1 @@
+/cgroup_xattr
diff --git a/testcases/kernel/controllers/cgroup_xattr/Makefile b/testcases/kernel/controllers/cgroup_xattr/Makefile
new file mode 100644
index 0000000..cd49588
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/Makefile
@@ -0,0 +1,19 @@
+# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/controllers/cgroup_xattr/README b/testcases/kernel/controllers/cgroup_xattr/README
new file mode 100644
index 0000000..9cc5176
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/README
@@ -0,0 +1,25 @@
+TEST SUITE:
+
+The directory cgroup_xattr contains the tests related to extended
+attributes in cgroup filesystem.
+
+WARNING:
+
+This test can cause a kernel panic due to a bug in kernels prior to 3.8.
+It was fixed by kernel upstream commit
+712317ad97f41e738e1a19aa0a6392a78a84094e:
+
+"We should store file xattrs in struct cfent instead of struct cftype,
+because cftype is a type while cfent is object instance of cftype."
+
+TESTS AIM:
+
+The aim of the tests is to check the extended attributes in cgroup
+filesystem. This feature was added in Linux 3.7 to allow attaching runtime
+meta information to cgroups and everything they model (services, apps, vms)
+and can easily be shared among applications.
+
+Test creates all available subsystems (cpu, cpuset, memory, ...) in the
+cgroup directory and in one more created hierarchy. Then sets extended
+attributes to all files in cgroup fs and subsequently reads the file's
+extended attributes back, checking values during the process.
diff --git a/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c
new file mode 100644
index 0000000..2cc592f
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author:
+ * Alexey Kodanev <alexey.kodanev@oracle.com>
+ *
+ * Test checks following preconditions:
+ * since Linux kernel 3.7 it is possible to set extended attributes
+ * to cgroup files.
+ */
+
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "test.h"
+#include "usctest.h"
+#include "safe_macros.h"
+
+char *TCID = "cgroup_xattr";
+
+static const char cgrp_point[]	= "cgroup";
+static const char cgrp_name[]	= "cgrp_test";
+static const char subdir_name[]	= "test";
+
+struct tst_key {
+	const char *name;
+	int good;
+};
+
+/* only security.* & trusted.* are valid key names */
+static const struct tst_key tkeys[] = {
+	{ .name = "trusted.test",	.good = 1,	},
+	{ .name = "security.",		.good = 1,	},
+	{ .name = "user.",		.good = 0,	},
+	{ .name = "system.",		.good = 0,	},
+};
+
+#define DEFAULT_VALUE_SIZE	8
+
+/* struct to store key's value */
+struct tst_val {
+	char *buf;
+	size_t size;
+};
+static struct tst_val val;
+
+/* it fills value's buffer */
+static char id;
+
+/* cleanup flags */
+static int cgrp_mounted;
+static int subdir_created;
+
+/*
+ * When test breaks, all open dirs should be closed
+ * otherwise umount won't succeed
+ */
+#define MAX_OPEN_DIR		32
+static DIR *odir[MAX_OPEN_DIR];
+static int odir_num;
+
+/* test options */
+static char *narg;
+static int nflag;
+static int skip_cleanup;
+static int verbose;
+static const option_t options[] = {
+	{"n:", &nflag, &narg},
+	{"s", &skip_cleanup, NULL},
+	{"v", &verbose, NULL},
+	{NULL, NULL, NULL}
+};
+
+static void help(void);
+static void setup(int argc, char *argv[]);
+static void test_run(void);
+static void cleanup(void);
+
+static int set_xattrs(const char *file);
+static int get_xattrs(const char *file);
+/*
+ * set or get xattr recursively
+ *
+ * @path: start directory
+ * @xattr_operation: can be set_xattrs() or get_xattrs()
+ */
+static int cgrp_files_walking(const char *path,
+	int (*xattr_operation)(const char *));
+
+int main(int argc, char *argv[])
+{
+	setup(argc, argv);
+
+	test_run();
+
+	cleanup();
+
+	tst_exit();
+}
+
+static void help(void)
+{
+	printf("  -n x    Write x bytes to xattr value, default is %d\n",
+		DEFAULT_VALUE_SIZE);
+	printf("  -s      Skip cleanup\n");
+	printf("  -v      Verbose\n");
+}
+
+void setup(int argc, char *argv[])
+{
+	char *msg;
+	msg = parse_opts(argc, argv, options, help);
+	if (msg != NULL)
+		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+
+	tst_require_root(NULL);
+
+	if (access("/proc/cgroups", F_OK) == -1)
+		tst_brkm(TCONF, NULL, "Kernel doesn't support for cgroups");
+
+	if (tst_kvercmp(3, 7, 0) < 0) {
+		tst_brkm(TCONF, NULL,
+			"Test must be run with kernel 3.7 or newer");
+	}
+
+	int value_size = DEFAULT_VALUE_SIZE;
+	if (nflag) {
+		if (sscanf(narg, "%i", &value_size) != 1)
+			tst_brkm(TBROK, NULL, "-n option arg is not a number");
+		if (value_size <= 0)
+			tst_brkm(TBROK, NULL, "-n option arg is less than 1");
+	}
+
+	/* initialize test value */
+	val.size = value_size;
+	val.buf = SAFE_MALLOC(NULL, value_size);
+
+	tst_sig(FORK, DEF_HANDLER, cleanup);
+
+	tst_tmpdir();
+
+	SAFE_MKDIR(cleanup, cgrp_point, 0755);
+
+	/* mount all available subsystems (cpu, cpuset, memory, ...) */
+	if (mount(cgrp_name, cgrp_point, "cgroup", 0, "xattr") == -1)
+		tst_brkm(TBROK, cleanup, "Can't mount: %s", cgrp_point);
+	cgrp_mounted = 1;
+
+	/* create new hierarchy */
+	SAFE_CHDIR(cleanup, cgrp_point);
+	SAFE_MKDIR(cleanup, subdir_name, 0755);
+	subdir_created = 1;
+}
+
+static void test_run(void)
+{
+	/* set xattr to each file in cgroup fs */
+	int set_res = cgrp_files_walking(".", set_xattrs);
+	/* reset value */
+	id = 0;
+	/* get & check xattr */
+	int get_res = cgrp_files_walking(".", get_xattrs);
+
+	/* final results */
+	tst_resm(TINFO, "All test-cases have been completed, summary:");
+	tst_resm(TINFO, "Set tests result: %s", (set_res) ? "FAIL" : "PASS");
+	tst_resm(TINFO, "Get tests result: %s", (get_res) ? "FAIL" : "PASS");
+}
+
+static void cleanup(void)
+{
+	if (val.buf != NULL)
+		free(val.buf);
+
+	if (skip_cleanup)
+		return;
+
+	/*
+	 * Kernels 3.7 can crash while unmounting cgroups with xattr,
+	 * call tst_flush() to make sure all buffered data written
+	 * before it happens
+	 */
+	tst_flush();
+
+	int i;
+	for (i = 0; i < odir_num; ++i) {
+		if (closedir(odir[i]) == -1)
+			tst_brkm(TBROK, NULL, "Failed to close dir\n");
+	}
+
+	char *cwd = get_tst_tmpdir();
+	SAFE_CHDIR(NULL, cwd);
+	free(cwd);
+
+	if (subdir_created) {
+		SAFE_CHDIR(NULL, cgrp_point);
+		if (rmdir(subdir_name) == -1)
+			tst_brkm(TBROK | TERRNO, NULL, "Can't remove dir");
+		SAFE_CHDIR(NULL, "..");
+	}
+
+	if (cgrp_mounted) {
+		if (umount(cgrp_point) == -1) {
+			tst_brkm(TBROK | TERRNO, NULL,
+				"Can't unmount: %s", cgrp_point);
+		}
+	}
+
+	tst_rmdir();
+	TEST_CLEANUP;
+}
+
+static int set_xattrs(const char *file)
+{
+	int i, err, fail, res;
+	res = 0;
+	for (i = 0; i < ARRAY_SIZE(tkeys); ++i) {
+		err = setxattr(file, tkeys[i].name,
+			(const void *)val.buf, val.size, 0) == -1;
+
+		fail = err && tkeys[i].good;
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS,
+			"Expect: %s set xattr key '%s' to file '%s'",
+			(tkeys[i].good) ? "can" : "can't",
+			tkeys[i].name, file);
+
+		if (verbose && tkeys[i].good)
+			tst_resm_hexd(TINFO, val.buf, val.size, "value:");
+	}
+	return res;
+}
+
+static int get_xattrs(const char *file)
+{
+	int i, fail, res;
+	res = 0;
+	for (i = 0; i < ARRAY_SIZE(tkeys); ++i) {
+		/* get value size */
+		ssize_t size = getxattr(file, tkeys[i].name, NULL, 0);
+		fail = (size == -1 && tkeys[i].good);
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS,
+			"Expect: %s read xattr %s of file '%s'",
+			(size == -1) ? "can't" : "can",
+			tkeys[i].name, file);
+
+		if (fail || size == -1)
+			continue;
+
+		/* get xattr value */
+		char xval[size];
+		if (getxattr(file, tkeys[i].name, xval, size) == -1) {
+			tst_brkm(TBROK, cleanup,
+				"Can't get buffer of key %s",
+				tkeys[i].name);
+		}
+		fail = val.size != size ||
+			strncmp(val.buf, xval, val.size) != 0;
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS, "Expect: values equal");
+
+		if (verbose && fail) {
+			tst_resm_hexd(TINFO, xval, size,
+				"Read  xattr  value:");
+			tst_resm_hexd(TINFO, val.buf, val.size,
+				"Expect xattr value:");
+		}
+	}
+	return res;
+}
+
+static int cgrp_files_walking(const char *path,
+	int (*xattr_operation)(const char *))
+{
+	int res = 0;
+	struct dirent *entry;
+	DIR *dir = opendir(path);
+
+	odir[odir_num] = dir;
+	if (++odir_num >= MAX_OPEN_DIR) {
+		tst_brkm(TBROK, cleanup,
+			"Unexpected num of open dirs, max: %d", MAX_OPEN_DIR);
+	}
+
+	SAFE_CHDIR(cleanup, path);
+
+	tst_resm(TINFO, "In dir %s", path);
+
+	errno = 0;
+	while ((entry = readdir(dir)) != NULL) {
+		const char *file = entry->d_name;
+		/* skip current and up directories */
+		if (!strcmp(file, "..") || !strcmp(file, "."))
+			continue;
+		struct stat stat_buf;
+		TEST(lstat(file, &stat_buf));
+		if (TEST_RETURN != -1 && S_ISDIR(stat_buf.st_mode)) {
+			/* proceed to subdir */
+			res |= cgrp_files_walking(file, xattr_operation);
+			tst_resm(TINFO, "In dir %s", path);
+		}
+		memset(val.buf, id++, val.size);
+		res |= xattr_operation(file);
+		errno = 0;
+	}
+	if (errno && !entry) {
+		tst_brkm(TWARN | TERRNO, cleanup,
+			"Error while reading dir '%s'", path);
+	}
+	if (closedir(dir) == -1)
+		tst_brkm(TWARN, cleanup, "Failed to close dir '%s'", path);
+	else
+		odir[--odir_num] = NULL;
+
+	if (strcmp(path, "."))
+		SAFE_CHDIR(cleanup, "..");
+	return res;
+}
-- 
1.7.1


------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service 
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_may
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

^ permalink raw reply related	[flat|nested] 15+ messages in thread
* [LTP] [PATCH] New core test of cgroups and extended attributes
@ 2013-05-15  9:40 Alexey Kodanev
  2013-05-15 12:38 ` chrubis
  0 siblings, 1 reply; 15+ messages in thread
From: Alexey Kodanev @ 2013-05-15  9:40 UTC (permalink / raw)
  To: ltp-list; +Cc: vasily.isaenko, Alexey Kodanev

Support of extended attributes in cgroups was added in Linux 3.7.

Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
---
 runtest/controllers                                |    1 +
 .../kernel/controllers/cgroup_xattr/.gitignore     |    1 +
 testcases/kernel/controllers/cgroup_xattr/Makefile |   19 ++
 testcases/kernel/controllers/cgroup_xattr/README   |   25 ++
 .../kernel/controllers/cgroup_xattr/cgroup_xattr.c |  343 ++++++++++++++++++++
 5 files changed, 389 insertions(+), 0 deletions(-)
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/.gitignore
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/Makefile
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/README
 create mode 100644 testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c

diff --git a/runtest/controllers b/runtest/controllers
index b78d828..94fc185 100644
--- a/runtest/controllers
+++ b/runtest/controllers
@@ -12,3 +12,4 @@ memcg_stress		memcg_stress_test.sh
 memcg_control		PAGESIZE=$(mem_process -p);memcg_control_test.sh $PAGESIZE $PAGESIZE $((PAGESIZE * 2))
 cgroup_fj	run_cgroup_test_fj.sh
 controllers	test_controllers.sh
+cgroup_xattr	cgroup_xattr
diff --git a/testcases/kernel/controllers/cgroup_xattr/.gitignore b/testcases/kernel/controllers/cgroup_xattr/.gitignore
new file mode 100644
index 0000000..3664cc9
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/.gitignore
@@ -0,0 +1 @@
+/cgroup_xattr
diff --git a/testcases/kernel/controllers/cgroup_xattr/Makefile b/testcases/kernel/controllers/cgroup_xattr/Makefile
new file mode 100644
index 0000000..cd49588
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/Makefile
@@ -0,0 +1,19 @@
+# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/controllers/cgroup_xattr/README b/testcases/kernel/controllers/cgroup_xattr/README
new file mode 100644
index 0000000..cbec077
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/README
@@ -0,0 +1,25 @@
+TEST SUITE:
+
+The directory cgroup_xattr contains the tests related to extended
+attributes in cgroup filesystem.
+
+WARNING:
+
+This test can cause a kernel panic due to a bug in kernels prior to 3.8.
+It was fixed by kernel upstream commit
+712317ad97f41e738e1a19aa0a6392a78a84094e:
+
+"We should store file xattrs in struct cfent instead of struct cftype,
+because cftype is a type while cfent is object instance of cftype."
+
+TESTS AIM:
+
+The aim of the tests is to check the extended attributes in cgroup
+filesystem. This feature was added in Linux 3.7 to allow attaching runtime
+meta information to cgroups and everything they model (services, apps, vms)
+and can easily be shared among applications.
+
+Test creates all available subsystems (cpu, cpuset, memory, ...) in the
+cgroup root directory and in one more created hierarchy. Then sets extended
+attributes to all files and subsequently reads the file's extended attributes
+back, checking values during the process.
diff --git a/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c
new file mode 100644
index 0000000..0425ae1
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author:
+ * Alexey Kodanev <alexey.kodanev@oracle.com>
+ *
+ * Test checks following preconditions:
+ * since Linux kernel 3.7 it is possible to set extended attributes
+ * to cgroup files.
+ */
+
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "test.h"
+#include "usctest.h"
+#include "safe_macros.h"
+
+char *TCID = "cgroup_xattr";
+
+static const char cgrp_point[]	= "/sys/fs/cgroup";
+static const char cgrp_name[]	= "cgrp_test";
+static const char subdir_name[]	= "test";
+
+struct tst_key {
+	const char *name;
+	int good;
+};
+
+/* only security.* & trusted.* is valid key names */
+static const struct tst_key tkeys[] = {
+	{ .name = "trusted.test",	.good = 1,	},
+	{ .name = "security.",		.good = 1,	},
+	{ .name = "user.",		.good = 0,	},
+	{ .name = "system.",		.good = 0,	},
+};
+
+#define VALUE_SIZE	8
+
+/*
+ * values that can be written to xattr keys,
+ * their can be anything
+ */
+struct tst_val {
+	char buf[VALUE_SIZE];
+	size_t size;
+};
+
+/* cleanup flags */
+static int cgrp_mounted;
+static int subdir_created;
+
+/* test options */
+static int skip_cleanup;
+static int verbose;
+static const option_t options[] = {
+	{"s", &skip_cleanup, NULL},
+	{"v", &verbose, NULL},
+	{NULL, NULL, NULL}
+};
+
+/* save to change back in the end */
+static char start_work_dir[PATH_MAX];
+
+static void help(void);
+static void setup(int argc, char *argv[]);
+static void test_run(void);
+static void cleanup(void);
+
+static int set_xattrs(const char *file, const struct tst_val *val);
+static char *get_xattr(const char *file, const char *key_name, size_t *size);
+static int get_xattrs(const char *file, const struct tst_val *val);
+/*
+ * set or get xattr recursively
+ *
+ * @path: start directory
+ * @id: start char to fill in value
+ * @xattr_operation: can be set_xattrs() or get_xattrs()
+ */
+static int cgrp_files_walking(const char *path, char *id,
+	int (*xattr_operation)(const char *, const struct tst_val *));
+static char *get_hex_value(const char *value, size_t size);
+static void fill_test_value(char *id, struct tst_val *val);
+
+
+int main(int argc, char *argv[])
+{
+	setup(argc, argv);
+
+	test_run();
+
+	cleanup();
+
+	tst_exit();
+}
+
+static void help(void)
+{
+	printf("  -s      Skip cleanup\n");
+	printf("  -v      Verbose\n");
+}
+
+void setup(int argc, char *argv[])
+{
+	char *msg;
+	msg = parse_opts(argc, argv, options, help);
+	if (msg != NULL)
+		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+
+	tst_require_root(NULL);
+
+	if (access("/proc/cgroups", F_OK) == -1)
+		tst_brkm(TCONF, cleanup, "Kernel doesn't support for cgroups");
+
+	if (tst_kvercmp(3, 7, 0) < 0) {
+		tst_brkm(TCONF, cleanup,
+			"Test must be run with kernel 3.7 or newer");
+	}
+
+	tst_sig(FORK, DEF_HANDLER, cleanup);
+
+	/* mount all available subsystems (cpu, cpuset, memory, ...) */
+	if (mount(cgrp_name, cgrp_point, "cgroup", 0, "xattr") == -1)
+		tst_brkm(TBROK, cleanup, "Can't mount: %s", cgrp_point);
+	cgrp_mounted = 1;
+
+	/* save current working directory */
+	SAFE_GETCWD(cleanup, start_work_dir, PATH_MAX);
+	SAFE_CHDIR(cleanup, cgrp_point);
+
+	/* create new hierarchy */
+	SAFE_MKDIR(cleanup, subdir_name, 0755);
+	subdir_created = 1;
+}
+
+static void test_run()
+{
+	char id;
+	/* set xattr to each file in cgroup fs */
+	id = 0;
+	int set_res = cgrp_files_walking(cgrp_point, &id, set_xattrs);
+
+	/* get & check xattr from each file in cgroup fs */
+	id = 0;
+	int get_res = cgrp_files_walking(cgrp_point, &id, get_xattrs);
+
+	/* final results */
+	tst_resm(TINFO, "All test-cases have been completed, summary:");
+	tst_resm(TINFO, "Set tests result: %s", (set_res) ? "FAIL" : "PASS");
+	tst_resm(TINFO, "Get tests result: %s", (get_res) ? "FAIL" : "PASS");
+}
+
+static void cleanup(void)
+{
+	if (skip_cleanup)
+		return;
+
+	fflush(stdout);
+
+	if (subdir_created) {
+		SAFE_CHDIR(NULL, cgrp_point);
+		if (rmdir(subdir_name) == -1) {
+			tst_brkm(TBROK, NULL, "Can't remove dir, error: %s",
+				strerror(errno));
+		}
+	}
+
+	if (strlen(start_work_dir) > 0)
+		SAFE_CHDIR(NULL, start_work_dir);
+
+	if (cgrp_mounted) {
+		if (umount(cgrp_point) == -1)
+			tst_brkm(TBROK, NULL, "Can't unmount: %s", cgrp_point);
+	}
+
+	TEST_CLEANUP;
+}
+
+static int set_xattrs(const char *file, const struct tst_val *val)
+{
+	int i, res;
+	res = 0;
+	for (i = 0; i < ARRAY_SIZE(tkeys); ++i) {
+		int good = setxattr(file, tkeys[i].name,
+			(const void *)val->buf, val->size, 0) != -1;
+
+		int fail = good != tkeys[i].good;
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS,
+			"Expect: %s set xattr key '%s' to file '%s'",
+			(tkeys[i].good) ? "can" : "can't",
+			tkeys[i].name, file);
+
+		if (verbose && tkeys[i].good) {
+			char *rval = get_hex_value(val->buf, val->size);
+			tst_resm(TINFO, "value =%s", rval);
+			free(rval);
+		}
+	}
+	return res;
+}
+
+static char *get_xattr(const char *file, const char *key_name, size_t *size)
+{
+	char *xval = NULL;
+	/* get value size */
+	ssize_t xval_size = getxattr(file, key_name, (void *)xval, 0);
+	if (xval_size == -1)
+		return NULL;
+
+	xval = SAFE_MALLOC(cleanup, xval_size);
+
+	if (getxattr(file, key_name, (void *)xval, xval_size) == -1) {
+		free(xval);
+		return NULL;
+	}
+	*size = xval_size;
+	return xval;
+}
+
+static int get_xattrs(const char *file, const struct tst_val *val)
+{
+	int i, fail, res;
+	res = 0;
+	for (i = 0; i < ARRAY_SIZE(tkeys); ++i) {
+		size_t xval_size = 0;
+		char *xval;
+
+		xval = get_xattr(file, tkeys[i].name, &xval_size);
+		fail = (xval == NULL && tkeys[i].good);
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS,
+			"Expect: %s read xattr %s of file '%s'",
+			(xval == NULL) ? "can't" : "can", tkeys[i].name, file);
+		if (xval == NULL)
+			continue;
+
+		if (fail) {
+			free(xval);
+			continue;
+		}
+
+		fail |= val->size != xval_size ||
+			strncmp(val->buf, xval, val->size) != 0;
+		res |= fail;
+
+		tst_resm((fail) ? TFAIL : TPASS, "Expect: values equal");
+
+		if (verbose && fail) {
+			char *rval = get_hex_value(xval, xval_size);
+			tst_resm(TINFO, "Read xattr value:%s", rval);
+			free(rval);
+			char *cval = get_hex_value(val->buf, val->size);
+			tst_resm(TINFO, "Expected   value:%s", cval);
+			free(cval);
+		}
+		free(xval);
+	}
+	return res;
+}
+
+static int cgrp_files_walking(const char *path, char *id,
+	int (*xattr_operation)(const char *, const struct tst_val *))
+{
+	int res = 0;
+	struct dirent *entry;
+	DIR *dir;
+	dir = opendir(path);
+	SAFE_CHDIR(cleanup, path);
+	tst_resm(TINFO, "In dir %s", path);
+	errno = 0;
+	while ((entry = readdir(dir)) != NULL) {
+		const char *file = entry->d_name;
+		/* skip current and up directories */
+		if (!strcmp(file, "..") || !strcmp(file, "."))
+			continue;
+
+		struct stat stat_buf;
+		TEST(lstat(file, &stat_buf));
+		if (TEST_RETURN != -1 && S_ISDIR(stat_buf.st_mode)) {
+			/* proceed to subdir */
+			res |= cgrp_files_walking(file, id, xattr_operation);
+			/* change directory back */
+			SAFE_CHDIR(cleanup, "..");
+			tst_resm(TINFO, "In dir %s", path);
+		}
+		struct tst_val val;
+		fill_test_value(id, &val);
+		res |= xattr_operation(file, &val);
+		errno = 0;
+	}
+	if (errno && !entry)
+		tst_brkm(TWARN, cleanup, "%s", strerror(errno));
+	if (closedir(dir) == -1)
+		tst_brkm(TWARN, cleanup, "Failed to close dir '%s'", path);
+
+	return res;
+}
+
+static char *get_hex_value(const char *value, size_t size)
+{
+	const size_t symb_num = 5; /* space + 0xXX*/
+	char *buf = SAFE_MALLOC(cleanup, size * symb_num + 1);
+	size_t i;
+	for (i = 0; i < size; ++i) {
+		sprintf(buf + i * symb_num, " 0x%02X",
+			(unsigned char) *(value++));
+	}
+	return buf;
+}
+
+static void fill_test_value(char *id, struct tst_val *val)
+{
+	int i;
+	for (i = 0; i < VALUE_SIZE; ++i)
+		val->buf[i] = *id;
+	val->size = VALUE_SIZE;
+	++(*id);
+}
-- 
1.7.1


------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2013-05-30 18:54 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-22 10:24 [LTP] [PATCH] New core test of cgroups and extended attributes Alexey Kodanev
2013-05-22 14:26 ` chrubis
  -- strict thread matches above, loose matches on Subject: below --
2013-05-29 10:28 Alexey Kodanev
2013-05-30 18:55 ` chrubis
2013-05-24 12:20 Alexey Kodanev
2013-05-28 14:37 ` chrubis
     [not found]   ` <51A4C663.7010506@oracle.com>
2013-05-28 15:43     ` chrubis
2013-05-23 16:28 Alexey Kodanev
2013-05-23  7:09 Alexey Kodanev
2013-05-23 13:31 ` chrubis
2013-05-15  9:40 Alexey Kodanev
2013-05-15 12:38 ` chrubis
     [not found]   ` <51939CB6.3020808@oracle.com>
2013-05-15 14:56     ` chrubis
     [not found]       ` <5194838B.2060104@oracle.com>
2013-05-16  8:39         ` chrubis
     [not found]           ` <5194A887.3010204@oracle.com>
2013-05-16 10:06             ` chrubis

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.