From: Matt Helsley <matth...@us.ibm.com>

Save/restore eventfd files. These are anon_inodes just like epoll
but instead of a set of files to poll they are a 64-bit counter
and a flag value. Used for AIO.

[Oren Laadan] Added #ifdef's around checkpoint/restart to compile even
without CONFIG_CHECKPOINT

Changelog[v19]:
  - Fix broken compilation for architectures that don't support c/r

Signed-off-by: Matt Helsley <matth...@us.ibm.com>
Acked-by: Oren Laadan <or...@cs.columbia.edu>
Acked-by: Serge E. Hallyn <se...@us.ibm.com>
Tested-by: Serge E. Hallyn <se...@us.ibm.com>
---
 checkpoint/files.c             |    7 +++++
 fs/eventfd.c                   |   55 ++++++++++++++++++++++++++++++++++++++++
 include/linux/checkpoint_hdr.h |    8 ++++++
 include/linux/eventfd.h        |   12 ++++++++
 4 files changed, 82 insertions(+), 0 deletions(-)

diff --git a/checkpoint/files.c b/checkpoint/files.c
index 6aaaf22..4b551fe 100644
--- a/checkpoint/files.c
+++ b/checkpoint/files.c
@@ -23,6 +23,7 @@
 #include <linux/checkpoint.h>
 #include <linux/checkpoint_hdr.h>
 #include <linux/eventpoll.h>
+#include <linux/eventfd.h>
 #include <net/sock.h>
 
 
@@ -644,6 +645,12 @@ static struct restore_file_ops restore_file_ops[] = {
                .file_type = CKPT_FILE_EPOLL,
                .restore = ep_file_restore,
        },
+       /* eventfd */
+       {
+               .file_name = "EVENTFD",
+               .file_type = CKPT_FILE_EVENTFD,
+               .restore = eventfd_restore,
+       },
 };
 
 static struct file *do_restore_file(struct ckpt_ctx *ctx)
diff --git a/fs/eventfd.c b/fs/eventfd.c
index 7758cc3..f2785c0 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/kref.h>
 #include <linux/eventfd.h>
+#include <linux/checkpoint.h>
 
 struct eventfd_ctx {
        struct kref kref;
@@ -287,11 +288,65 @@ static ssize_t eventfd_write(struct file *file, const 
char __user *buf, size_t c
        return res;
 }
 
+#ifdef CONFIG_CHECKPOINT
+static int eventfd_checkpoint(struct ckpt_ctx *ckpt_ctx, struct file *file)
+{
+       struct eventfd_ctx *ctx;
+       struct ckpt_hdr_file_eventfd *h;
+       int ret = -ENOMEM;
+
+       h = ckpt_hdr_get_type(ckpt_ctx, sizeof(*h), CKPT_HDR_FILE);
+       if (!h)
+               return -ENOMEM;
+       h->common.f_type = CKPT_FILE_EVENTFD;
+       ret = checkpoint_file_common(ckpt_ctx, file, &h->common);
+       if (ret < 0)
+               goto out;
+       ctx = file->private_data;
+       h->count = ctx->count;
+       h->flags = ctx->flags;
+       ret = ckpt_write_obj(ckpt_ctx, &h->common.h);
+out:
+       ckpt_hdr_put(ckpt_ctx, h);
+       return ret;
+}
+
+struct file *eventfd_restore(struct ckpt_ctx *ckpt_ctx,
+                            struct ckpt_hdr_file *ptr)
+{
+       struct ckpt_hdr_file_eventfd *h = (struct ckpt_hdr_file_eventfd *) ptr;
+       struct file *evfile;
+       int evfd, ret;
+
+       /* Already know type == CKPT_HDR_FILE and f_type == CKPT_FILE_EVENTFD */
+       if (h->common.h.len != sizeof(*h))
+               return ERR_PTR(-EINVAL);
+
+       evfd = sys_eventfd2(h->count, h->flags);
+       if (evfd < 0)
+               return ERR_PTR(evfd);
+       evfile = fget(evfd);
+       sys_close(evfd);
+       if (!evfile)
+               return ERR_PTR(-EBUSY);
+
+       ret = restore_file_common(ckpt_ctx, evfile, &h->common);
+       if (ret < 0) {
+               fput(evfile);
+               return ERR_PTR(ret);
+       }
+       return evfile;
+}
+#else
+#define eventfd_checkpoint NULL
+#endif
+
 static const struct file_operations eventfd_fops = {
        .release        = eventfd_release,
        .poll           = eventfd_poll,
        .read           = eventfd_read,
        .write          = eventfd_write,
+       .checkpoint     = eventfd_checkpoint,
 };
 
 /**
diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
index b96d2dc..0b36430 100644
--- a/include/linux/checkpoint_hdr.h
+++ b/include/linux/checkpoint_hdr.h
@@ -481,6 +481,8 @@ enum file_type {
 #define CKPT_FILE_TTY CKPT_FILE_TTY
        CKPT_FILE_EPOLL,
 #define CKPT_FILE_EPOLL CKPT_FILE_EPOLL
+       CKPT_FILE_EVENTFD,
+#define CKPT_FILE_EVENTFD CKPT_FILE_EVENTFD
        CKPT_FILE_MAX
 #define CKPT_FILE_MAX CKPT_FILE_MAX
 };
@@ -505,6 +507,12 @@ struct ckpt_hdr_file_pipe {
        __s32 pipe_objref;
 } __attribute__((aligned(8)));
 
+struct ckpt_hdr_file_eventfd {
+       struct ckpt_hdr_file common;
+       __u64 count;
+       __u32 flags;
+} __attribute__((aligned(8)));
+
 /* socket */
 struct ckpt_hdr_socket {
        struct ckpt_hdr h;
diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h
index 91bb4f2..2ce8525 100644
--- a/include/linux/eventfd.h
+++ b/include/linux/eventfd.h
@@ -39,6 +39,16 @@ ssize_t eventfd_ctx_read(struct eventfd_ctx *ctx, int 
no_wait, __u64 *cnt);
 int eventfd_ctx_remove_wait_queue(struct eventfd_ctx *ctx, wait_queue_t *wait,
                                  __u64 *cnt);
 
+#ifdef CONFIG_CHECKPOINT
+struct ckpt_ctx;
+struct ckpt_hdr_file;
+
+struct file *eventfd_restore(struct ckpt_ctx *ckpt_ctx,
+                            struct ckpt_hdr_file *ptr);
+#else
+#define eventfd_restore NULL
+#endif
+
 #else /* CONFIG_EVENTFD */
 
 /*
@@ -77,6 +87,8 @@ static inline int eventfd_ctx_remove_wait_queue(struct 
eventfd_ctx *ctx,
        return -ENOSYS;
 }
 
+#define eventfd_restore NULL
+
 #endif
 
 #endif /* _LINUX_EVENTFD_H */
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-api" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to