Commit 95801808 authored by Qiang Huang's avatar Qiang Huang Committed by Pavel Emelyanov

crtools: dump flock&posix file locks

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: 's avatarZheng Gu <cengku.gu@huawei.com>
Signed-off-by: 's avatarQiang Huang <h.huangqiang@huawei.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 286801d4
......@@ -648,6 +648,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;
......@@ -1213,7 +1341,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;
......@@ -1507,6 +1635,15 @@ static int dump_one_task(struct pstree_item *item)
}
}
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);
......
......@@ -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);
}
......@@ -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__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment