This patch adds checkpoint and restore methods to struct proto_ops
which should allow compilation of af-unix sockets as a module. It also
simplifies the code.

Signed-off-by: Oren Laadan <[email protected]>
---
 include/linux/net.h   |    7 ++++++
 include/net/af_unix.h |   29 ++------------------------
 net/checkpoint.c      |   53 +++++++++++++++++++++++-------------------------
 net/unix/af_unix.c    |    6 +++++
 net/unix/checkpoint.c |    6 ++--
 5 files changed, 44 insertions(+), 57 deletions(-)

diff --git a/include/linux/net.h b/include/linux/net.h
index 2c4a75d..96c7e22 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -147,6 +147,9 @@ struct sockaddr;
 struct msghdr;
 struct module;
 
+struct ckpt_ctx;
+struct ckpt_hdr_socket;
+
 struct proto_ops {
        int             family;
        struct module   *owner;
@@ -191,6 +194,10 @@ struct proto_ops {
                                      int offset, size_t size, int flags);
        ssize_t         (*splice_read)(struct socket *sock,  loff_t *ppos,
                                       struct pipe_inode_info *pipe, size_t 
len, unsigned int flags);
+       int             (*checkpoint)(struct ckpt_ctx *ctx,
+                                     struct socket *sock);
+       int             (*restore)(struct ckpt_ctx *ctx, struct socket *sock,
+                                  struct ckpt_hdr_socket *h);
 };
 
 struct net_proto_family {
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 35b5b9c..e265e9e 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -72,32 +72,9 @@ static inline void unix_sysctl_unregister(struct net *net) {}
 #ifdef CONFIG_CHECKPOINT
 struct ckpt_ctx;
 struct ckpt_hdr_socket;
-
-#ifdef CONFIG_UNIX_MODULE
-/* FIXME: Our current scheme won't work with CONFIG_UNIX=m */
-#error "CONFIG_UNIX=m not currently supported by CONFIG_CHECKPOINT"
-#endif
-
-#ifdef CONFIG_UNIX
-extern int sock_unix_checkpoint(struct ckpt_ctx *ctx, struct socket *socket);
-extern int sock_unix_restore(struct ckpt_ctx *ctx,
-                            struct ckpt_hdr_socket *h,
-                            struct socket *socket);
-#else
-static inline int sock_unix_checkpoint(struct ckpt_ctx *ctx,
-                                      struct socket *socket,
-                                      struct ckpt_hdr_socket *h)
-{
-       return -ENOSYS;
-}
-
-static inline int sock_unix_restore(struct ckpt_ctx *ctx,
-                                   struct ckpt_hdr_socket *h,
-                                   struct socket *socket)
-{
-       return -ENOSYS;
-}
-#endif /* CONFIG_UNIX */
+extern int sock_unix_checkpoint(struct ckpt_ctx *ctx, struct socket *sock);
+extern int sock_unix_restore(struct ckpt_ctx *ctx, struct socket *sock,
+                            struct ckpt_hdr_socket *h);
 #endif /* CONFIG_CHECKPOINT */
 
 #endif
diff --git a/net/checkpoint.c b/net/checkpoint.c
index b97cb89..9f92d7a 100644
--- a/net/checkpoint.c
+++ b/net/checkpoint.c
@@ -326,10 +326,15 @@ static int sock_cptrst(struct ckpt_ctx *ctx,
 int sock_file_checkpoint(struct ckpt_ctx *ctx, struct file *file)
 {
        struct ckpt_hdr_file_socket *h;
-       struct socket *socket = file->private_data;
-       struct sock *sock = socket->sk;
+       struct socket *sock = file->private_data;
+       struct sock *sk = sock->sk;
        int ret;
 
+       if (!sock->ops->checkpoint) {
+               ckpt_write_err(ctx, "socket (proto_ops: %pS)", sock->ops);
+               return -ENOSYS;
+       }
+
        h = ckpt_hdr_get_type(ctx, sizeof(*h), CKPT_HDR_FILE);
        if (!h)
                return -ENOMEM;
@@ -337,7 +342,7 @@ int sock_file_checkpoint(struct ckpt_ctx *ctx, struct file 
*file)
        h->common.f_type = CKPT_FILE_SOCKET;
 
        /* part I: common to all sockets */
-       ret = sock_cptrst(ctx, sock, &h->socket, CKPT_CPT);
+       ret = sock_cptrst(ctx, sk, &h->socket, CKPT_CPT);
        if (ret < 0)
                goto out;
        ret = checkpoint_file_common(ctx, file, &h->common);
@@ -348,22 +353,16 @@ int sock_file_checkpoint(struct ckpt_ctx *ctx, struct 
file *file)
                goto out;
 
        /* part II: per socket type state */
-       if (sock->sk_family == AF_UNIX) {
-               ret = sock_unix_checkpoint(ctx, socket);
-       } else {
-               ckpt_write_err(ctx, "unsupported socket family %i",
-                              sock->sk_family);
-               ret = -ENOSYS;
-       }
+       ret = sock->ops->checkpoint(ctx, sock);
        if (ret < 0)
                goto out;
 
        /* part III: socket buffers */
-       if (sock->sk_state != TCP_LISTEN) {
-               ret = sock_write_buffers(ctx, &sock->sk_receive_queue);
+       if (sk->sk_state != TCP_LISTEN) {
+               ret = sock_write_buffers(ctx, &sk->sk_receive_queue);
                if (ret)
                        goto out;
-               ret = sock_write_buffers(ctx, &sock->sk_write_queue);
+               ret = sock_write_buffers(ctx, &sk->sk_write_queue);
        }
  out:
        ckpt_hdr_put(ctx, h);
@@ -428,7 +427,7 @@ struct file *sock_file_restore(struct ckpt_ctx *ctx, struct 
ckpt_hdr_file *ptr)
 {
        struct ckpt_hdr_file_socket *hh = (struct ckpt_hdr_file_socket *) ptr;
        struct ckpt_hdr_socket *h = &hh->socket;
-       struct socket *socket;
+       struct socket *sock;
        struct file *file;
        int ret;
 
@@ -436,35 +435,33 @@ struct file *sock_file_restore(struct ckpt_ctx *ctx, 
struct ckpt_hdr_file *ptr)
            ptr->h.len != sizeof(*hh) || ptr->f_type != CKPT_FILE_SOCKET)
                return ERR_PTR(-EINVAL);
 
-       if ((h->sock.type != SOCK_DGRAM) && (h->sock.type != SOCK_STREAM)) {
-               ckpt_debug("Socket type %i not supported", h->sock.type);
+       if (h->sock.type & ~SOCK_TYPE_MASK)
                return ERR_PTR(-EINVAL);
-       }
 
-       ret = sock_create(h->sock_common.family, h->sock.type, 0, &socket);
+       ret = sock_create(h->sock_common.family, h->sock.type, 0, &sock);
        if (ret < 0)
                return ERR_PTR(ret);
 
+       if (!sock->ops->restore) {
+               ckpt_debug("proto_ops lacks checkpoint: %pS\n", sock->ops);
+               ret = -EINVAL;
+               goto err;
+       }
+
        /*
         * part II: per socket type state
         * (also takes care of part III: socket buffer)
         */
-       if (h->sock_common.family == AF_UNIX) {
-               ret = sock_unix_restore(ctx, h, socket);
-               ckpt_debug("sock_unix_restore: %i\n", ret);
-       } else {
-               ckpt_debug("unsupported family %i\n", h->sock_common.family);
-               ret = -ENOSYS;
-       }
+       ret = sock->ops->restore(ctx, sock, h);
        if (ret < 0)
                goto err;
 
        /* part I: common to all sockets */
-       ret = sock_cptrst(ctx, socket->sk, h, CKPT_RST);
+       ret = sock_cptrst(ctx, sock->sk, h, CKPT_RST);
        if (ret < 0)
                goto err;
 
-       file = sock_alloc_attach_fd(socket);
+       file = sock_alloc_attach_fd(sock);
        if (IS_ERR(file)) {
                ret = PTR_ERR(file);
                goto err;
@@ -478,7 +475,7 @@ struct file *sock_file_restore(struct ckpt_ctx *ctx, struct 
ckpt_hdr_file *ptr)
        return file;
 
  err:
-       sock_release(socket);
+       sock_release(sock);
        return ERR_PTR(ret);
 }
 
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index fc3ebb9..667397d 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -523,6 +523,8 @@ static const struct proto_ops unix_stream_ops = {
        .recvmsg =      unix_stream_recvmsg,
        .mmap =         sock_no_mmap,
        .sendpage =     sock_no_sendpage,
+       .checkpoint =   sock_unix_checkpoint,
+       .restore =      sock_unix_restore,
 };
 
 static const struct proto_ops unix_dgram_ops = {
@@ -544,6 +546,8 @@ static const struct proto_ops unix_dgram_ops = {
        .recvmsg =      unix_dgram_recvmsg,
        .mmap =         sock_no_mmap,
        .sendpage =     sock_no_sendpage,
+       .checkpoint =   sock_unix_checkpoint,
+       .restore =      sock_unix_restore,
 };
 
 static const struct proto_ops unix_seqpacket_ops = {
@@ -565,6 +569,8 @@ static const struct proto_ops unix_seqpacket_ops = {
        .recvmsg =      unix_dgram_recvmsg,
        .mmap =         sock_no_mmap,
        .sendpage =     sock_no_sendpage,
+       .checkpoint =   sock_unix_checkpoint,
+       .restore =      sock_unix_restore,
 };
 
 static struct proto unix_proto = {
diff --git a/net/unix/checkpoint.c b/net/unix/checkpoint.c
index 69fdcf1..d2431a4 100644
--- a/net/unix/checkpoint.c
+++ b/net/unix/checkpoint.c
@@ -472,9 +472,9 @@ static int sock_unix_precheck(struct socket *socket,
        return 0;
 }
 
-int sock_unix_restore(struct ckpt_ctx *ctx,
-                     struct ckpt_hdr_socket *h,
-                     struct socket *socket)
+int sock_unix_restore(struct ckpt_ctx *ctx, struct socket *socket,
+                     struct ckpt_hdr_socket *h)
+
 {
        struct ckpt_hdr_socket_unix *un;
        int ret = -EINVAL;
-- 
1.6.0.4

_______________________________________________
Containers mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/containers

_______________________________________________
Devel mailing list
[email protected]
https://openvz.org/mailman/listinfo/devel

Reply via email to