[CRIU] [PATCH 2/3] dump: Add support to flock&posix file locks' dump

Gu Zheng cengku.gu at huawei.com
Wed Nov 7 22:10:25 EST 2012


The crtools does not handle file locks when dumping, so this patch adds a preliminary
support to dump flock&posix file locks used by all the tasks in the same container
when dumping. This can be only used for the container dumping indeed.

Signed-off-by: Zheng Gu <cengku.gu at huawei.com>
---
 Makefile                 |    1 +
 cr-dump.c                |  176 ++++++++++++++++++++++++++++++++++++++++++++++
 cr-show.c                |    5 ++
 file-lock.c              |   15 ++++
 image.c                  |    1 +
 include/crtools.h        |    2 +
 include/file-lock.h      |   30 ++++++++
 include/image.h          |    1 +
 include/protobuf.h       |    1 +
 protobuf.c               |    2 +
 protobuf/Makefile        |    1 +
 protobuf/file-lock.proto |    9 +++
 12 files changed, 244 insertions(+), 0 deletions(-)
 create mode 100644 file-lock.c
 create mode 100644 include/file-lock.h
 create mode 100644 protobuf/file-lock.proto

diff --git a/Makefile b/Makefile
index 5574b8c..ac2a8b6 100644
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,7 @@ OBJS		+= signalfd.o
 OBJS		+= pstree.o
 OBJS		+= protobuf.o
 OBJS		+= tty.o
+OBJS		+= file-lock.o
 
 PROTOBUF-LIB	:= protobuf/protobuf-lib.o
 
diff --git a/cr-dump.c b/cr-dump.c
index b2df6b0..b55321c 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -29,6 +29,7 @@
 #include "protobuf/mm.pb-c.h"
 #include "protobuf/creds.pb-c.h"
 #include "protobuf/core.pb-c.h"
+#include "protobuf/file-lock.pb-c.h"
 
 #include "types.h"
 #include "list.h"
@@ -60,6 +61,7 @@
 #include "tty.h"
 #include "net.h"
 #include "sk-packet.h"
+#include "file-lock.h"
 
 #ifndef CONFIG_X86_64
 # error No x86-32 support yet
@@ -608,6 +610,171 @@ out:
 	return ret;
 }
 
+static int fill_flock_entry(FileLockEntry *fe, const char *fl_flag,
+		const char *fl_type, const char *fl_option)
+{
+	if (!strcmp(fl_flag, "POSIX")) {
+		fe->flag |= FL_POSIX;
+	} else if (!strcmp(fl_flag, "FLOCK")) {
+		fe->flag |= FL_FLOCK;
+	} else {
+		pr_err("Unknow file lock!\n");
+		goto err_out;
+	}
+
+	if (!strcmp(fl_type, "MSNFS")) {
+		fe->type |= LOCK_MAND;
+
+		if (!strcmp(fl_option, "READ")) {
+			fe->type |= LOCK_READ;
+		} else if (!strcmp(fl_option, "RW")) {
+			fe->type |= LOCK_RW;
+		} else if (!strcmp(fl_option, "WRITE")) {
+			fe->type |= LOCK_WRITE;
+		} else {
+			pr_err("unknow lock option!\n");
+			goto err_out;
+		}
+	} else {
+		if (!strcmp(fl_option, "UNLCK")) {
+			fe->type |= F_UNLCK;
+		} else if (!strcmp(fl_option, "WRITE")) {
+			fe->type |= F_WRLCK;
+		} else if (!strcmp(fl_option, "READ")) {
+			fe->type |= F_RDLCK;
+		} else {
+			pr_err("unknow lock option!\n");
+			goto err_out;
+		}
+	}
+	return 0;
+err_out:
+	return -1;
+}
+
+static int get_fd_by_ino(unsigned long i_no, struct parasite_drain_fd *dfds,
+		pid_t pid)
+{
+	int i, ret = -1;
+	char path[PATH_MAX];
+	char buf[40];
+	struct stat fd_stat;
+
+	i = 0;
+	while (i < dfds->nr_fds) {
+		snprintf(buf, sizeof(buf), "/proc/%d/fd/%d", pid,
+				dfds->fds[i]);
+		buf[39] = '\0';
+
+		ret = readlink(buf, path, sizeof(path));
+		if (ret < 0) {
+			pr_err("read link %s failed!\n", buf);
+			goto err_out;
+		}
+
+		if (stat(path, &fd_stat) == -1) {
+			i++;
+			pr_msg("Could not get %s stat!\n", path);
+			continue;
+		}
+
+		if (fd_stat.st_ino == i_no)
+			return dfds->fds[i];
+		i++;
+	}
+err_out:
+	return ret;
+}
+
+static int dump_task_file_locks(struct parasite_ctl *ctl,
+		struct cr_fdset *fdset,	struct parasite_drain_fd *dfds)
+{
+	pid_t pid = ctl->pid;
+	FileLockEntry fe;
+	FILE *fp_locks = NULL;
+	char buf[100];
+
+	long long fl_id = 0;
+	char fl_flag[10], fl_type[15], fl_option[10];
+	pid_t fl_own;
+	int maj, min;
+	unsigned long i_no;
+	long long start;
+	char end[32];
+
+	int num = 0, ret = 0;
+	bool is_block;
+
+	fp_locks = fopen("/proc/locks", "r");
+	if (fp_locks == NULL)
+		return -1;
+
+	while (fgets(buf, sizeof(buf), fp_locks)) {
+		file_lock_entry__init(&fe);
+		is_block = false;
+
+		if (strstr(buf, "->")) {
+			is_block = true;
+			pr_info("There is a blocked lock!\n");
+
+			num = sscanf(buf,
+				"%lld: -> %s %s %s %d %02x:%02x:%ld %lld %s",
+				&fl_id, fl_flag, fl_type, fl_option,
+				&fl_own, &maj, &min, &i_no, &start, end);
+		} else {
+			num = sscanf(buf,
+				"%lld:%s %s %s %d %02x:%02x:%ld %lld %s",
+				&fl_id, fl_flag, fl_type, fl_option,
+				&fl_own, &maj, &min, &i_no, &start, end);
+		}
+
+		if (num < 10) {
+			pr_info("%lld: %s %s %s %s %d %02x:%02x:%ld %lld %s\n",
+				fl_id, is_block ? "->" : "", fl_flag, fl_type,
+				fl_option, fl_own, maj, min, i_no, start, end);
+			continue;
+		}
+
+		if (fl_own == pid) {
+			pr_info("lockinfo: %lld:%s %s %s %s %d %02x:%02x:%ld %lld %s\n",
+				fl_id, is_block ? "->" : "", fl_flag, fl_type,
+				fl_option, fl_own, maj, min, i_no, start, end);
+
+			fe.pid = fl_own;
+
+			ret = fill_flock_entry(&fe, fl_flag, fl_type,
+				fl_option);
+			if (ret < 0) {
+				pr_err("translate file lock cmd failed!\n");
+				goto out;
+			}
+
+			fe.fd = get_fd_by_ino(i_no, dfds, pid);
+			if (fe.fd < 0) {
+				ret = -1;
+				goto out;
+			}
+
+			fe.start = start;
+
+			if (!strncmp(end, "EOF", 3))
+				fe.len = OFFSET_MAX;
+			else
+				fe.len = (atoll(end) + 1) - start;
+
+			ret = dump_one_file_lock(&fe, fdset);
+			if (ret < 0) {
+				pr_err("dump file lock failed!\n");
+				goto out;
+			}
+		}
+	}
+
+out:
+	fclose(fp_locks);
+	return ret;
+}
+
 static int get_task_futex_robust_list(pid_t pid, ThreadCoreEntry *info)
 {
 	struct robust_list_head *head = NULL;
@@ -1564,6 +1731,15 @@ static int dump_one_task(struct pstree_item *item)
 		goto err_cure;
 	}
 
+	if (opts.handle_file_locks) {
+		ret = dump_task_file_locks(parasite_ctl, cr_fdset, dfds);
+		if (ret) {
+			pr_err("Dump file locks (pid: %d) failed with %d\n",
+					pid, ret);
+			goto err_cure;
+		}
+	}
+
 	ret = parasite_dump_pages_seized(parasite_ctl, &vma_area_list, cr_fdset);
 	if (ret) {
 		pr_err("Can't dump pages (pid: %d) with parasite\n", pid);
diff --git a/cr-show.c b/cr-show.c
index 8e88584..05973ce 100644
--- a/cr-show.c
+++ b/cr-show.c
@@ -124,6 +124,11 @@ void show_tty_info(int fd, struct cr_options *o)
 	pb_show_plain(fd, PB_TTY_INFO);
 }
 
+void show_file_locks(int fd, struct cr_options *o)
+{
+	pb_show_plain(fd, PB_FILE_LOCK);
+}
+
 void show_fs(int fd_fs, struct cr_options *o)
 {
 	pb_show_vertical(fd_fs, PB_FS);
diff --git a/file-lock.c b/file-lock.c
new file mode 100644
index 0000000..32d2765
--- /dev/null
+++ b/file-lock.c
@@ -0,0 +1,15 @@
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "crtools.h"
+#include "file-lock.h"
+
+int dump_one_file_lock(FileLockEntry *fe, const struct cr_fdset *fdset)
+{
+	pr_info("flag: %d,type: %d,pid: %d,fd: %d,start: %8lx,len: %8lx\n",
+			fe->flag, fe->type, fe->pid,
+			fe->fd, fe->start, fe->len);
+
+	return pb_write_one(fdset_fd(fdset, CR_FD_FILE_LOCKS),
+			fe, PB_FILE_LOCK);
+}
diff --git a/image.c b/image.c
index f1f93a0..1e778e2 100644
--- a/image.c
+++ b/image.c
@@ -90,6 +90,7 @@ static void show_raw_image(int fd, struct cr_options *opt) {};
 struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
 	FD_ENTRY(INVENTORY,	"inventory",	 show_inventory),
 	FD_ENTRY(FDINFO,	"fdinfo-%d",	 show_files),
+	FD_ENTRY(FILE_LOCKS,	"filelocks-%d",   show_file_locks),
 	FD_ENTRY(PAGES,		"pages-%d",	 show_pages),
 	FD_ENTRY(SHMEM_PAGES,	"pages-shmem-%ld", show_pages),
 	FD_ENTRY(REG_FILES,	"reg-files",	 show_reg_files),
diff --git a/include/crtools.h b/include/crtools.h
index ba9a06d..6d73b3f 100644
--- a/include/crtools.h
+++ b/include/crtools.h
@@ -25,6 +25,7 @@ enum {
 
 	_CR_FD_TASK_FROM,
 	CR_FD_FDINFO,
+	CR_FD_FILE_LOCKS,
 	CR_FD_PAGES,
 	CR_FD_CORE,
 	CR_FD_MM,
@@ -156,6 +157,7 @@ void show_fown_cont(void *p);
 void show_eventfds(int fd, struct cr_options *o);
 void show_tty(int fd, struct cr_options *o);
 void show_tty_info(int fd, struct cr_options *o);
+void show_file_locks(int fd, struct cr_options *o);
 
 int check_img_inventory(void);
 int write_img_inventory(void);
diff --git a/include/file-lock.h b/include/file-lock.h
new file mode 100644
index 0000000..491f637
--- /dev/null
+++ b/include/file-lock.h
@@ -0,0 +1,30 @@
+#include "protobuf.h"
+#include "../protobuf/file-lock.pb-c.h"
+
+#define INT_LIMIT(x)	(~((x)1 << (sizeof(x)*8 - 1)))
+#define OFFSET_MAX	INT_LIMIT(loff_t)
+
+#define FL_POSIX		1
+#define FL_FLOCK		2
+
+#ifndef F_RDLCK
+#define F_RDLCK		0
+#define F_WRLCK		1
+#define F_UNLCK		2
+#endif
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH		1	/* shared lock */
+#define LOCK_EX		2	/* exclusive lock */
+#define LOCK_NB		4	/* or'd with one of the above to prevent
+							blocking */
+#define LOCK_UN		8	/* remove lock */
+
+#define LOCK_MAND		32	/* This is a mandatory flock ... */
+#define LOCK_READ		64	/* which allows concurrent
+					   read operations */
+#define LOCK_WRITE		128	/* which allows concurrent
+					   write operations */
+#define LOCK_RW		192	/* which allows concurrent read & write ops */
+
+extern int dump_one_file_lock(FileLockEntry *fe, const struct cr_fdset *fdset);
diff --git a/include/image.h b/include/image.h
index f4ed3eb..1f9aac7 100644
--- a/include/image.h
+++ b/include/image.h
@@ -61,6 +61,7 @@
 #define NETDEV_MAGIC		0x57373951 /* Yaroslavl */
 #define TTY_MAGIC		0x59433025 /* Pushkin */
 #define TTY_INFO_MAGIC		0x59453036 /* Kolpino */
+#define FILE_LOCKS_MAGIC	0x87654321 /* Town on the Mars */
 
 #define IFADDR_MAGIC		RAW_IMAGE_MAGIC
 #define ROUTE_MAGIC		RAW_IMAGE_MAGIC
diff --git a/include/protobuf.h b/include/protobuf.h
index 52f03f7..6f5f85f 100644
--- a/include/protobuf.h
+++ b/include/protobuf.h
@@ -43,6 +43,7 @@ enum {
 	PB_INOTIFY_WD,
 	PB_TTY,
 	PB_TTY_INFO,
+	PB_FILE_LOCK,
 
 	PB_MAX
 };
diff --git a/protobuf.c b/protobuf.c
index 7f76e13..1abb6e1 100644
--- a/protobuf.c
+++ b/protobuf.c
@@ -49,6 +49,7 @@
 #include "protobuf/netdev.pb-c.h"
 #include "protobuf/tcp-stream.pb-c.h"
 #include "protobuf/tty.pb-c.h"
+#include "protobuf/file-lock.pb-c.h"
 
 typedef size_t (*pb_getpksize_t)(void *obj);
 typedef size_t (*pb_pack_t)(void *obj, void *where);
@@ -125,6 +126,7 @@ void cr_pb_init(void)
 	CR_PB_DESC(PACKETSK,		PacketSock,	packet_sock);
 	CR_PB_DESC(TTY,			TtyFile,	tty_file);
 	CR_PB_DESC(TTY_INFO,		TtyInfo,	tty_info);
+	CR_PB_DESC(FILE_LOCK,		FileLock,	file_lock);
 }
 
 /*
diff --git a/protobuf/Makefile b/protobuf/Makefile
index 6a7f297..a54d024 100644
--- a/protobuf/Makefile
+++ b/protobuf/Makefile
@@ -39,6 +39,7 @@ PROTO_FILES	+= vma.proto
 PROTO_FILES	+= core.proto
 PROTO_FILES	+= netdev.proto
 PROTO_FILES	+= tty.proto
+PROTO_FILES	+= file-lock.proto
 
 PROTO_HDRS	:= $(patsubst %.proto,%.pb-c.h,$(PROTO_FILES))
 PROTO_SRCS	:= $(patsubst %.proto,%.pb-c.c,$(PROTO_FILES))
diff --git a/protobuf/file-lock.proto b/protobuf/file-lock.proto
new file mode 100644
index 0000000..c8ec987
--- /dev/null
+++ b/protobuf/file-lock.proto
@@ -0,0 +1,9 @@
+message file_lock_entry {
+	required uint32 		flag  = 1;
+	required uint32 		type  = 2;
+	required int32			pid   = 3;
+	required int32			fd    = 4;
+	required int64			start = 5;
+	required int64			len   = 6;
+}
+
-- 
1.7.1




More information about the CRIU mailing list