[CRIU] [PATCH 07/11] crtools: dump flock&posix file locks

Qiang Huang h.huangqiang at huawei.com
Thu Jan 17 03:09:33 EST 2013


Dump file locks' necessary entries to the image, we only support flock and
posix file lock right now.

Changelog since the initial version:
We got file lock info from global list, so the dump_task_file_locks
can be much simpler.

Originally-signed-off-by: Zheng Gu <cengku.gu at huawei.com>
Signed-off-by: Qiang Huang <h.huangqiang at huawei.com>
---
 cr-dump.c           |  139 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 file-lock.c         |    9 +++
 include/file-lock.h |   17 ++++++
 3 files changed, 164 insertions(+), 1 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index 9480fdb..4bd546f 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -608,6 +608,134 @@ out:
 	return ret;
 }
 
+static int fill_flock_entry(FileLockEntry *fle, const char *fl_flag,
+			const char *fl_type, const char *fl_option)
+{
+	if (!strcmp(fl_flag, "POSIX")) {
+		fle->flag |= FL_POSIX;
+	} else if (!strcmp(fl_flag, "FLOCK")) {
+		fle->flag |= FL_FLOCK;
+	} else {
+		pr_err("Unknow file lock!\n");
+		goto err;
+	}
+
+	if (!strcmp(fl_type, "MSNFS")) {
+		fle->type |= LOCK_MAND;
+
+		if (!strcmp(fl_option, "READ")) {
+			fle->type |= LOCK_READ;
+		} else if (!strcmp(fl_option, "RW")) {
+			fle->type |= LOCK_RW;
+		} else if (!strcmp(fl_option, "WRITE")) {
+			fle->type |= LOCK_WRITE;
+		} else {
+			pr_err("Unknow lock option!\n");
+			goto err;
+		}
+	} else {
+		if (!strcmp(fl_option, "UNLCK")) {
+			fle->type |= F_UNLCK;
+		} else if (!strcmp(fl_option, "WRITE")) {
+			fle->type |= F_WRLCK;
+		} else if (!strcmp(fl_option, "READ")) {
+			fle->type |= F_RDLCK;
+		} else {
+			pr_err("Unknow lock option!\n");
+			goto err;
+		}
+	}
+
+	return 0;
+err:
+	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';
+
+		memset(path, 0, sizeof(path));
+		ret = readlink(buf, path, sizeof(path));
+		if (ret < 0) {
+			pr_err("Read link %s failed!\n", buf);
+			goto err;
+		}
+
+		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:
+	return -1;
+}
+
+static int dump_task_file_locks(struct parasite_ctl *ctl,
+			struct cr_fdset *fdset,	struct parasite_drain_fd *dfds)
+{
+	FileLockEntry	 fle;
+	struct file_lock *fl;
+
+	pid_t	pid = ctl->pid;
+	int	ret = 0;
+
+	list_for_each_entry(fl, &file_lock_list, list) {
+		if (fl->fl_owner != pid)
+			continue;
+		pr_info("lockinfo: %lld:%s %s %s %d %02x:%02x:%ld %lld %s\n",
+			fl->fl_id, fl->fl_flag, fl->fl_type, fl->fl_option,
+			fl->fl_owner, fl->maj, fl->min, fl->i_no,
+			fl->start, fl->end);
+
+		file_lock_entry__init(&fle);
+		fle.pid = fl->fl_owner;
+
+		ret = fill_flock_entry(&fle, fl->fl_flag, fl->fl_type,
+				fl->fl_option);
+		if (ret)
+			goto err;
+
+		fle.fd = get_fd_by_ino(fl->i_no, dfds, pid);
+		if (fle.fd < 0) {
+			ret = -1;
+			goto err;
+		}
+
+		fle.start = fl->start;
+
+		if (!strncmp(fl->end, "EOF", 3))
+			fle.len = 0;
+		else
+			fle.len = (atoll(fl->end) + 1) - fl->start;
+
+		ret = dump_one_file_lock(&fle, fdset);
+		if (ret) {
+			pr_err("Dump file lock failed!\n");
+			goto err;
+		}
+	}
+
+err:
+	return ret;
+}
+
 static int get_task_futex_robust_list(pid_t pid, ThreadCoreEntry *info)
 {
 	struct robust_list_head *head = NULL;
@@ -1357,7 +1485,7 @@ static int collect_file_locks(const struct cr_options *opts)
 
 	if (opts->handle_file_locks)
 		/*
-		 * If the handle file locks option is set,
+		 * If the handle file locks option(-l) is set,
 		 * collect work is over.
 		 */
 		return 0;
@@ -1648,6 +1776,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/file-lock.c b/file-lock.c
index 2760079..3d4183d 100644
--- a/file-lock.c
+++ b/file-lock.c
@@ -28,3 +28,12 @@ void free_file_locks(void)
 
 	INIT_LIST_HEAD(&file_lock_list);
 }
+
+int dump_one_file_lock(FileLockEntry *fle, const struct cr_fdset *fdset)
+{
+	pr_info("flag: %d,type: %d,pid: %d,fd: %d,start: %8lx,len: %8lx\n",
+		fle->flag, fle->type, fle->pid,	fle->fd, fle->start, fle->len);
+
+	return pb_write_one(fdset_fd(fdset, CR_FD_FILE_LOCKS),
+			fle, PB_FILE_LOCK);
+}
diff --git a/include/file-lock.h b/include/file-lock.h
index 9fdaa39..d6d2397 100644
--- a/include/file-lock.h
+++ b/include/file-lock.h
@@ -5,6 +5,22 @@
 #include "protobuf.h"
 #include "../protobuf/file-lock.pb-c.h"
 
+#define FL_POSIX	1
+#define FL_FLOCK	2
+
+/* for posix fcntl() and lockf() */
+#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_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 */
+
 struct file_lock {
 	long long	fl_id;
 	char		fl_flag[10];
@@ -24,5 +40,6 @@ extern struct list_head file_lock_list;
 
 extern struct file_lock *alloc_file_lock(void);
 extern void free_file_locks(void);
+extern int dump_one_file_lock(FileLockEntry *fle, const struct cr_fdset *fdset);
 
 #endif /* __FILE_LOCK_H__ */
-- 
1.7.1




More information about the CRIU mailing list