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 <xemul@parallels.com>
This commit is contained in:
Pavel Emelyanov 2012-08-02 12:26:35 +04:00
parent 8097a8dc09
commit da409cc641
8 changed files with 169 additions and 0 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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;

View file

@ -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),

View file

@ -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,

View file

@ -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 */

10
include/signalfd.h Normal file
View file

@ -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

147
signalfd.c Normal file
View file

@ -0,0 +1,147 @@
#include <unistd.h>
#include <signal.h>
#include <sys/signalfd.h>
#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;
}