From da409cc6416fcc05c3593404a78df3b7d34cd384 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Thu, 2 Aug 2012 12:26:35 +0400 Subject: [PATCH] signalfd: Dumping and restoring Only the fact of the fd presence, its flags and fown and the sigmask. The sigpending state is tightly coupled with the task's sigpending state which is not yet supported. Signed-off-by: Pavel Emelyanov --- Makefile | 1 + cr-dump.c | 3 + cr-restore.c | 4 ++ image.c | 2 + include/crtools.h | 1 + include/image.h | 1 + include/signalfd.h | 10 +++ signalfd.c | 147 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 169 insertions(+) create mode 100644 include/signalfd.h create mode 100644 signalfd.c diff --git a/Makefile b/Makefile index 0ac83ead7..7b2cc3b5b 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,7 @@ OBJS += eventfd.o OBJS += eventpoll.o OBJS += mount.o OBJS += inotify.o +OBJS += signalfd.o OBJS += pstree.o OBJS += protobuf.o diff --git a/cr-dump.c b/cr-dump.c index 3d9d30d0f..6b445d4a8 100644 --- a/cr-dump.c +++ b/cr-dump.c @@ -44,6 +44,7 @@ #include "eventfd.h" #include "eventpoll.h" #include "inotify.h" +#include "signalfd.h" #include "pstree.h" #include "mount.h" @@ -291,6 +292,8 @@ static int dump_one_file(pid_t pid, int fd, int lfd, char fd_flags, return dump_eventpoll(&p, lfd, cr_fdset); else if (is_inotify_link(lfd)) return dump_inotify(&p, lfd, cr_fdset); + else if (is_signalfd_link(lfd)) + return dump_signalfd(&p, lfd, cr_fdset); else return dump_unsupp_fd(&p); } diff --git a/cr-restore.c b/cr-restore.c index 148eeb6d5..3febf25ca 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -40,6 +40,7 @@ #include "sk-inet.h" #include "eventfd.h" #include "eventpoll.h" +#include "signalfd.h" #include "proc_parse.h" #include "restorer-blob.h" #include "crtools.h" @@ -107,6 +108,9 @@ static int prepare_shared(void) if (collect_eventpoll()) return -1; + if (collect_signalfd()) + return -1; + if (collect_inotify()) return -1; diff --git a/image.c b/image.c index bcca98c95..725f33409 100644 --- a/image.c +++ b/image.c @@ -3,6 +3,7 @@ #include "crtools.h" #include "image.h" #include "eventpoll.h" +#include "signalfd.h" #include "inotify.h" #include "sockets.h" #include "uts_ns.h" @@ -92,6 +93,7 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = { FD_ENTRY(EVENTFD, "eventfd", show_eventfds), FD_ENTRY(EVENTPOLL, "eventpoll", show_eventpoll), FD_ENTRY(EVENTPOLL_TFD, "eventpoll-tfd", show_eventpoll_tfd), + FD_ENTRY(SIGNALFD, "signalfd", show_signalfd), FD_ENTRY(INOTIFY, "inotify", show_inotify), FD_ENTRY(INOTIFY_WD, "inotify-wd", show_inotify_wd), FD_ENTRY(CORE, "core-%d", show_core), diff --git a/include/crtools.h b/include/crtools.h index 6fda2cdd7..d346a03c1 100644 --- a/include/crtools.h +++ b/include/crtools.h @@ -69,6 +69,7 @@ enum { CR_FD_EVENTFD, CR_FD_EVENTPOLL, CR_FD_EVENTPOLL_TFD, + CR_FD_SIGNALFD, CR_FD_INOTIFY, CR_FD_INOTIFY_WD, _CR_FD_GLOB_TO, diff --git a/include/image.h b/include/image.h index e8a5c6e37..345edc553 100644 --- a/include/image.h +++ b/include/image.h @@ -53,6 +53,7 @@ #define EVENTFD_MAGIC 0x44523722 /* Anapa */ #define EVENTPOLL_MAGIC 0x45023858 /* Krasnodar */ #define EVENTPOLL_TFD_MAGIC 0x44433746 /* Novorossiysk */ +#define SIGNALFD_MAGIC 0x57323820 /* Uglich */ #define INOTIFY_MAGIC 0x48424431 /* Volgograd */ #define INOTIFY_WD_MAGIC 0x54562009 /* Svetlogorsk (Rauschen) */ #define MOUNTPOINTS_MAGIC 0x55563928 /* Petushki */ diff --git a/include/signalfd.h b/include/signalfd.h new file mode 100644 index 000000000..9721a4dbb --- /dev/null +++ b/include/signalfd.h @@ -0,0 +1,10 @@ +#ifndef __CR_SIGNALFD_H__ +#define __CR_SIGNALFD_H__ +struct cr_fdset; +struct fd_parms; +struct cr_options; +extern int is_signalfd_link(int lfd); +extern int dump_signalfd(struct fd_parms *p, int lfd, const struct cr_fdset *set); +extern void show_signalfd(int fd, struct cr_options *o); +extern int collect_signalfd(void); +#endif diff --git a/signalfd.c b/signalfd.c new file mode 100644 index 000000000..1018a4a68 --- /dev/null +++ b/signalfd.c @@ -0,0 +1,147 @@ +#include +#include +#include + +#include "compiler.h" +#include "types.h" +#include "signalfd.h" +#include "proc_parse.h" +#include "crtools.h" +#include "image.h" +#include "util.h" +#include "log.h" +#include "files.h" + +#include "protobuf.h" +#include "protobuf/signalfd.pb-c.h" + +struct signalfd_info { + SignalfdEntry *sfe; + struct file_desc d; +}; + +int is_signalfd_link(int lfd) +{ + return is_anon_link_type(lfd, "[signalfd]"); +} + +struct signalfd_dump_arg { + u32 id; + const struct fd_parms *p; + bool dumped; +}; + +void show_signalfd(int fd, struct cr_options *o) +{ + pb_show_plain(fd, signalfd_entry); +} + +static int dump_signalfd_entry(union fdinfo_entries *e, void *arg) +{ + struct signalfd_dump_arg *da = arg; + + if (da->dumped) { + pr_err("Several counters in a file?\n"); + return -1; + } + + da->dumped = true; + e->sfd.id = da->id; + e->sfd.flags = da->p->flags; + e->sfd.fown = (FownEntry *)&da->p->fown; + + return pb_write(fdset_fd(glob_fdset, CR_FD_SIGNALFD), + &e->sfd, signalfd_entry); +} + +static int dump_one_signalfd(int lfd, u32 id, const struct fd_parms *p) +{ + struct signalfd_dump_arg da = { .id = id, .p = p, }; + return parse_fdinfo(lfd, FD_TYPES__SIGNALFD, dump_signalfd_entry, &da); +} + +static const struct fdtype_ops signalfd_ops = { + .type = FD_TYPES__SIGNALFD, + .make_gen_id = make_gen_id, + .dump = dump_one_signalfd, +}; + +int dump_signalfd(struct fd_parms *p, int lfd, const struct cr_fdset *set) +{ + return do_dump_gen_file(p, lfd, &signalfd_ops, set); +} + +static void sigset_fill(sigset_t *to, unsigned long long from) +{ + int sig; + + pr_info("\tCalculating sigmask for %Lx\n", from); + sigemptyset(to); + for (sig = 1; sig < NSIG; sig++) + if (from & (1ULL << (sig - 1))) { + pr_debug("\t\tAdd %d signal to mask\n", sig); + sigaddset(to, sig); + } +} + +static int signalfd_open(struct file_desc *d) +{ + struct signalfd_info *info; + int tmp; + sigset_t mask; + + info = container_of(d, struct signalfd_info, d); + pr_info("Restoring signalfd %#x\n", info->sfe->id); + + sigset_fill(&mask, info->sfe->sigmask); + tmp = signalfd(-1, &mask, 0); + if (tmp < 0) { + pr_perror("Can't create signalfd %#08x", info->sfe->id); + return -1; + } + + if (rst_file_params(tmp, info->sfe->fown, info->sfe->flags)) { + pr_perror("Can't restore params on signalfd %#08x", + info->sfe->id); + goto err_close; + } + + return tmp; + +err_close: + close(tmp); + return -1; +} + +static struct file_desc_ops signalfd_desc_ops = { + .type = FD_TYPES__SIGNALFD, + .open = signalfd_open, +}; + +int collect_signalfd(void) +{ + struct signalfd_info *info = NULL; + int ret, image_fd; + + image_fd = open_image_ro(CR_FD_SIGNALFD); + if (image_fd < 0) + return -1; + + while (1) { + ret = -1; + info = xmalloc(sizeof(*info)); + if (!info) + break; + + ret = pb_read_eof(image_fd, &info->sfe, signalfd_entry); + if (ret <= 0) + break; + + file_desc_add(&info->d, info->sfe->id, &signalfd_desc_ops); + } + + xfree(info ? info->sfe : NULL); + xfree(info); + close(image_fd); + return ret; +}