-
Notifications
You must be signed in to change notification settings - Fork 559
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
criu: Add pidfd support #2259
base: criu-dev
Are you sure you want to change the base?
criu: Add pidfd support #2259
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -113,6 +113,7 @@ enum { | |
CR_FD_PIPES, | ||
CR_FD_TTY_FILES, | ||
CR_FD_MEMFD_FILE, | ||
CR_FD_PIDFD, | ||
|
||
CR_FD_AUTOFS, | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#ifndef __CR_PIDFD_H__ | ||
#define __CR_PIDFD_H__ | ||
|
||
#include <sys/stat.h> | ||
#include "images/pidfd.pb-c.h" | ||
#include <sys/syscall.h> | ||
#include <unistd.h> | ||
|
||
struct fd_parms; | ||
|
||
extern const struct fdtype_ops pidfd_dump_ops; | ||
extern struct collect_image_info pidfd_cinfo; | ||
extern int is_pidfd_link(char *link); | ||
|
||
static inline int pidfd_open(pid_t pid, unsigned int flags) | ||
{ | ||
return syscall(__NR_pidfd_open, pid, flags); | ||
} | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,6 +81,7 @@ enum { | |
PB_SK_QUEUES, | ||
PB_IPCNS_MSG, | ||
PB_IPCNS_MSG_ENT, | ||
PB_PIDFD, | ||
|
||
PB_MAX, | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
#include "pidfd.h" | ||
#include "util.h" | ||
|
||
#include "fdinfo.h" | ||
#include "files.h" | ||
#include "imgset.h" | ||
#include "protobuf.h" | ||
#include "fdinfo.pb-c.h" | ||
|
||
int is_pidfd_link(char *link) | ||
{ | ||
return is_anon_link_type(link, "[pidfd]"); | ||
} | ||
|
||
static int dump_one_pidfd(int lfd, u32 id, const struct fd_parms *p) | ||
{ | ||
PidfdEntry tfe = PIDFD_ENTRY__INIT; | ||
FileEntry fe = FILE_ENTRY__INIT; | ||
|
||
if (parse_fdinfo(lfd, FD_TYPES__PIDFD, &tfe)) | ||
return -1; | ||
|
||
tfe.id = id; | ||
tfe.flags = p->flags; | ||
tfe.inode = p->stat.st_ino; | ||
tfe.mnt_id = p->mnt_id; | ||
tfe.fown = (FownEntry *)&p->fown; | ||
|
||
fe.type = FD_TYPES__PIDFD; | ||
fe.id = tfe.id; | ||
fe.pidfd = &tfe; | ||
|
||
return pb_write_one(img_from_set(glob_imgset, CR_FD_FILES), &fe, PB_FILE); | ||
} | ||
|
||
const struct fdtype_ops pidfd_dump_ops = { | ||
.type = FD_TYPES__PIDFD, | ||
.dump = dump_one_pidfd, | ||
}; | ||
|
||
struct pidfd_info { | ||
PidfdEntry *pidfde; | ||
struct file_desc d; | ||
}; | ||
|
||
static int open_pidfd_fd(struct file_desc *d, int *new_fd) | ||
{ | ||
int fd = -1; | ||
struct pidfd_info *info = container_of(d, struct pidfd_info, d); | ||
PidfdEntry *pidfde = info->pidfde; | ||
|
||
pr_info("Creating new pidfd %" PRId64 "\n", pidfde->pid); | ||
fd = pidfd_open(pidfde->pid, 0); | ||
if (fd < 0) { | ||
pr_perror("Cannot create pidfd %" PRId64, pidfde->pid); | ||
return -1; | ||
} | ||
|
||
*new_fd = fd; | ||
return 0; | ||
} | ||
|
||
static struct file_desc_ops pidfd_desc_ops = { | ||
.type = FD_TYPES__PIDFD, | ||
.open = open_pidfd_fd, | ||
}; | ||
|
||
static int collect_one_pidfd(void *o, ProtobufCMessage *msg, struct cr_img *i) | ||
{ | ||
struct pidfd_info *info = o; | ||
|
||
info->pidfde = pb_msg(msg, PidfdEntry); | ||
return file_desc_add(&info->d, info->pidfde->id, &pidfd_desc_ops); | ||
} | ||
|
||
struct collect_image_info pidfd_cinfo = { | ||
.fd_type = CR_FD_PIDFD, | ||
.pb_type = PB_PIDFD, | ||
.priv_size = sizeof(struct pidfd_info), | ||
.collect = collect_one_pidfd, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
syntax = "proto2"; | ||
|
||
import "fown.proto"; | ||
|
||
message pidfd_entry { | ||
required uint32 id = 1; | ||
required uint64 pos = 2; | ||
required uint32 flags = 3; | ||
required uint32 mnt_id = 4; | ||
required uint64 inode = 5; | ||
required int64 pid = 6; | ||
required int64 nspid = 7; | ||
required fown_entry fown = 8; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#include <errno.h> | ||
#include <unistd.h> | ||
#include <fcntl.h> | ||
#include <stdlib.h> | ||
#include <sys/types.h> | ||
#include <sys/wait.h> | ||
#include <signal.h> | ||
#include <string.h> | ||
#include <sys/syscall.h> | ||
#include <sys/types.h> | ||
#include <unistd.h> | ||
#include <poll.h> | ||
|
||
#include "zdtmtst.h" | ||
|
||
static int pidfd_open(pid_t pid, unsigned int flags) | ||
{ | ||
return syscall(SYS_pidfd_open, pid, flags); | ||
} | ||
|
||
const char *test_doc = "Pidfd "; | ||
const char *test_author = "Suraj Shirvankar <surajshirvankar@gmail.com>"; | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
int pidfd, errcode = 42; | ||
int status; | ||
int ret; | ||
struct pollfd pollfd; | ||
|
||
test_init(argc, argv); | ||
|
||
pidfd = pidfd_open(1, 0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test has to create more than one pidfd linked to different tasks and then checks that they are linked to proper tasks after C/R. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @avagin I tried to write a test that would create a fork of a process and the parent process would monitor the pid of the child process. The dumping and restore process would first restore the parent process and the child process would still not be restored, hence the restore would fail. |
||
if (pidfd == -1) { | ||
perror("Couldnt open pidfd"); | ||
exit(1); | ||
} | ||
|
||
test_daemon(); | ||
test_waitsig(); | ||
|
||
pollfd.fd = pidfd; | ||
pollfd.events = POLLIN; | ||
|
||
ret = poll(&pollfd, 1, -1); | ||
if (ret == -1) { | ||
pr_perror("Poll error"); | ||
fail(); | ||
} | ||
|
||
if (pollfd.revents & POLLIN) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why can it be triggered? |
||
if (read(pidfd, &status, sizeof(status)) != sizeof(status)) { | ||
fail("pidfd read error"); | ||
} | ||
if (status == errcode) { | ||
printf("Status code is %d", status); | ||
pass(); | ||
} else { | ||
fail("Exit code mismatch"); | ||
} | ||
} | ||
|
||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a task linked to fd can be dead and pidfd_open will fail in this case.