[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