mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 06:15:24 +00:00
zdtm: fanotify00 -- Make test to check all flags we c/r
Just reading if event entry exist in buffer is not enough we rathee need to be sure that all flags and bits are recovered well. For this sake we parse fdinfo before and after the c/r sessions and compare results. Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
committed by
Pavel Emelyanov
parent
12b579bac0
commit
c28573fda1
@@ -29,7 +29,36 @@ const char *test_author = "Cyrill Gorcunov <gorcunov@openvz.org>";
|
||||
|
||||
const char fanotify_path[] = "fanotify-del-after-cr";
|
||||
|
||||
#define BUFF_SIZE ((sizeof(struct inotify_event) + PATH_MAX))
|
||||
#define BUFF_SIZE (8192)
|
||||
|
||||
struct fanotify_mark_inode {
|
||||
unsigned long i_ino;
|
||||
unsigned int s_dev;
|
||||
unsigned int mflags;
|
||||
unsigned int mask;
|
||||
unsigned int ignored_mask;
|
||||
unsigned int fhandle_bytes;
|
||||
unsigned int fhandle_type;
|
||||
unsigned char fhandle[512];
|
||||
};
|
||||
|
||||
struct fanotify_mark_mount {
|
||||
unsigned int mnt_id;
|
||||
unsigned int mflags;
|
||||
unsigned int mask;
|
||||
unsigned int ignored_mask;
|
||||
};
|
||||
|
||||
struct fanotify_glob {
|
||||
unsigned int faflags;
|
||||
unsigned int evflags;
|
||||
};
|
||||
|
||||
struct fanotify_obj {
|
||||
struct fanotify_glob glob;
|
||||
struct fanotify_mark_inode inode;
|
||||
struct fanotify_mark_mount mount;
|
||||
};
|
||||
|
||||
static int fanotify_init(unsigned int flags, unsigned int event_f_flags)
|
||||
{
|
||||
@@ -42,10 +71,114 @@ static int fanotify_mark(int fanotify_fd, unsigned int flags, unsigned long mask
|
||||
return syscall(__NR_fanotify_mark, fanotify_fd, flags, mask, dfd, pathname);
|
||||
}
|
||||
|
||||
#define fdinfo_field(str, field) !strncmp(str, field":", sizeof(field))
|
||||
|
||||
static void show_fanotify_obj(struct fanotify_obj *obj)
|
||||
{
|
||||
test_msg("fanotify obj at %p\n", obj);
|
||||
|
||||
test_msg(" glob\n");
|
||||
test_msg(" faflags: %x evflags: %x\n",
|
||||
obj->glob.faflags, obj->glob.evflags);
|
||||
|
||||
test_msg(" inode\n");
|
||||
test_msg(" i_ino: %lx s_dev: %x mflags: %x "
|
||||
"mask: %x ignored_mask: %x "
|
||||
"fhandle_bytes: %x fhandle_type: %x"
|
||||
"fhandle: %s",
|
||||
obj->inode.i_ino, obj->inode.s_dev,
|
||||
obj->inode.mflags, obj->inode.mask,
|
||||
obj->inode.ignored_mask, obj->inode.fhandle_bytes,
|
||||
obj->inode.fhandle_type, obj->inode.fhandle);
|
||||
|
||||
test_msg(" mount\n");
|
||||
test_msg(" mnt_id: %x mflags: %x mask: %x ignored_mask: %x\n",
|
||||
obj->mount.mnt_id, obj->mount.mflags,
|
||||
obj->mount.mask, obj->mount.ignored_mask);
|
||||
}
|
||||
|
||||
static void copy_fhandle(char *tok, struct fanotify_mark_inode *inode)
|
||||
{
|
||||
int off = 0;
|
||||
|
||||
while (*tok && (*tok > '0' || *tok < 'f')) {
|
||||
inode->fhandle[off++] = *tok++;
|
||||
if (off >= sizeof(inode->fhandle) - 1)
|
||||
break;
|
||||
}
|
||||
inode->fhandle[off] = '\0';
|
||||
}
|
||||
|
||||
int parse_fanotify_fdinfo(int fd, struct fanotify_obj *obj, unsigned int expected_to_meet)
|
||||
{
|
||||
unsigned int met = 0;
|
||||
char str[512];
|
||||
FILE *f;
|
||||
int ret;
|
||||
|
||||
sprintf(str, "/proc/self/fdinfo/%d", fd);
|
||||
f = fopen(str, "r");
|
||||
if (!f) {
|
||||
err("Can't open fdinfo to parse");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(str, sizeof(str), f)) {
|
||||
if (fdinfo_field(str, "fanotify flags")) {
|
||||
ret = sscanf(str, "fanotify flags:%x event-flags:%x",
|
||||
&obj->glob.faflags, &obj->glob.evflags);
|
||||
if (ret != 2)
|
||||
goto parse_err;
|
||||
met++;
|
||||
continue;
|
||||
}
|
||||
if (fdinfo_field(str, "fanotify mnt_id")) {
|
||||
ret = sscanf(str,
|
||||
"fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x",
|
||||
&obj->mount.mnt_id, &obj->mount.mflags,
|
||||
&obj->mount.mask, &obj->mount.ignored_mask);
|
||||
if (ret != 4)
|
||||
goto parse_err;
|
||||
met++;
|
||||
continue;
|
||||
}
|
||||
if (fdinfo_field(str, "fanotify ino")) {
|
||||
int hoff;
|
||||
ret = sscanf(str,
|
||||
"fanotify ino:%lx sdev:%x mflags:%x mask:%x ignored_mask:%x "
|
||||
"fhandle-bytes:%x fhandle-type:%x f_handle: %n",
|
||||
&obj->inode.i_ino, &obj->inode.s_dev,
|
||||
&obj->inode.mflags, &obj->inode.mask, &obj->inode.ignored_mask,
|
||||
&obj->inode.fhandle_bytes, &obj->inode.fhandle_type,
|
||||
&hoff);
|
||||
if (ret != 7)
|
||||
goto parse_err;
|
||||
copy_fhandle(&str[hoff], &obj->inode);
|
||||
met++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (expected_to_meet != met) {
|
||||
err("Expected to meet %d entries but got %d\n",
|
||||
expected_to_meet, met);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
parse_err:
|
||||
err("Can't parse '%s'\n", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
char buf[BUFF_SIZE];
|
||||
struct fanotify_obj old = { }, new = { };
|
||||
int fa_fd, fd, del_after;
|
||||
char buf[BUFF_SIZE];
|
||||
ssize_t length;
|
||||
|
||||
|
||||
test_init(argc, argv);
|
||||
|
||||
@@ -85,6 +218,13 @@ int main (int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (parse_fanotify_fdinfo(fa_fd, &old, 3)) {
|
||||
err("parsing fanotify fdinfo failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
show_fanotify_obj(&old);
|
||||
|
||||
test_daemon();
|
||||
test_waitsig();
|
||||
|
||||
@@ -99,7 +239,20 @@ int main (int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (read(fa_fd, buf, sizeof(buf)) <= 0) {
|
||||
if (parse_fanotify_fdinfo(fa_fd, &new, 3)) {
|
||||
fail("parsing fanotify fdinfo failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
show_fanotify_obj(&new);
|
||||
|
||||
if (memcmp(&old, &new, sizeof(old))) {
|
||||
fail("fanotify mismatch on fdinfo level\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
length = read(fa_fd, buf, sizeof(buf));
|
||||
if (length <= 0) {
|
||||
fail("No events in fanotify queue\n");
|
||||
exit(1);
|
||||
}
|
||||
|
Reference in New Issue
Block a user