[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