Skip to content
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

Proposal for support of dmabuf with CRIU #2581

Draft
wants to merge 1 commit into
base: criu-dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions criu/cr-dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -2228,6 +2228,9 @@ int cr_dump_tasks(pid_t pid)
goto err;
}

if(run_plugins(DUMP_DEVICE_LATE, pid))
goto err;

if (parent_ie) {
inventory_entry__free_unpacked(parent_ie, NULL);
parent_ie = NULL;
Expand Down
1 change: 1 addition & 0 deletions criu/cr-restore.c
Original file line number Diff line number Diff line change
Expand Up @@ -3470,6 +3470,7 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
close_image_dir();
close_proc();
close_service_fd(TRANSPORT_FD_OFF);
close_service_fd(DMABUF_FD_OFF);
close_service_fd(CR_PROC_FD_OFF);
close_service_fd(ROOT_FD_OFF);
close_service_fd(USERNSD_SK);
Expand Down
10 changes: 7 additions & 3 deletions criu/files-ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ static int open_fd(struct file_desc *d, int *new_fd)
{
struct ext_file_info *xfi;
int fd;
bool retry_needed;

xfi = container_of(d, struct ext_file_info, d);

fd = run_plugins(RESTORE_EXT_FILE, xfi->xfe->id);
fd = run_plugins(RESTORE_EXT_FILE, xfi->xfe->id, &retry_needed);
if (fd < 0) {
pr_err("Unable to restore %#x\n", xfi->xfe->id);
return -1;
Expand All @@ -57,8 +58,11 @@ static int open_fd(struct file_desc *d, int *new_fd)
if (restore_fown(fd, xfi->xfe->fown))
return -1;

*new_fd = fd;
return 0;
if (!retry_needed)
*new_fd = fd;
else
*new_fd = -1;
return retry_needed;
}

static struct file_desc_ops ext_desc_ops = {
Expand Down
113 changes: 113 additions & 0 deletions criu/files.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
static struct hlist_head file_desc_hash[FDESC_HASH_SIZE];
/* file_desc's, which fle is not owned by a process, that is able to open them */
static LIST_HEAD(fake_master_head);
/* processes that have a file from a plugin that can use shared dmabuf_fds */
static LIST_HEAD(dmabuf_processes);

static u32 max_file_desc_id = 0;

Expand Down Expand Up @@ -831,10 +833,35 @@
}
}

static int add_pid_to_dmabuf_list(int pid)
{
struct fdinfo_list_entry *le;

list_for_each_entry(le, &dmabuf_processes, desc_list)
if (le->pid == pid)
return 0;

le = alloc_fle(pid, NULL);

if (!le)
return -ENOMEM;

list_add(&le->desc_list, &dmabuf_processes);

return 0;
}

struct fdinfo_list_entry *collect_fd_to(int pid, FdinfoEntry *e, struct rst_info *rst_info, struct file_desc *fdesc,
bool fake, bool force_master)
{
struct fdinfo_list_entry *new_le;
int ret;

if (fdesc->ops->type == FD_TYPES__EXT) {
ret = add_pid_to_dmabuf_list(pid);
if (ret)
return NULL;
}

new_le = alloc_fle(pid, e);
if (new_le) {
Expand Down Expand Up @@ -983,6 +1010,14 @@
*addr->sun_path = '\0';
}

static void dmabuf_socket_name_gen(struct sockaddr_un *addr, int *len, int pid)
{
addr->sun_family = AF_UNIX;
snprintf(addr->sun_path, UNIX_PATH_MAX, "x/crtools-dmabuf-%d-%" PRIx64, pid, criu_run_id);

Check failure

Code scanning / CodeQL

Wrong type of arguments to formatting function High

This format specifier for type 'unsigned long' does not match the argument type 'char *'.
*len = SUN_LEN(addr);
*addr->sun_path = '\0';
}

static bool task_fle(struct pstree_item *task, struct fdinfo_list_entry *fle)
{
struct fdinfo_list_entry *tmp;
Expand Down Expand Up @@ -1028,6 +1063,45 @@
return 0;
}

static int recv_dmabuf_fds(void)
{
int fd, newfd, ret, tsock, handle;

tsock = get_service_fd(DMABUF_FD_OFF);

while (true) {
ret = __recv_fds(tsock, &fd, 1, (void *)&handle, sizeof(handle), MSG_DONTWAIT);

if (ret == -EAGAIN || ret == -EWOULDBLOCK)
return 1;
else if (ret)
return -1;

newfd = get_unused_high_fd();

reopen_fd_as(newfd, fd);

run_plugins(DMABUF_FD, handle, newfd);
}

return 0;
}

static int send_dmabuf_fd_to_peer(int handle, int fd, int pid)
{
struct sockaddr_un saddr;
int len, sock, ret;

sock = get_service_fd(DMABUF_FD_OFF);

dmabuf_socket_name_gen(&saddr, &len, pid);
pr_info("\t\tSend dmabuf fd %d for handle %d to %s\n", fd, handle, saddr.sun_path + 1);
ret = send_fds(sock, &saddr, len, &fd, 1, (void *)&handle, sizeof(handle));
if (ret < 0)
return -1;
return set_fds_event(pid);
}

static int send_fd_to_peer(int fd, struct fdinfo_list_entry *fle)
{
struct sockaddr_un saddr;
Expand Down Expand Up @@ -1132,6 +1206,25 @@
return 0;
}

int serve_out_dmabuf_fd(int handle, int fd)
{
int ret;
struct fdinfo_list_entry *fle;

list_for_each_entry(fle, &dmabuf_processes, desc_list) {
ret = send_dmabuf_fd_to_peer(handle, fd, fle->pid);

if (ret) {
pr_err("Can't sent fd %d to %d\n", fd, fle->pid);
goto out;
}
}

ret = 0;
out:
return ret;
}

static int open_fd(struct fdinfo_list_entry *fle)
{
struct file_desc *d = fle->desc;
Expand Down Expand Up @@ -1212,6 +1305,7 @@
do {
progress = again = false;
clear_fds_event();
recv_dmabuf_fds();

list_for_each_entry_safe(fle, tmp, list, ps_list) {
st = fle->stage;
Expand Down Expand Up @@ -1707,6 +1801,25 @@

if (install_service_fd(TRANSPORT_FD_OFF, sock) < 0)
goto out;


sock = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (sock < 0) {
pr_perror("Can't create socket");
goto out;
}

dmabuf_socket_name_gen(&saddr, &slen, pid);
if (bind(sock, (struct sockaddr *)&saddr, slen) < 0) {
pr_perror("Can't bind dmabuf socket %s", saddr.sun_path + 1);
close(sock);
goto out;
}

if (install_service_fd(DMABUF_FD_OFF, sock) < 0)
goto out;


ret = 0;
out:
return ret;
Expand Down
8 changes: 7 additions & 1 deletion criu/include/criu-plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ enum {

CR_PLUGIN_HOOK__CHECKPOINT_DEVICES = 11,

CR_PLUGIN_HOOK__DUMP_DEVICE_LATE = 12,

CR_PLUGIN_HOOK__DMABUF_FD = 13,

CR_PLUGIN_HOOK__MAX
};

Expand All @@ -68,7 +72,7 @@ enum {
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DUMP_UNIX_SK, int fd, int id);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__RESTORE_UNIX_SK, int id);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DUMP_EXT_FILE, int fd, int id);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__RESTORE_EXT_FILE, int id);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__RESTORE_EXT_FILE, int id, bool *retry_needed);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DUMP_EXT_MOUNT, char *mountpoint, int id);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__RESTORE_EXT_MOUNT, int id, char *mountpoint, char *old_root, int *is_file);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DUMP_EXT_LINK, int index, int type, char *kind);
Expand All @@ -78,6 +82,8 @@ DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__UPDATE_VMA_MAP, const char *path, const
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__RESUME_DEVICES_LATE, int pid);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__PAUSE_DEVICES, int pid);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__CHECKPOINT_DEVICES, int pid);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DUMP_DEVICE_LATE, int id);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DMABUF_FD, int handle, int fd);

enum {
CR_PLUGIN_STAGE__DUMP,
Expand Down
2 changes: 2 additions & 0 deletions criu/include/files.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,5 +195,7 @@ extern int open_transport_socket(void);
extern int set_fds_event(pid_t virt);
extern void wait_fds_event(void);

int serve_out_dmabuf_fd(int handle, int fd);

int find_unused_fd_pid(pid_t pid);
#endif /* __CR_FILES_H__ */
2 changes: 2 additions & 0 deletions criu/include/servicefd.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ enum sfd_type {
USERNSD_SK, /* Socket for usernsd */
NS_FD_OFF, /* Node's net namespace fd */
TRANSPORT_FD_OFF, /* to transfer file descriptors */
DMABUF_FD_OFF,
RPC_SK_OFF,
FDSTORE_SK_OFF,

Expand All @@ -47,5 +48,6 @@ extern int install_service_fd(enum sfd_type type, int fd);
extern int close_service_fd(enum sfd_type type);
extern void __close_service_fd(enum sfd_type type);
extern int clone_service_fd(struct pstree_item *me);
extern int get_unused_high_fd(void);

#endif /* __CR_SERVICE_FD_H__ */
4 changes: 4 additions & 0 deletions criu/pie/restorer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1920,6 +1920,10 @@ __visible long __export_restore_task(struct task_restore_args *args)

for (m = 0; m < sizeof(vma_entry->madv) * 8; m++) {
if (vma_entry->madv & (1ul << m)) {

if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR)))
continue;

ret = sys_madvise(vma_entry->start, vma_entry_len(vma_entry), m);
if (ret) {
pr_err("madvise(%" PRIx64 ", %" PRIu64 ", %ld) "
Expand Down
1 change: 1 addition & 0 deletions criu/plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static cr_plugin_desc_t *cr_gen_plugin_desc(void *h, char *path)
__assign_hook(RESUME_DEVICES_LATE, "cr_plugin_resume_devices_late");
__assign_hook(PAUSE_DEVICES, "cr_plugin_pause_devices");
__assign_hook(CHECKPOINT_DEVICES, "cr_plugin_checkpoint_devices");
__assign_hook(DUMP_DEVICE_LATE, "cr_plugin_dump_device_late");

#undef __assign_hook

Expand Down
12 changes: 12 additions & 0 deletions criu/servicefd.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ int service_fd_rlim_cur;

/* Base of current process service fds set */
static int service_fd_base;
static int next_high_fd;

/* Id of current process in shared fdt */
static int service_fd_id = 0;
Expand Down Expand Up @@ -53,6 +54,7 @@ const char *sfd_type_name(enum sfd_type type)
[USERNSD_SK] = __stringify_1(USERNSD_SK),
[NS_FD_OFF] = __stringify_1(NS_FD_OFF),
[TRANSPORT_FD_OFF] = __stringify_1(TRANSPORT_FD_OFF),
[DMABUF_FD_OFF] = __stringify_1(DMABUF_FD_OFF),
[RPC_SK_OFF] = __stringify_1(RPC_SK_OFF),
[FDSTORE_SK_OFF] = __stringify_1(FDSTORE_SK_OFF),
[SERVICE_FD_MAX] = __stringify_1(SERVICE_FD_MAX),
Expand Down Expand Up @@ -312,5 +314,15 @@ int clone_service_fd(struct pstree_item *me)
service_fd_id = id;
ret = 0;

next_high_fd = service_fd_base + 1024;

return ret;
}

int get_unused_high_fd(void)
{
if (next_high_fd > service_fd_rlim_cur)
return -1;
next_high_fd += 1;
return next_high_fd - 1;
}
Loading
Loading