[Devel] [PATCH 8/9] cr_tests: fs: Add unlinked fifo test

Matt Helsley matthltc at us.ibm.com
Fri Feb 19 18:18:56 PST 2010


Signed-off-by: Matt Helsley <matthltc at us.ibm.com>
---
 fs/fifo.c    |  190 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/module.mk |    2 +-
 2 files changed, 191 insertions(+), 1 deletions(-)
 create mode 100644 fs/fifo.c

diff --git a/fs/fifo.c b/fs/fifo.c
new file mode 100644
index 0000000..d0e08eb
--- /dev/null
+++ b/fs/fifo.c
@@ -0,0 +1,190 @@
+/*
+ * Test checkpoint/restart of unlinked fifos. fifos are an interesting
+ * case for unlinked file support because they offer limited buffer space
+ * but are not seekable.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+
+/* open() */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* set inode flags */
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+
+/* waitpid() and W* status macros */
+#include <sys/wait.h>
+
+#define LOG_FILE	"log.unlinked.file"
+#include "libfstest.h"
+
+const char *descr = "Create an unlinked file to checkpoint/restore.";
+
+void usage(FILE *pout, const char *prog)
+{
+	fprintf(pout, "\n%s [-L] [-N] [-h|--help] [-l LABEL] [-n NUM]\n"
+"%s\n"
+"\n"
+"\t-L\tPrint the valid LABELs in order and exit.\n"
+"\t-l\tWait for checkpoint at LABEL.\n"
+"\t-N\tPrint the maximum label number and exit.\n"
+"\t-n\tWait for checkpoint at NUM.\n"
+"\t-a\tSet the append-only flag (extX filesystems, needs cap_linux_immutable).\n"
+"\t-i\tSet the immutable flag (extX filesystems, needs cap_linux_immutable).\n"
+"\t-u\tSet the undeleteable (recoverable) flag (extX filesystems).\n"
+"\n"
+"You may only specify one LABEL or NUM and you may not specify both.\n"
+"Label numbers are integers in the range 0-%d\n"
+"Valid label numbers and their corresponding LABELs are:\n", prog,
+		descr, num_labels - 1);
+	print_labels(pout);
+}
+
+const struct option long_options[] = {
+	{ "print-labels",	0, 0, 'L'},
+	{ "print-max-label-no",	0, 0, 'N'},
+	{ "help",		0, 0, 'h'},
+	{ "append",		0, 0, 'a'}, /* Need CAP_LINUX_IMMUTABLE */
+	{ "immutable",		0, 0, 'i'}, /* Need CAP_LINUX_IMMUTABLE */
+	{ "undelete",		0, 0, 'u'}, /* unsupported */
+	{ "label",		1, 0, 'l'},
+	{ "num",		1, 0, 'n'},
+	{0, 0, 0, 0},
+};
+
+static int inode_flags = 0;
+static int oflags = O_RDWR; /* rely on Linux-specific behavior (man 7 fifo) */
+
+void parse_args(int argc, char **argv)
+{
+	ckpt_op_num = num_labels - 1;
+	ckpt_label = labels[ckpt_op_num];
+	while (1) {
+		char c;
+		c = getopt_long(argc, argv, "LNhl:n:aiu", long_options, NULL);
+		if (c == -1)
+			break;
+		switch(c) {
+			case 'L':
+				print_labels(stdout);
+				exit(EXIT_SUCCESS);
+				break;
+			case 'N':
+				printf("%d\n", num_labels - 1);
+				exit(EXIT_SUCCESS);
+				break;
+			case 'h':
+				usage(stdout, argv[0]);
+				exit(EXIT_SUCCESS);
+				break;
+			case 'a':
+				oflags |= O_APPEND;
+				inode_flags |= FS_APPEND_FL;
+				break;
+			case 'i':
+				inode_flags |= FS_IMMUTABLE_FL;
+				break;
+			case 'u':
+				inode_flags |= FS_UNRM_FL;
+				break;
+			case 'l':
+				ckpt_label = optarg;
+				break;
+			case 'n':
+				if ((sscanf(optarg, "%d", &ckpt_op_num) < 1) ||
+				    (ckpt_op_num < 0) ||
+				    (ckpt_op_num >= num_labels)) {
+					fprintf(stderr, "Option -n requires an argument in the range 0-%d. Got %d\n", num_labels - 1, ckpt_op_num);
+					usage(stderr, argv[0]);
+					exit(EXIT_FAILURE);
+				}
+				break;
+			default: /* unknown option */
+				break;
+		}
+	}
+}
+
+static int setflags(int fd)
+{
+	int flags = inode_flags;
+
+	if (!flags)
+		return 0;
+#ifdef FS_IOC_SETFLAGS
+	return ioctl(fd, FS_IOC_SETFLAGS, &flags);
+#else
+	errno = ENOTSUP;
+	return -1;
+#endif
+}
+
+int main (int argc, char **argv)
+{
+	const char *pathname = "trash";
+	const char buffer1[] = "hello world!\n";
+	const char buffer2[] = "goodbye old world, hello new world!\n";
+	char fdcontents1[sizeof(buffer1)];
+	char fdcontents2[sizeof(buffer2)];
+	int fifo1 = -1, fifo2 = -1, ret, op_num = 0;
+
+	parse_args(argc, argv);
+	/* FIXME eventually stdio streams should be harmless */
+	close(0);
+	logfp = fopen(LOG_FILE, "w");
+	if (!logfp) {
+		perror("could not open logfile");
+		exit(1);
+	}
+	dup2(fileno(logfp), 1); /* redirect stdout and stderr to the log file */
+	dup2(fileno(logfp), 2);
+	if (!move_to_cgroup("freezer", "1", getpid())) {
+		log_error("move_to_cgroup");
+		exit(2);
+	}
+
+/* Open a first fifo, write to it, and unlink it */
+label(mkfifo1,   ret, mkfifo(pathname, S_IRUSR|S_IWUSR));
+label(open1,   fifo1, open(pathname, oflags));
+label(setflags1, ret, setflags(fifo1));
+label(write1,    ret, write(fifo1, buffer1, sizeof(buffer1)));
+label(unlink,    ret, unlink(pathname));
+
+/* Open a second fifo, write to it */
+label(mkfifo2,   ret, mkfifo(pathname, S_IRUSR|S_IWUSR));
+label(open2,   fifo2, open(pathname, oflags));
+label(setflags2, ret, setflags(fifo2));
+label(write2,    ret, write(fifo2, buffer2, sizeof(buffer2)));
+
+/* Check fifo contents */
+label(read1,     ret, read(fifo1, fdcontents1, sizeof(fdcontents1)));
+	if (strcmp(buffer1, fdcontents1) != 0) {
+		log("FAIL", "original fifo contents don't match.");
+		ret = EXIT_FAILURE;
+		goto out;
+	}
+label(read2,     ret, read(fifo2, fdcontents2, sizeof(fdcontents2)));
+	if (strcmp(buffer2, fdcontents2) != 0) {
+		log("FAIL", "new fifo contents don't match.");
+		ret = EXIT_FAILURE;
+		goto out;
+	}
+	ret = EXIT_SUCCESS;
+out:
+	if (ret != EXIT_SUCCESS)
+		perror("ERROR");
+	if (fifo1 > -1)
+		close(fifo1);
+	if (fifo2 > -1)
+		close(fifo2);
+	unlink(pathname);
+	fclose(logfp);
+	exit(ret);
+}
diff --git a/fs/module.mk b/fs/module.mk
index 1af5815..8aeaad2 100644
--- a/fs/module.mk
+++ b/fs/module.mk
@@ -1,5 +1,5 @@
 local_dir := fs
-local_progs := $(addprefix $(local_dir)/, file dir do_ckpt)
+local_progs := $(addprefix $(local_dir)/, file dir do_ckpt fifo)
 
 sources += $(addprefix $(local_dir)/,libeptest.c)
 progs += $(local_progs)
-- 
1.6.3.3

_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers




More information about the Devel mailing list