All of lore.kernel.org
 help / color / mirror / Atom feed
* [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; 17+ 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] 17+ messages in thread

* Re: [LTP] [PATCH] New core test of cgroups and extended attributes
  2013-05-24 12:20 [LTP] [PATCH] New core test of cgroups and extended attributes Alexey Kodanev
@ 2013-05-28 14:37 ` chrubis
       [not found]   ` <51A4C663.7010506@oracle.com>
  0 siblings, 1 reply; 17+ messages in thread
From: chrubis @ 2013-05-28 14:37 UTC (permalink / raw)
  To: Alexey Kodanev; +Cc: vasily.isaenko, ltp-list

Hi!
> +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");
                                                     ^         ^
				               Either add have here or
					       remove the for

> +	/* 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, "..");
> +	}

I would keep the mounting code in the function that parses the cgroups
proc file, that way we can have simple:

	if (!mount_cgroups())
		tst_brkm(TBROK, cleanup, "Nothing mounted");

in the setup and keep all the details in the function.

> +	if (!any_mounted)
> +		tst_brkm(TBROK, cleanup, "Mounted nothing");

This should be TCONF.

> +}
> +
> +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;

I would keep these at one line, which would save vertical space, but
that is purely cosmetic change.

> +	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 */

Remove the /* end of workaround */ please.

> +		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) {

                Could also be if (cgrp_opt[i].opt[0] == '\0') {
		(or something similar)

> +			strcpy(cgrp_opt[i].opt, "xattr");
> +			len = strlen(cgrp_opt[i].opt);

                        len == 5 in this case ;)

> +		}
> +
> +		sprintf(cgrp_opt[i].opt + len, ",%s", name);

So we create a list of subsystem by hierarchy here, and try to mount
them with xattr later?

Ah but due to bug in kernel (hier == 0 when we got to this part) we end
up only with these that are not mounted at the moment, right?

That looks OK. Hopefully the kernel gets fixed. Will the kernel support
mouting the subsystems with additional xattr flags or will the mount
return an error (on my machine all mounted subsystems are mounted
without xattr)?

> +	}
> +	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);
> +	}
> +}
> +


-- 
Cyril Hrubis
chrubis@suse.cz

------------------------------------------------------------------------------
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	[flat|nested] 17+ messages in thread

* Re: [LTP] [PATCH] New core test of cgroups and extended attributes
       [not found]   ` <51A4C663.7010506@oracle.com>
@ 2013-05-28 15:43     ` chrubis
       [not found]       ` <51A5E74C.5000002@oracle.com>
  0 siblings, 1 reply; 17+ messages in thread
From: chrubis @ 2013-05-28 15:43 UTC (permalink / raw)
  To: alexey.kodanev; +Cc: vasily.isaenko, ltp-list

Hi!
> > So we create a list of subsystem by hierarchy here, and try to mount
> > them with xattr later?
> That's right
> > Ah but due to bug in kernel (hier == 0 when we got to this part) we end
> > up only with these that are not mounted at the moment, right?
> Yes
> > That looks OK. Hopefully the kernel gets fixed. Will the kernel support
> > mouting the subsystems with additional xattr flags or will the mount
> > return an error (on my machine all mounted subsystems are mounted
> > without xattr)?
> >
> It's difficult to say, for now, we have a recent upstream commit 
> <http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=873fe09ea5df6ccf6bb34811d8c9992aacb67598> 
> in which new cgroup mount option introduced (__DEVEL__sane_behavior). It 
> can be used to get mount error. Developer says that this bug is a part 
> of largerbreakage - cgroup silently ignores mount option changes 
> whenremounted. He thinks that fixing only this part is not meaningful, 
> suggesting to add warning message if the mount options mismatch.

OK. Lets get keep the test as it is now. We will fix it later, once the
kernel devs figure out their solution.

-- 
Cyril Hrubis
chrubis@suse.cz

------------------------------------------------------------------------------
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	[flat|nested] 17+ messages in thread

* Re: [LTP] Device firmware loading test
       [not found]       ` <51A5E74C.5000002@oracle.com>
@ 2013-05-30 11:07         ` chrubis
       [not found]           ` <51A747E8.7070105@oracle.com>
  0 siblings, 1 reply; 17+ messages in thread
From: chrubis @ 2013-05-30 11:07 UTC (permalink / raw)
  To: alexey.kodanev; +Cc: Vasily Isaenko, ltp-list

Hi!
> I'm developing a test of device firmware loading (after 3.7 it can be 
> loaded directly or as usual), but I'm not sure under which ltp directory 
> it should be placed. Is it OK if I use two locations as described below?
> 
> .../testcases/kernel/device-drivers/firmware/fw_load_kernel/fw_load.ko - 
> kernel space part (calls request_firmware with specified parameters), and
>
> .../testcases/kernel/device-drivers/firmware/fw_load_user/fw_load - user 
> space part (creates firmware files, replaces udev's firmware searched 
> paths, loads the module, prints results...).

The problem with device-drivers directory is that the code there is
broken (unmaintained since 2009 or so) and the make (from the top
directory) doesn't go there. It should be cleaned/removed/fixed but
nobody had time to look at the tests and decide what to do with them.

Otherwise the destination fits well enough.

And there is another problem with building kernel modules, I think that
we don't have any configure checks to find out if kernel-devel is
installed (i.e. /lib/modules/$(version)/build/ exists) and which kernel
version to use, etc. But this part shouldn't be that hard.

-- 
Cyril Hrubis
chrubis@suse.cz

------------------------------------------------------------------------------
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	[flat|nested] 17+ messages in thread

* Re: [LTP] Device firmware loading test
       [not found]           ` <51A747E8.7070105@oracle.com>
@ 2013-05-30 13:13             ` chrubis
  0 siblings, 0 replies; 17+ messages in thread
From: chrubis @ 2013-05-30 13:13 UTC (permalink / raw)
  To: alexey.kodanev; +Cc: Vasily Isaenko, ltp-list

Hi!
> > The problem with device-drivers directory is that the code there is
> > broken (unmaintained since 2009 or so) and the make (from the top
> > directory) doesn't go there. It should be cleaned/removed/fixed but
> > nobody had time to look at the tests and decide what to do with them.
> >
> > Otherwise the destination fits well enough.
> As I understand from README file in that directory, these tests should 
> not be run automatically. It explains why make doesn't go there. But the 
> firmware loading test can be (preferably should be) run automatically. 
> That way, may be change directory to .../testcases/kernel/firmware?

Hmm, so the test tests userspace API for firmware loading but needs
helper kernel module, am I right?. In that case kernel/firmware/ should
be ok as well.

-- 
Cyril Hrubis
chrubis@suse.cz

------------------------------------------------------------------------------
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	[flat|nested] 17+ messages in thread

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

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

Pushed after removing trailing whitespace from the Makefile, thanks.

-- 
Cyril Hrubis
chrubis@suse.cz

------------------------------------------------------------------------------
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	[flat|nested] 17+ 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; 17+ 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] 17+ messages in thread

* [LTP] [PATCH] New core test of cgroups and extended attributes
@ 2013-05-23 16:28 Alexey Kodanev
  0 siblings, 0 replies; 17+ 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] 17+ messages in thread

* Re: [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, 0 replies; 17+ messages in thread
From: chrubis @ 2013-05-23 13:31 UTC (permalink / raw)
  To: Alexey Kodanev; +Cc: vasily.isaenko, ltp-list

Hi!
> Support of extended attributes in cgroups was added in Linux 3.7.

I've tried to run the test on my machine where cgroups are allready
mounted to /sys/fs/cgroup (which seems to be the case for modern
distributions). In such situation the mount in the test fails with
EBUSY. I looks like the root hierarchy can be mounted only once. Now we
cannot unmout the /sys/fs/cgroup as this one is used by the system.

But it looks like we can mount each of the controllers, i.e.

for each controller:
	mkdir /path/type
	mount -t cgroup -o type type /path/type

So the options are either to use the /sys/fs/cgroup directory or mount
each controller one by one.

What do you think?

-- 
Cyril Hrubis
chrubis@suse.cz

------------------------------------------------------------------------------
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	[flat|nested] 17+ 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; 17+ 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] 17+ messages in thread

* Re: [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, 0 replies; 17+ messages in thread
From: chrubis @ 2013-05-22 14:26 UTC (permalink / raw)
  To: Alexey Kodanev; +Cc: vasily.isaenko, ltp-list

Hi!
> Support of extended attributes in cgroups was added in Linux 3.7.
> +		/* get xattr value */
> +		char xval[size];
> +		if (getxattr(file, tkeys[i].name, (void *)xval, size) == -1) {

The conversion from char * to void * should be automatic so the cast to
(void *) shouldn't be needed, or not?


The rest if fine. Waiting for resping of the tst_resm_hexd() patch
before aplying this one.

-- 
Cyril Hrubis
chrubis@suse.cz

------------------------------------------------------------------------------
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	[flat|nested] 17+ messages in thread

* [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; 17+ 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] 17+ messages in thread

* Re: [LTP] [PATCH] New core test of cgroups and extended attributes
       [not found]           ` <5194A887.3010204@oracle.com>
@ 2013-05-16 10:06             ` chrubis
  0 siblings, 0 replies; 17+ messages in thread
From: chrubis @ 2013-05-16 10:06 UTC (permalink / raw)
  To: alexey.kodanev; +Cc: vasily.isaenko, ltp-list

Hi!
> >> Since we're going to print buf in hex, may be we can use
> >> tst_resm_hex(flags, buf, buf_len, fmt, ...) to make it more descriptive?
> > Naming things right is hard. I agree that 'hex' should be part of the
> > name but ideally something like 'dump' or 'buf' should be there as well
> > at least in form of the first letter (to keep the name reasonably short).
> >
> > tst_resm_bhex() or tst_resm_dhex() ?
> >
> tst_resm_hexd()? to make name similar to hexdump and od utilities.

Sounds good.

-- 
Cyril Hrubis
chrubis@suse.cz

------------------------------------------------------------------------------
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	[flat|nested] 17+ messages in thread

* Re: [LTP] [PATCH] New core test of cgroups and extended attributes
       [not found]       ` <5194838B.2060104@oracle.com>
@ 2013-05-16  8:39         ` chrubis
       [not found]           ` <5194A887.3010204@oracle.com>
  0 siblings, 1 reply; 17+ messages in thread
From: chrubis @ 2013-05-16  8:39 UTC (permalink / raw)
  To: alexey.kodanev; +Cc: vasily.isaenko, ltp-list

Hi!
> > I do not want to add custom printf() format strings on purpose, as that
> > would:
> >
> > 1) create confusion
> >
> > 2) possibly break the checks on the format done by compiler
> >
> > Anybody else has better idea?
> Since we're going to print buf in hex, may be we can use
> tst_resm_hex(flags, buf, buf_len, fmt, ...) to make it more descriptive?

Naming things right is hard. I agree that 'hex' should be part of the
name but ideally something like 'dump' or 'buf' should be there as well
at least in form of the first letter (to keep the name reasonably short).

tst_resm_bhex() or tst_resm_dhex() ?

-- 
Cyril Hrubis
chrubis@suse.cz

------------------------------------------------------------------------------
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	[flat|nested] 17+ messages in thread

* Re: [LTP] [PATCH] New core test of cgroups and extended attributes
       [not found]   ` <51939CB6.3020808@oracle.com>
@ 2013-05-15 14:56     ` chrubis
       [not found]       ` <5194838B.2060104@oracle.com>
  0 siblings, 1 reply; 17+ messages in thread
From: chrubis @ 2013-05-15 14:56 UTC (permalink / raw)
  To: alexey.kodanev; +Cc: vasily.isaenko, ltp-list

Hi!
> > What is this fflush() for?
> >
> kernels 3.7 can crash while unmounting cgroups with xattr,
> so just to make sure all buffered data written before it happens

Ok, let's add simlilar comment to the code as well.

And it would be better to call tst_flush() as you are using tst_resm()
interface.

> > This function is too ugly. You should rather do something like
> > print_xattr() that would both preprare the string and call the
> > tst_resm() so that you don't need to pass allocated buffers around.
> >
> > void print_xattr(const char *msg, const char *val, size_t size)
> > {
> > 	char buf[size + sybm_num + 1];
> > 	...
> >
> > 	tst_resm(TINFO, "%s%s", msg, buf);
> > }
> >
> > Or we can create a tst_xxx function to print a buffer of bytes, I guess
> > that there are more cases where such function could be used. But that
> > would require a little more work to desing the interface right.
> >
> I agree, let's do that

Ok, lets address that in separate patch. I would go for simple function
that would take prefix in printf() format and would dump the hex values
after that. Something like tst_resm_buf(flags, buf, buf_len, fmt, ...)
but perhaps we can come up with better name and/or API.

I do not want to add custom printf() format strings on purpose, as that
would:

1) create confusion

2) possibly break the checks on the format done by compiler

Anybody else has better idea?

> >> +static void fill_test_value(char *id, struct tst_val *val)
> >> +{
> >> +	int i;
> >> +	for (i = 0; i<  VALUE_SIZE; ++i)
> >> +		val->buf[i] = *id;
> > What about using memset()?
> Ok :) further may be remove this function completely and just use memset 
> instead?

Sounds good.

> > What about just defining the id in the walk functions and incrementing
> > it each time fill_test_value() was called?
> >
> The point is to make unique key's values among all hierarchies (there 
> was a bug when files with the same name share the same struct)
> Would it be better to use global id that is incrementing each time when 
> fill_test_value() called,
> and resetting to init value between set and get walk functions?

Global id sounds better to me.

-- 
Cyril Hrubis
chrubis@suse.cz

------------------------------------------------------------------------------
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	[flat|nested] 17+ messages in thread

* Re: [LTP] [PATCH] New core test of cgroups and extended attributes
  2013-05-15  9:40 Alexey Kodanev
@ 2013-05-15 12:38 ` chrubis
       [not found]   ` <51939CB6.3020808@oracle.com>
  0 siblings, 1 reply; 17+ messages in thread
From: chrubis @ 2013-05-15 12:38 UTC (permalink / raw)
  To: Alexey Kodanev; +Cc: vasily.isaenko, ltp-list

Hi!
> +++ 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 */
                                  ^ are
> +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
      ^ their value?
> + */
> +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);

Here we mount cgroups under /sys/fs/cgroup which later causes problems
as you need to switch to another directory to unmount.

I'm not that much familiar with cgroups, is mounting it to /sys/
required or is it customary? Wouldn't that interfere with rest of the
system?

What about calling tst_tmpdir(), creating a directory to mount the
cgroups there and then simply doing chdir to test temporary directory
before the unmount. Would that work?

> +	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()

void in params is missing

> +{
> +	char id;
> +	/* set xattr to each file in cgroup fs */
> +	id = 0;
> +	int set_res = cgrp_files_walking(cgrp_point, &id, set_xattrs);

Here you are passing pointer to the value, modify it by the function but
never use the resulting value.

> +	/* 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);

What is this fflush() for?

> +	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);
	
	Pass NULL here, instead of the xval initialized to NULL.

> +	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));

Use TERRNO and also describe the warning more verbosely.

> +	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;
> +}

This function is too ugly. You should rather do something like
print_xattr() that would both preprare the string and call the
tst_resm() so that you don't need to pass allocated buffers around.

void print_xattr(const char *msg, const char *val, size_t size)
{
	char buf[size + sybm_num + 1];
	...

	tst_resm(TINFO, "%s%s", msg, buf);
}

Or we can create a tst_xxx function to print a buffer of bytes, I guess
that there are more cases where such function could be used. But that
would require a little more work to desing the interface right.

> +static void fill_test_value(char *id, struct tst_val *val)
> +{
> +	int i;
> +	for (i = 0; i < VALUE_SIZE; ++i)
> +		val->buf[i] = *id;

What about using memset()?

> +	val->size = VALUE_SIZE;
> +	++(*id);

This is quite cryptic, why aren't you modifying the id in the loop that
calls this function?

What about just defining the id in the walk functions and incrementing
it each time fill_test_value() was called?

> +}

-- 
Cyril Hrubis
chrubis@suse.cz

------------------------------------------------------------------------------
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	[flat|nested] 17+ 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; 17+ 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] 17+ messages in thread

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

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-24 12:20 [LTP] [PATCH] New core test of cgroups and extended attributes Alexey Kodanev
2013-05-28 14:37 ` chrubis
     [not found]   ` <51A4C663.7010506@oracle.com>
2013-05-28 15:43     ` chrubis
     [not found]       ` <51A5E74C.5000002@oracle.com>
2013-05-30 11:07         ` [LTP] Device firmware loading test chrubis
     [not found]           ` <51A747E8.7070105@oracle.com>
2013-05-30 13:13             ` chrubis
  -- strict thread matches above, loose matches on Subject: below --
2013-05-29 10:28 [LTP] [PATCH] New core test of cgroups and extended attributes Alexey Kodanev
2013-05-30 18:55 ` chrubis
2013-05-23 16:28 Alexey Kodanev
2013-05-23  7:09 Alexey Kodanev
2013-05-23 13:31 ` chrubis
2013-05-22 10:24 Alexey Kodanev
2013-05-22 14:26 ` 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.