From: Jingxian He hejingxian@huawei.com
Add support for char device dump and restore during module upgrade.
`/sys/kernel/repairing_device` provides the char device whiltelist with `IOCTL_CMD_{NEEDREPAIR, REPAIR}` command besides the internal device list. The device modules could use `mures_{add, del}_devname()` to add, or delete the char device whitelist dynamically.
Conflict:NA Reference:https://gitee.com/src-openeuler/criu/pulls/21 Signed-off-by: Xiaoguang Li lixiaoguang2@huawei.com Signed-off-by: Jingxian He hejingxian@huawei.com Signed-off-by: fu.lin fulin10@huawei.com --- criu/Makefile.crtools | 1 + criu/config.c | 1 + criu/cr-dump.c | 3 + criu/cr-restore.c | 4 +- criu/crtools.c | 1 + criu/devname.c | 130 ++++++++++++++++++++++++++++ criu/files-reg.c | 34 +++++++- criu/files.c | 159 ++++++++++++++++++++++++++++++++++- criu/include/cr_options.h | 1 + criu/include/files-reg.h | 9 ++ criu/include/files.h | 6 ++ criu/include/image-desc.h | 1 + criu/include/image.h | 1 + criu/include/protobuf-desc.h | 1 + criu/include/util.h | 3 + criu/mem.c | 6 +- criu/proc_parse.c | 16 +++- images/Makefile | 1 + images/chr.proto | 12 +++ images/fdinfo.proto | 3 + 20 files changed, 382 insertions(+), 11 deletions(-) create mode 100644 criu/devname.c create mode 100644 images/chr.proto
diff --git a/criu/Makefile.crtools b/criu/Makefile.crtools index dcffb4f..a9008f0 100644 --- a/criu/Makefile.crtools +++ b/criu/Makefile.crtools @@ -89,6 +89,7 @@ obj-y += servicefd.o obj-y += pie-util-vdso.o obj-y += vdso.o obj-y += timens.o +obj-y += devname.o obj-$(CONFIG_HAS_LIBBPF) += bpfmap.o obj-$(CONFIG_COMPAT) += pie-util-vdso-elf32.o CFLAGS_pie-util-vdso-elf32.o += -DCONFIG_VDSO_32 diff --git a/criu/config.c b/criu/config.c index 4d2b709..0ccd2b5 100644 --- a/criu/config.c +++ b/criu/config.c @@ -546,6 +546,7 @@ int parse_options(int argc, char **argv, bool *usage_error, BOOL_OPT("use-fork-pid", &opts.use_fork_pid), BOOL_OPT("with-notifier", &opts.with_notifier_kup), BOOL_OPT("with-fd-cred", &opts.with_fd_cred), + BOOL_OPT("dump-char-dev", &opts.dump_char_dev), { }, };
diff --git a/criu/cr-dump.c b/criu/cr-dump.c index 96c0cd3..9ba27a2 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -1827,6 +1827,9 @@ int cr_dump_tasks(pid_t pid) */ rlimit_unlimit_nofile();
+ if (opts.dump_char_dev && parse_devname() < 0) + goto err; + root_item = alloc_pstree_item(); if (!root_item) goto err; diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 7ceb8fe..7c198ce 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -349,11 +349,11 @@ static int root_prepare_shared(void) if (pi->pid->state == TASK_HELPER) continue;
- ret = prepare_mm_pid(pi); + ret = prepare_fd_pid(pi); if (ret < 0) break;
- ret = prepare_fd_pid(pi); + ret = prepare_mm_pid(pi); if (ret < 0) break;
diff --git a/criu/crtools.c b/criu/crtools.c index 942e683..26010b5 100644 --- a/criu/crtools.c +++ b/criu/crtools.c @@ -450,6 +450,7 @@ usage: " Only for the host with these feature.\n" " --with-fd-cred Allow to make the restored process has the same cred\n" " as checkout assisted by kernel.\n" +" --dump-char-dev Dump char dev files as normal file with repair cmd\n" "\n" "Check options:\n" " Without options, "criu check" checks availability of absolutely required\n" diff --git a/criu/devname.c b/criu/devname.c new file mode 100644 index 0000000..5f6fbed --- /dev/null +++ b/criu/devname.c @@ -0,0 +1,130 @@ +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "log.h" +#include "common/xmalloc.h" + +#define REPAIRING_DEVICE_FILE "/sys/kernel/repairing_device" +#define ASCII_SIZE 128 + +static void *root_bucket[ASCII_SIZE]; + +static int insert_devname_internal(void *bucket[], const char *name) +{ + void *new = NULL; + int idx = *name; + + if (bucket[idx] != NULL) + return insert_devname_internal(bucket[idx], name+1); + else if (idx == '\0') { + new = xmalloc(sizeof(void *)); + if (!new) { + pr_perror("alloc devname failed\n"); + return -1; + } + bucket[idx] = new; + return 0; + } else { + new = xmalloc(sizeof(void *) * ASCII_SIZE); + if (!new) { + pr_perror("alloc devname failed\n"); + return -1; + } + memset(new, 0, sizeof(void *) * ASCII_SIZE); + bucket[idx] = new; + return insert_devname_internal(bucket[idx], name+1); + } +} + +int insert_devname(const char *devname) +{ + if (devname == NULL || *devname == '\0') // ignore + return 0; + + pr_debug("insert device '%s'\n", devname); + return insert_devname_internal(root_bucket, devname); +} + +int parse_devname(void) +{ + int retval = -1; + char *line = NULL; + size_t len = 0; + ssize_t nread = 0; + FILE *fp = NULL; + + fp = fopen(REPAIRING_DEVICE_FILE, "r"); + if (fp == NULL) { + pr_info("Unable to open %s, downgrade to use internal whitelist\n", + REPAIRING_DEVICE_FILE); + return 0; + } + + while ((nread = getline(&line, &len, fp)) != -1) { + if (nread <= 1) // ignore empty string + continue; + + line[nread-1] = '\0'; // drop '\n' + retval = insert_devname(line); + if (retval != 0) + goto out; + } + retval = 0; + +out: + free(line); + fclose(fp); + return retval; +} + +static const char *steal_devname(const char *name, ssize_t len) +{ + ssize_t off = len; + + for (off -= 1; off > 0; off--) { + if (name[off] == '/') + break; + } + + return name + off + 1; +} + +static bool find_devname_internal(void *bucket[], const char *name) +{ + int idx = *name; + + if (*name == '\0' && bucket[idx] != NULL) + return true; + else if (bucket[idx] == NULL) + return false; + else { + return find_devname_internal(bucket[idx], name+1); + } +} + +bool find_devname(const char *name) +{ + const char *devname; + size_t len = 0; + bool found = false; + + if (name == NULL) + return false; + else if ((len = strlen(name)) == 0) + return false; + + devname = steal_devname(name, len); + found = find_devname_internal(root_bucket, devname); + + pr_debug("device '%s' (original name '%s') %s found in %s\n", + devname, name, found ? "is" : "isn't", REPAIRING_DEVICE_FILE); + + /* Compatible with the old version, there are still `strstr` branch in the following */ + found |= (strstr(name, "uverbs") != NULL + || strstr(name, "rdma_cm") != NULL + || strstr(name, "umad") != NULL); + + return found; +} diff --git a/criu/files-reg.c b/criu/files-reg.c index 4724994..ba78c67 100644 --- a/criu/files-reg.c +++ b/criu/files-reg.c @@ -1701,8 +1701,8 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p) rfe.has_mnt_id = true; }
- pr_info("Dumping path for %d fd via self %d [%s]\n", - p->fd, lfd, &link->name[1]); + pr_info("Dumping path for %d fd via self %d [%s], id: %d\n", + p->fd, lfd, &link->name[1], id);
/* * The regular path we can handle should start with slash. @@ -2366,6 +2366,34 @@ static int open_filemap(int pid, struct vma_area *vma) return 0; }
+int collect_chr_map(struct pstree_item *me, struct vma_area *vma) +{ + struct list_head *list = &rsti(me)->fds; + struct fdinfo_list_entry *fle, *tmp; + struct chrfile_info *ci; + bool exist_fd; + + list_for_each_entry_safe(fle, tmp, list, ps_list) { + struct file_desc *d = fle->desc; + + if (d->ops->type != FD_TYPES__CHR) + continue; + + ci = container_of(d, struct chrfile_info, d); + if (!strcmp(vma->e->name, ci->path)) { + vma->vmfd = d; + vma->e->fd = fle->fe->fd; + exist_fd = true; + break; + } + } + + if (!exist_fd) + return -EEXIST; + + return 0; +} + int collect_filemap(struct vma_area *vma) { struct file_desc *fd; @@ -2453,7 +2481,7 @@ static int collect_one_regfile(void *o, ProtobufCMessage *base, struct cr_img *i rfi->remap = NULL; rfi->size_mode_checked = false;
- pr_info("Collected [%s] ID %#x\n", rfi->path, rfi->rfe->id); + pr_info("Collected regfile [%s] ID %#x\n", rfi->path, rfi->rfe->id); return file_desc_add(&rfi->d, rfi->rfe->id, ®_desc_ops); }
diff --git a/criu/files.c b/criu/files.c index 6f580af..34aa8be 100644 --- a/criu/files.c +++ b/criu/files.c @@ -331,10 +331,32 @@ int do_dump_gen_file(struct fd_parms *p, int lfd, e->fd = p->fd; e->flags = p->fd_flags;
+ pr_info("fdinfoEntry fd: %d\n", e->fd); ret = fd_id_generate(p->pid, e, p); if (ret == 1) /* new ID generated */ ret = ops->dump(lfd, e->id, p); - else + else if (ops->type == FD_TYPES__CHR) { + /* + * Sometimes the app_data subprocess may inherit the fd from + * app_data. Those fds may result the unconditional oops during + * the restoration of app_data. Therefore, prevent the dump in + * those condition. + */ + struct fd_link _link, *link; + + if (!p->link) { + if (fill_fdlink(lfd, p, &_link)) + return -1; + link = &_link; + } else + link = p->link; + + if (find_devname(link->name)) { + pr_err("char dev '%s' fd %d is owned by multi-processes\n", + link->name, e->fd); + ret = -1; + } + } else /* Remove locks generated by the fd before going to the next */ discard_dup_locks_tail(p->pid, e->fd);
@@ -473,6 +495,58 @@ static int dump_blkdev(struct fd_parms *p, int lfd, FdinfoEntry *e) return err; }
+static int dump_chr_file(int lfd, u32 id, const struct fd_parms *p) +{ + int ret; + struct fd_link _link, *link; + struct cr_img *img; + FileEntry fe = FILE_ENTRY__INIT; + ChrfileEntry cfe = CHRFILE_ENTRY__INIT; + + if (!p->link) { + if (fill_fdlink(lfd, p, &_link)) + return -1; + link = &_link; + } else + link = p->link; + + pr_info("Dumping chr-file fd %d with lfd %d with id %d, name: %s\n", p->fd, lfd, id, link->name); + + if (strstr(link->name, "(deleted)") != NULL) { + pr_err("char device '%s' is deleted\n", link->name); + return -ENXIO; + } + + cfe.repair = false; + if (find_devname(link->name)) { + ret = ioctl(lfd, IOCTL_CMD_NEEDREPAIR, 0); + if (ret <= 0) { + pr_err("ioctl cmd needrepair failed, errno: %d, %s\n", ret, strerror(errno)); + return -1; + } else { + pr_info("char device needrepair cmd return: %d\n", ret); + cfe.index = ret; + cfe.repair = true; + } + } + + cfe.id = id; + cfe.name = &link->name[1]; + cfe.flags = p->flags; + fe.type = FD_TYPES__CHR; + fe.id = cfe.id; + fe.chr = &cfe; + + img = img_from_set(glob_imgset, CR_FD_FILES); + ret = pb_write_one(img, &fe, PB_FILE); + return ret; +} + +const struct fdtype_ops chr_dump_ops = { + .type = FD_TYPES__CHR, + .dump = dump_chr_file, +}; + static int dump_chrdev(struct fd_parms *p, int lfd, FdinfoEntry *e) { struct fd_link *link_old = p->link; @@ -500,6 +574,10 @@ static int dump_chrdev(struct fd_parms *p, int lfd, FdinfoEntry *e) ops = &tty_dump_ops; break; } + if (opts.dump_char_dev) { + ops = &chr_dump_ops; + break; + }
sprintf(more, "%d:%d", maj, minor(p->stat.st_rdev)); err = dump_unsupp_fd(p, lfd, "chr", more, e); @@ -513,6 +591,12 @@ static int dump_chrdev(struct fd_parms *p, int lfd, FdinfoEntry *e) return err; }
+/* Checks if file descriptor @lfd is infinibandevent */ +int is_infiniband_link(char *link) +{ + return is_anon_link_type(link, "[infinibandevent]"); +} + static int dump_one_file(struct pid *pid, int fd, int lfd, struct fd_opts *opts, struct parasite_ctl *ctl, FdinfoEntry *e, struct parasite_drain_fd *dfds) @@ -567,6 +651,8 @@ static int dump_one_file(struct pid *pid, int fd, int lfd, struct fd_opts *opts, ops = &signalfd_dump_ops; else if (is_timerfd_link(link)) ops = &timerfd_dump_ops; + else if (is_infiniband_link(link)) + return 1; #ifdef CONFIG_HAS_LIBBPF else if (is_bpfmap_link(link)) ops = &bpfmap_dump_ops; @@ -673,9 +759,15 @@ int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
ret = dump_one_file(item->pid, dfds->fds[i + off], lfds[i], opts + i, ctl, &e, dfds); - if (ret) + if (ret < 0) break; + /* infiniband link file */ + if (ret > 0) { + ret = 0; + continue; + }
+ pr_info("write fdinfoEntry fd=%d id=%d\n", (&e)->fd, (&e)->id); ret = pb_write_one(img, &e, PB_FDINFO); if (ret) break; @@ -933,6 +1025,7 @@ int prepare_fd_pid(struct pstree_item *item) if (!img) return -1;
+ pr_info("prepare_fd_pid\n"); while (1) { FdinfoEntry *e;
@@ -1140,6 +1233,7 @@ int setup_and_serve_out(struct fdinfo_list_entry *fle, int new_fd) if (reopen_fd_as(fle->fe->fd, new_fd)) return -1;
+ pr_info("*******flags: %d",fle->fe->flags); if (fcntl(fle->fe->fd, F_SETFD, fle->fe->flags) == -1) { pr_perror("Unable to set file descriptor flags"); return -1; @@ -1690,6 +1784,64 @@ out: return ret; }
+static int chrfile_open(struct file_desc *d, int *new_fd) +{ + int fd, mntns_root; + int ret = 0; + struct chrfile_info *ci; + + ci = container_of(d, struct chrfile_info, d); + + mntns_root = open_pid_proc(getpid()); + fd = openat(mntns_root, ci->path, ci->cfe->flags | O_REPAIR); + if (fd < 0){ + pr_err("open chr file failed\n"); + return -1; + } + + if (ci->cfe->repair) { + ret = ioctl(fd, IOCTL_CMD_REPAIR , ci->cfe->index); + pr_info("repair ioctl return: %d, index: %d\n", ret, ci->cfe->index); + if (ret) + goto err; + } + + *new_fd = fd; + return ret; +err: + close(fd); + return ret; +} + +static struct file_desc_ops chrfile_desc_ops = { + .type = FD_TYPES__CHR, + .open = chrfile_open, +}; + +static int collect_one_chrfile(void *o, ProtobufCMessage *base, struct cr_img *i) +{ + struct chrfile_info *ci = o; + static char dot[] = "."; + + ci->cfe = pb_msg(base, ChrfileEntry); + if (ci->cfe->name[1] == '\0') + ci->path = dot; + else + ci->path = ci->cfe->name; + + pr_info("Collected chr file: %#x, name: %s\n", ci->cfe->id, ci->path); + file_desc_add(&ci->d, ci->cfe->id, &chrfile_desc_ops); + + return 0; +} + +struct collect_image_info chrfile_cinfo = { + .fd_type = CR_FD_CHRFILE, + .pb_type = PB_CHRFILE, + .priv_size = sizeof(struct chrfile_info), + .collect = collect_one_chrfile, +}; + static int collect_one_file_entry(FileEntry *fe, u_int32_t id, ProtobufCMessage *base, struct collect_image_info *cinfo) { @@ -1770,6 +1922,9 @@ static int collect_one_file(void *o, ProtobufCMessage *base, struct cr_img *i) ret = collect_one_file_entry(fe, fe->bpf->id, &fe->bpf->base, &bpfmap_cinfo); break; #endif + case FD_TYPES__CHR: + ret = collect_one_file_entry(fe, fe->chr->id, &fe->chr->base, &chrfile_cinfo); + break; }
return ret; diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h index 5b0ff24..5ca177a 100644 --- a/criu/include/cr_options.h +++ b/criu/include/cr_options.h @@ -180,6 +180,7 @@ struct cr_options { int use_fork_pid; int with_notifier_kup; int with_fd_cred; + int dump_char_dev; };
extern struct cr_options opts; diff --git a/criu/include/files-reg.h b/criu/include/files-reg.h index 016d76a..458fe89 100644 --- a/criu/include/files-reg.h +++ b/criu/include/files-reg.h @@ -4,6 +4,7 @@ #include "files.h"
#include "images/regfile.pb-c.h" +#include "images/chr.pb-c.h" #include "images/ghost-file.pb-c.h"
struct cr_imgset; @@ -26,12 +27,19 @@ struct reg_file_info { char *path; };
+struct chrfile_info { + struct file_desc d; + ChrfileEntry *cfe; + char *path; +}; + extern int open_reg_by_id(u32 id); extern int open_reg_fd(struct file_desc *); extern int open_path(struct file_desc *, int (*open_cb)(int ns_root_fd, struct reg_file_info *, void *), void *arg);
extern const struct fdtype_ops regfile_dump_ops; +extern const struct fdtype_ops chr_dump_ops; extern int do_open_reg_noseek_flags(int ns_root_fd, struct reg_file_info *rfi, void *arg); extern int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p);
@@ -40,6 +48,7 @@ extern struct file_remap *lookup_ghost_remap(u32 dev, u32 ino); extern struct file_desc *try_collect_special_file(u32 id, int optional); #define collect_special_file(id) try_collect_special_file(id, 0) extern int collect_filemap(struct vma_area *); +extern int collect_chr_map(struct pstree_item *me, struct vma_area *); extern void filemap_ctx_init(bool auto_close); extern void filemap_ctx_fini(void);
diff --git a/criu/include/files.h b/criu/include/files.h index 2c1e1e7..b12d079 100644 --- a/criu/include/files.h +++ b/criu/include/files.h @@ -15,6 +15,12 @@ #include "images/fown.pb-c.h" #include "images/vma.pb-c.h"
+#ifndef IOCTL_CMD_NEEDREPAIR +#define IOCTL_CMD_NEEDREPAIR 0x00100000UL +#define IOCTL_CMD_REPAIR 0x00200000UL +#define O_REPAIR 040000000 +#endif + struct parasite_drain_fd; struct pstree_item; struct file_desc; diff --git a/criu/include/image-desc.h b/criu/include/image-desc.h index f69cc58..22676ae 100644 --- a/criu/include/image-desc.h +++ b/criu/include/image-desc.h @@ -114,6 +114,7 @@ enum { CR_FD_MEMFD_FILE,
CR_FD_AUTOFS, + CR_FD_CHRFILE,
CR_FD_MAX }; diff --git a/criu/include/image.h b/criu/include/image.h index 939db37..70f17a5 100644 --- a/criu/include/image.h +++ b/criu/include/image.h @@ -85,6 +85,7 @@ #define VMA_AREA_AIORING (1 << 13) #define VMA_AREA_MEMFD (1 << 14) #define VMA_AREA_ANON_INODE (1 << 15) +#define VMA_AREA_CHR (1 << 16)
#define VMA_CLOSE (1 << 28) #define VMA_NO_PROT_WRITE (1 << 29) diff --git a/criu/include/protobuf-desc.h b/criu/include/protobuf-desc.h index 35fa1a9..e7df57e 100644 --- a/criu/include/protobuf-desc.h +++ b/criu/include/protobuf-desc.h @@ -69,6 +69,7 @@ enum { PB_PIDNS, PB_BPFMAP_FILE, PB_BPFMAP_DATA, + PB_CHRFILE,
/* PB_AUTOGEN_STOP */
diff --git a/criu/include/util.h b/criu/include/util.h index d226d2c..cf9a8f4 100644 --- a/criu/include/util.h +++ b/criu/include/util.h @@ -422,4 +422,7 @@ enum notifier_state { int notifier_kup(enum KUP_HOOK_POINT, enum nvwa_cmd, bool); void do_notifier_rollback(bool, enum notifier_state);
+int parse_devname(void); +bool find_devname(const char *name); + #endif /* __CR_UTIL_H__ */ diff --git a/criu/mem.c b/criu/mem.c index dd64f10..d56f69e 100644 --- a/criu/mem.c +++ b/criu/mem.c @@ -848,7 +848,9 @@ int prepare_mm_pid(struct pstree_item *i) }
pr_info("vma 0x%"PRIx64" 0x%"PRIx64"\n", vma->e->start, vma->e->end); - if (vma_area_is(vma, VMA_ANON_SHARED)) + if (vma_area_is(vma, VMA_AREA_CHR)) + ret = collect_chr_map(i, vma); + else if (vma_area_is(vma, VMA_ANON_SHARED)) ret = collect_shmem(pid, vma); else if (vma_area_is(vma, VMA_FILE_PRIVATE) || vma_area_is(vma, VMA_FILE_SHARED)) @@ -1502,7 +1504,7 @@ int open_vmas(struct pstree_item *t) filemap_ctx_init(false);
list_for_each_entry(vma, &vmas->h, list) { - if (vma_area_is(vma, VMA_AREA_ANON_INODE)) + if (vma_area_is(vma, VMA_AREA_ANON_INODE) || vma_area_is(vma, VMA_AREA_CHR)) continue;
if (!vma_area_is(vma, VMA_AREA_REGULAR) || !vma->vm_open) diff --git a/criu/proc_parse.c b/criu/proc_parse.c index 23db7f3..4f5bbaa 100644 --- a/criu/proc_parse.c +++ b/criu/proc_parse.c @@ -622,11 +622,23 @@ static int handle_vma(pid_t pid, struct vma_area *vma_area, } else if (*vm_file_fd >= 0) { struct stat *st_buf = vma_area->vmst;
+ pr_info("file mode is: %x, st_ino: %ld\n", st_buf->st_mode, st_buf->st_ino); if (S_ISREG(st_buf->st_mode)) /* regular file mapping -- supported */; - else if (S_ISCHR(st_buf->st_mode) && (st_buf->st_rdev == DEVZERO)) + else if (S_ISCHR(st_buf->st_mode)) { /* devzero mapping -- also makes sense */; - else { + if (opts.dump_char_dev && (strstr(file_path, "uverbs") != NULL)) { + int len = strlen(file_path) + 1; + vma_area->e->status |= VMA_AREA_CHR; + vma_area->e->name = xmalloc(len); + if (!vma_area->e->name) { + pr_err("alloc vma area name fail\n"); + goto err; + } + strncpy(vma_area->e->name, file_path, len); + pr_info("uverbs name content is: %s\n", vma_area->e->name); + } + } else { pr_err("Can't handle non-regular mapping on %d's map %"PRIx64"\n", pid, vma_area->e->start); goto err; } diff --git a/images/Makefile b/images/Makefile index 34bc367..efd6fcb 100644 --- a/images/Makefile +++ b/images/Makefile @@ -70,6 +70,7 @@ proto-obj-y += timens.o proto-obj-y += img-streamer.o proto-obj-y += bpfmap-file.o proto-obj-y += bpfmap-data.o +proto-obj-y += chr.o
CFLAGS += -iquote $(obj)/
diff --git a/images/chr.proto b/images/chr.proto new file mode 100644 index 0000000..67929db --- /dev/null +++ b/images/chr.proto @@ -0,0 +1,12 @@ +syntax = "proto2"; + +import "opts.proto"; + +message chrfile_entry { + required uint32 id = 1; + required uint32 flags = 2 [(criu).flags = "rfile.flags"]; + required uint32 index = 3; + required string name = 4; + required bool repair = 5; +}; + diff --git a/images/fdinfo.proto b/images/fdinfo.proto index f5e1895..8561da4 100644 --- a/images/fdinfo.proto +++ b/images/fdinfo.proto @@ -18,6 +18,7 @@ import "pipe.proto"; import "tty.proto"; import "memfd.proto"; import "bpfmap-file.proto"; +import "chr.proto";
enum fd_types { UND = 0; @@ -40,6 +41,7 @@ enum fd_types { TIMERFD = 17; MEMFD = 18; BPFMAP = 19; + CHR = 21;
/* Any number above the real used. Not stored to image */ CTL_TTY = 65534; @@ -76,4 +78,5 @@ message file_entry { optional tty_file_entry tty = 19; optional memfd_file_entry memfd = 20; optional bpfmap_file_entry bpf = 21; + optional chrfile_entry chr = 23; }