2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-31 06:15:24 +00:00

crtools: collect and check file locks

We collect all file locks to a golbal list, so we can use them easily
in dump_one_task. For optimizaton, we only collect file locks hold by
tasks in the pstree.

Thanks to the ptrace-seize machanism, we can aviod the blocked file lock
issue, makes the work simpler.

Right now, the check handles only one situation:
-- Dumping tasks with file locks hold without the -l option.

This covers for the most part. But we still need some more work to make
it perfect robust in the future.

Signed-off-by: Qiang Huang <h.huangqiang@huawei.com>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
Qiang Huang
2013-01-17 16:09:32 +08:00
committed by Pavel Emelyanov
parent b08836cc51
commit 286801d4c1
6 changed files with 195 additions and 0 deletions

View File

@@ -15,6 +15,8 @@
#include "crtools.h"
#include "mount.h"
#include "cpu.h"
#include "file-lock.h"
#include "pstree.h"
#include "fsnotify.h"
#include "proc_parse.h"
@@ -1063,3 +1065,96 @@ parse_err:
pr_perror("%s: error parsing [%s] for %d\n", __func__, str, type);
return -1;
}
static int parse_file_lock_buf(char *buf, struct file_lock *fl,
bool is_blocked)
{
int num;
if (is_blocked) {
num = sscanf(buf, "%lld: -> %s %s %s %d %02x:%02x:%ld %lld %s",
&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);
} else {
num = sscanf(buf, "%lld:%s %s %s %d %02x:%02x:%ld %lld %s",
&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);
}
if (num < 10) {
pr_perror("Invalid file lock info!");
return -1;
}
return 0;
}
int parse_file_locks(void)
{
struct file_lock *fl;
FILE *fl_locks;
int ret = 0;
bool is_blocked = false;
fl_locks = fopen("/proc/locks", "r");
if (!fl_locks) {
pr_perror("Can't open file locks file!");
return -1;
}
while (fgets(buf, BUF_SIZE, fl_locks)) {
if (strstr(buf, "->"))
is_blocked = true;
fl = alloc_file_lock();
if (!fl) {
pr_perror("Alloc file lock failed!");
ret = -1;
goto err;
}
if (parse_file_lock_buf(buf, fl, is_blocked)) {
xfree(fl);
ret = -1;
goto err;
}
if (!pid_in_pstree(fl->fl_owner)) {
/*
* We only care about tasks which are taken
* into dump, so we only collect file locks
* belong to these tasks.
*/
xfree(fl);
continue;
}
if (is_blocked) {
/*
* Here the task is in the pstree.
* If it is blocked on a flock, when we try to
* ptrace-seize it, the kernel will unblock task
* from flock and will stop it in another place.
* So in dumping, a blocked file lock should never
* be here.
*/
pr_perror("We have a blocked file lock!");
ret = -1;
goto err;
}
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);
list_add_tail(&fl->list, &file_lock_list);
}
err:
fclose(fl_locks);
return ret;
}