kernel_builddir=$kernel_stuffdir/build
kernel_out=$kernel_outpath/kernel
-kernel_version=4.10
+kernel_version=4.15
kernel_name=linux-$kernel_version
kernel_tarball="$kernel_name".tar.xz
kernel_url=https://www.kernel.org/pub/linux/kernel/v4.x/"$kernel_tarball"
--- /dev/null
+From b2d2494d918609daa252ed8cfa486fa65c8ece1b Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <sstabellini@kernel.org>
+Date: Mon, 26 Feb 2018 17:24:57 -0800
+Subject: [PATCH 1/4] patch pvcalls_enable
+
+---
+ drivers/xen/Makefile | 1 +
+ drivers/xen/pvcalls.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ include/xen/pvcalls.h | 13 ++++++
+ net/ipv4/af_inet.c | 7 ++-
+ 4 files changed, 143 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/xen/pvcalls.c
+ create mode 100644 include/xen/pvcalls.h
+
+diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
+index 451e833..87352a8 100644
+--- a/drivers/xen/Makefile
++++ b/drivers/xen/Makefile
+@@ -38,6 +38,7 @@ obj-$(CONFIG_XEN_SCSI_BACKEND) += xen-scsiback.o
+ obj-$(CONFIG_XEN_AUTO_XLATE) += xlate_mmu.o
+ obj-$(CONFIG_XEN_PVCALLS_BACKEND) += pvcalls-back.o
+ obj-$(CONFIG_XEN_PVCALLS_FRONTEND) += pvcalls-front.o
++obj-$(CONFIG_XEN_PVCALLS_FRONTEND) += pvcalls.o
+ xen-evtchn-y := evtchn.o
+ xen-gntdev-y := gntdev.o
+ xen-gntalloc-y := gntalloc.o
+diff --git a/drivers/xen/pvcalls.c b/drivers/xen/pvcalls.c
+new file mode 100644
+index 0000000..b5cb160c
+--- /dev/null
++++ b/drivers/xen/pvcalls.c
+@@ -0,0 +1,123 @@
++#include <linux/types.h>
++#include <linux/bitops.h>
++#include <linux/cred.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/kmod.h>
++#include <linux/list.h>
++#include <linux/miscdevice.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/net.h>
++#include <linux/poll.h>
++#include <linux/skbuff.h>
++#include <linux/smp.h>
++#include <linux/socket.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/wait.h>
++#include <linux/workqueue.h>
++#include <net/sock.h>
++#include <net/inet_common.h>
++
++#include "pvcalls-front.h"
++
++static int
++pvcalls_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
++{
++ int ret;
++ ret = pvcalls_front_socket(sock);
++ if (ret < 0)
++ return ret;
++ return pvcalls_front_bind(sock, addr, addr_len);
++}
++
++static int pvcalls_stream_connect(struct socket *sock, struct sockaddr *addr,
++ int addr_len, int flags)
++{
++ int ret;
++ ret = pvcalls_front_socket(sock);
++ if (ret < 0)
++ return ret;
++ return pvcalls_front_connect(sock, addr, addr_len, flags);
++}
++
++static int pvcalls_accept(struct socket *sock, struct socket *newsock, int flags, bool kern)
++{
++ return pvcalls_front_accept(sock, newsock, flags);
++}
++
++static int pvcalls_getname(struct socket *sock,
++ struct sockaddr *uaddr, int *uaddr_len, int peer)
++{
++ DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr);
++
++ sin->sin_family = AF_INET;
++ memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
++ *uaddr_len = sizeof(*sin);
++ return 0;
++}
++
++static unsigned int pvcalls_poll(struct file *file, struct socket *sock,
++ poll_table *wait)
++{
++ return pvcalls_front_poll(file, sock, wait);
++}
++
++static int pvcalls_listen(struct socket *sock, int backlog)
++{
++ return pvcalls_front_listen(sock, backlog);
++}
++
++static int pvcalls_stream_sendmsg(struct socket *sock, struct msghdr *msg,
++ size_t len)
++{
++ return pvcalls_front_sendmsg(sock, msg, len);
++}
++
++static int
++pvcalls_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
++ int flags)
++{
++ return pvcalls_front_recvmsg(sock, msg, len, flags);
++}
++
++static int pvcalls_release(struct socket *s)
++{
++ return pvcalls_front_release(s);
++}
++
++static int pvcalls_shutdown(struct socket *s, int h)
++{
++ return -ENOTSUPP;
++}
++
++const struct proto_ops pvcalls_stream_ops = {
++ .family = PF_INET,
++ .owner = THIS_MODULE,
++ .release = pvcalls_release,
++ .bind = pvcalls_bind,
++ .connect = pvcalls_stream_connect,
++ .socketpair = sock_no_socketpair,
++ .accept = pvcalls_accept,
++ .getname = pvcalls_getname,
++ .poll = pvcalls_poll,
++ .ioctl = sock_no_ioctl,
++ .listen = pvcalls_listen,
++ .shutdown = pvcalls_shutdown,
++ .setsockopt = sock_no_setsockopt,
++ .getsockopt = sock_no_getsockopt,
++ .sendmsg = pvcalls_stream_sendmsg,
++ .recvmsg = pvcalls_stream_recvmsg,
++ .mmap = sock_no_mmap,
++ .sendpage = sock_no_sendpage,
++};
++
++bool pvcalls = false;
++static __init int xen_parse_pvcalls(char *arg)
++{
++ pvcalls = true;
++ return 0;
++}
++early_param("pvcalls", xen_parse_pvcalls);
+diff --git a/include/xen/pvcalls.h b/include/xen/pvcalls.h
+new file mode 100644
+index 0000000..7a61475
+--- /dev/null
++++ b/include/xen/pvcalls.h
+@@ -0,0 +1,13 @@
++#ifndef __LINUX_NET_PVCALLS_H
++#define __LINUX_NET_PVCALLS_H
++
++#include <linux/net.h>
++
++#ifdef CONFIG_XEN_PVCALLS_FRONTEND
++extern bool pvcalls;
++#else
++#define pvcalls (0)
++#endif
++extern const struct proto_ops pvcalls_stream_ops;
++
++#endif
+diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
+index f00499a..6dc38c0 100644
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -120,7 +120,7 @@
+ #include <linux/mroute.h>
+ #endif
+ #include <net/l3mdev.h>
+-
++#include <xen/pvcalls.h>
+
+ /* The inetsw table contains everything that inet_create needs to
+ * build a new socket.
+@@ -1869,6 +1869,11 @@ static int __init inet_init(void)
+ for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)
+ INIT_LIST_HEAD(r);
+
++ if (pvcalls) {
++ pr_info("Enabling pvcalls for AF_INET SOCK_STREAM\n");
++ inetsw_array[0].ops = &pvcalls_stream_ops;
++ }
++
+ for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)
+ inet_register_protosw(q);
+
+--
+1.9.1
+
+++ /dev/null
-From 9e0245ab50894954d1e43c5b6519def29cbf0dad Mon Sep 17 00:00:00 2001
-From: Stefano Stabellini <sstabellini@kernel.org>
-Date: Wed, 5 Apr 2017 12:03:55 -0700
-Subject: [PATCH 1/8] xen: import new ring macros in ring.h
-
-Sync the ring.h file with upstream Xen, to introduce the new ring macros.
-They will be used by the Xen transport for 9pfs.
-
-CC: konrad.wilk@oracle.com
-CC: boris.ostrovsky@oracle.com
-CC: jgross@suse.com
-CC: groug@kaod.org
-
-Signed-off-by: Stefano Stabellini <stefano@aporeto.com>
-Acked-by: Juergen Gross <jgross@suse.com>
-Signed-off-by: Juergen Gross <jgross@suse.com>
----
- include/xen/interface/io/ring.h | 143 ++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 143 insertions(+)
-
-diff --git a/include/xen/interface/io/ring.h b/include/xen/interface/io/ring.h
-index 21f4fbd..c794568 100644
---- a/include/xen/interface/io/ring.h
-+++ b/include/xen/interface/io/ring.h
-@@ -283,4 +283,147 @@ struct __name##_back_ring { \
- (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
- } while (0)
-
-+
-+/*
-+ * DEFINE_XEN_FLEX_RING_AND_INTF defines two monodirectional rings and
-+ * functions to check if there is data on the ring, and to read and
-+ * write to them.
-+ *
-+ * DEFINE_XEN_FLEX_RING is similar to DEFINE_XEN_FLEX_RING_AND_INTF, but
-+ * does not define the indexes page. As different protocols can have
-+ * extensions to the basic format, this macro allow them to define their
-+ * own struct.
-+ *
-+ * XEN_FLEX_RING_SIZE
-+ * Convenience macro to calculate the size of one of the two rings
-+ * from the overall order.
-+ *
-+ * $NAME_mask
-+ * Function to apply the size mask to an index, to reduce the index
-+ * within the range [0-size].
-+ *
-+ * $NAME_read_packet
-+ * Function to read data from the ring. The amount of data to read is
-+ * specified by the "size" argument.
-+ *
-+ * $NAME_write_packet
-+ * Function to write data to the ring. The amount of data to write is
-+ * specified by the "size" argument.
-+ *
-+ * $NAME_get_ring_ptr
-+ * Convenience function that returns a pointer to read/write to the
-+ * ring at the right location.
-+ *
-+ * $NAME_data_intf
-+ * Indexes page, shared between frontend and backend. It also
-+ * contains the array of grant refs.
-+ *
-+ * $NAME_queued
-+ * Function to calculate how many bytes are currently on the ring,
-+ * ready to be read. It can also be used to calculate how much free
-+ * space is currently on the ring (XEN_FLEX_RING_SIZE() -
-+ * $NAME_queued()).
-+ */
-+
-+#ifndef XEN_PAGE_SHIFT
-+/* The PAGE_SIZE for ring protocols and hypercall interfaces is always
-+ * 4K, regardless of the architecture, and page granularity chosen by
-+ * operating systems.
-+ */
-+#define XEN_PAGE_SHIFT 12
-+#endif
-+#define XEN_FLEX_RING_SIZE(order) \
-+ (1UL << ((order) + XEN_PAGE_SHIFT - 1))
-+
-+#define DEFINE_XEN_FLEX_RING(name) \
-+static inline RING_IDX name##_mask(RING_IDX idx, RING_IDX ring_size) \
-+{ \
-+ return idx & (ring_size - 1); \
-+} \
-+ \
-+static inline unsigned char *name##_get_ring_ptr(unsigned char *buf, \
-+ RING_IDX idx, \
-+ RING_IDX ring_size) \
-+{ \
-+ return buf + name##_mask(idx, ring_size); \
-+} \
-+ \
-+static inline void name##_read_packet(void *opaque, \
-+ const unsigned char *buf, \
-+ size_t size, \
-+ RING_IDX masked_prod, \
-+ RING_IDX *masked_cons, \
-+ RING_IDX ring_size) \
-+{ \
-+ if (*masked_cons < masked_prod || \
-+ size <= ring_size - *masked_cons) { \
-+ memcpy(opaque, buf + *masked_cons, size); \
-+ } else { \
-+ memcpy(opaque, buf + *masked_cons, ring_size - *masked_cons); \
-+ memcpy((unsigned char *)opaque + ring_size - *masked_cons, buf, \
-+ size - (ring_size - *masked_cons)); \
-+ } \
-+ *masked_cons = name##_mask(*masked_cons + size, ring_size); \
-+} \
-+ \
-+static inline void name##_write_packet(unsigned char *buf, \
-+ const void *opaque, \
-+ size_t size, \
-+ RING_IDX *masked_prod, \
-+ RING_IDX masked_cons, \
-+ RING_IDX ring_size) \
-+{ \
-+ if (*masked_prod < masked_cons || \
-+ size <= ring_size - *masked_prod) { \
-+ memcpy(buf + *masked_prod, opaque, size); \
-+ } else { \
-+ memcpy(buf + *masked_prod, opaque, ring_size - *masked_prod); \
-+ memcpy(buf, (unsigned char *)opaque + (ring_size - *masked_prod), \
-+ size - (ring_size - *masked_prod)); \
-+ } \
-+ *masked_prod = name##_mask(*masked_prod + size, ring_size); \
-+} \
-+ \
-+static inline RING_IDX name##_queued(RING_IDX prod, \
-+ RING_IDX cons, \
-+ RING_IDX ring_size) \
-+{ \
-+ RING_IDX size; \
-+ \
-+ if (prod == cons) \
-+ return 0; \
-+ \
-+ prod = name##_mask(prod, ring_size); \
-+ cons = name##_mask(cons, ring_size); \
-+ \
-+ if (prod == cons) \
-+ return ring_size; \
-+ \
-+ if (prod > cons) \
-+ size = prod - cons; \
-+ else \
-+ size = ring_size - (cons - prod); \
-+ return size; \
-+} \
-+ \
-+struct name##_data { \
-+ unsigned char *in; /* half of the allocation */ \
-+ unsigned char *out; /* half of the allocation */ \
-+}
-+
-+#define DEFINE_XEN_FLEX_RING_AND_INTF(name) \
-+struct name##_data_intf { \
-+ RING_IDX in_cons, in_prod; \
-+ \
-+ uint8_t pad1[56]; \
-+ \
-+ RING_IDX out_cons, out_prod; \
-+ \
-+ uint8_t pad2[56]; \
-+ \
-+ RING_IDX ring_order; \
-+ grant_ref_t ref[]; \
-+}; \
-+DEFINE_XEN_FLEX_RING(name)
-+
- #endif /* __XEN_PUBLIC_IO_RING_H__ */
---
-1.9.1
-
--- /dev/null
+From ba4fffac6e0267ce056e900be5a79695a685ce54 Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <sstabellini@kernel.org>
+Date: Mon, 26 Feb 2018 20:14:58 -0800
+Subject: [PATCH 2/4] pvcalls-front: introduce a per sock_mapping refcount
+
+Introduce a per sock_mapping refcount, in addition to the existing
+global refcount. Thanks to the sock_mapping refcount, we can safely wait
+for it to be 1 in pvcalls_front_release before freeing an active socket,
+instead of waiting for the global refcount to be 1.
+
+Signed-off-by: Stefano Stabellini <stefano@aporeto.com>
+
+---
+Changes in v2:
+- fix code style
+- nicer checks in pvcalls_front_release
+- fix check in pvcalls_enter_sock
+---
+ drivers/xen/pvcalls-front.c | 191 ++++++++++++++++++--------------------------
+ 1 file changed, 79 insertions(+), 112 deletions(-)
+
+diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c
+index 4c789e6..18d1bac 100644
+--- a/drivers/xen/pvcalls-front.c
++++ b/drivers/xen/pvcalls-front.c
+@@ -60,6 +60,7 @@ struct sock_mapping {
+ bool active_socket;
+ struct list_head list;
+ struct socket *sock;
++ atomic_t refcount;
+ union {
+ struct {
+ int irq;
+@@ -93,6 +94,32 @@ struct sock_mapping {
+ };
+ };
+
++static inline struct sock_mapping *pvcalls_enter_sock(struct socket *sock)
++{
++ struct sock_mapping *map;
++
++ if (!pvcalls_front_dev ||
++ dev_get_drvdata(&pvcalls_front_dev->dev) == NULL)
++ return ERR_PTR(-ENOTCONN);
++
++ map = (struct sock_mapping *)sock->sk->sk_send_head;
++ if (map == NULL)
++ return ERR_PTR(-ENOTSOCK);
++
++ pvcalls_enter();
++ atomic_inc(&map->refcount);
++ return map;
++}
++
++static inline void pvcalls_exit_sock(struct socket *sock)
++{
++ struct sock_mapping *map;
++
++ map = (struct sock_mapping *)sock->sk->sk_send_head;
++ atomic_dec(&map->refcount);
++ pvcalls_exit();
++}
++
+ static inline int get_request(struct pvcalls_bedata *bedata, int *req_id)
+ {
+ *req_id = bedata->ring.req_prod_pvt & (RING_SIZE(&bedata->ring) - 1);
+@@ -369,31 +396,23 @@ int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr,
+ if (addr->sa_family != AF_INET || sock->type != SOCK_STREAM)
+ return -EOPNOTSUPP;
+
+- pvcalls_enter();
+- if (!pvcalls_front_dev) {
+- pvcalls_exit();
+- return -ENOTCONN;
+- }
++ map = pvcalls_enter_sock(sock);
++ if (IS_ERR(map))
++ return PTR_ERR(map);
+
+ bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
+
+- map = (struct sock_mapping *)sock->sk->sk_send_head;
+- if (!map) {
+- pvcalls_exit();
+- return -ENOTSOCK;
+- }
+-
+ spin_lock(&bedata->socket_lock);
+ ret = get_request(bedata, &req_id);
+ if (ret < 0) {
+ spin_unlock(&bedata->socket_lock);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return ret;
+ }
+ ret = create_active(map, &evtchn);
+ if (ret < 0) {
+ spin_unlock(&bedata->socket_lock);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return ret;
+ }
+
+@@ -423,7 +442,7 @@ int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr,
+ smp_rmb();
+ ret = bedata->rsp[req_id].ret;
+ bedata->rsp[req_id].req_id = PVCALLS_INVALID_ID;
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return ret;
+ }
+
+@@ -488,23 +507,15 @@ int pvcalls_front_sendmsg(struct socket *sock, struct msghdr *msg,
+ if (flags & (MSG_CONFIRM|MSG_DONTROUTE|MSG_EOR|MSG_OOB))
+ return -EOPNOTSUPP;
+
+- pvcalls_enter();
+- if (!pvcalls_front_dev) {
+- pvcalls_exit();
+- return -ENOTCONN;
+- }
++ map = pvcalls_enter_sock(sock);
++ if (IS_ERR(map))
++ return PTR_ERR(map);
+ bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
+
+- map = (struct sock_mapping *) sock->sk->sk_send_head;
+- if (!map) {
+- pvcalls_exit();
+- return -ENOTSOCK;
+- }
+-
+ mutex_lock(&map->active.out_mutex);
+ if ((flags & MSG_DONTWAIT) && !pvcalls_front_write_todo(map)) {
+ mutex_unlock(&map->active.out_mutex);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return -EAGAIN;
+ }
+ if (len > INT_MAX)
+@@ -526,7 +537,7 @@ int pvcalls_front_sendmsg(struct socket *sock, struct msghdr *msg,
+ tot_sent = sent;
+
+ mutex_unlock(&map->active.out_mutex);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return tot_sent;
+ }
+
+@@ -591,19 +602,11 @@ int pvcalls_front_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+ if (flags & (MSG_CMSG_CLOEXEC|MSG_ERRQUEUE|MSG_OOB|MSG_TRUNC))
+ return -EOPNOTSUPP;
+
+- pvcalls_enter();
+- if (!pvcalls_front_dev) {
+- pvcalls_exit();
+- return -ENOTCONN;
+- }
++ map = pvcalls_enter_sock(sock);
++ if (IS_ERR(map))
++ return PTR_ERR(map);
+ bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
+
+- map = (struct sock_mapping *) sock->sk->sk_send_head;
+- if (!map) {
+- pvcalls_exit();
+- return -ENOTSOCK;
+- }
+-
+ mutex_lock(&map->active.in_mutex);
+ if (len > XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER))
+ len = XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER);
+@@ -623,7 +626,7 @@ int pvcalls_front_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+ ret = 0;
+
+ mutex_unlock(&map->active.in_mutex);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return ret;
+ }
+
+@@ -637,24 +640,16 @@ int pvcalls_front_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
+ if (addr->sa_family != AF_INET || sock->type != SOCK_STREAM)
+ return -EOPNOTSUPP;
+
+- pvcalls_enter();
+- if (!pvcalls_front_dev) {
+- pvcalls_exit();
+- return -ENOTCONN;
+- }
++ map = pvcalls_enter_sock(sock);
++ if (IS_ERR(map))
++ return PTR_ERR(map);
+ bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
+
+- map = (struct sock_mapping *) sock->sk->sk_send_head;
+- if (map == NULL) {
+- pvcalls_exit();
+- return -ENOTSOCK;
+- }
+-
+ spin_lock(&bedata->socket_lock);
+ ret = get_request(bedata, &req_id);
+ if (ret < 0) {
+ spin_unlock(&bedata->socket_lock);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return ret;
+ }
+ req = RING_GET_REQUEST(&bedata->ring, req_id);
+@@ -684,7 +679,7 @@ int pvcalls_front_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
+ bedata->rsp[req_id].req_id = PVCALLS_INVALID_ID;
+
+ map->passive.status = PVCALLS_STATUS_BIND;
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return 0;
+ }
+
+@@ -695,21 +690,13 @@ int pvcalls_front_listen(struct socket *sock, int backlog)
+ struct xen_pvcalls_request *req;
+ int notify, req_id, ret;
+
+- pvcalls_enter();
+- if (!pvcalls_front_dev) {
+- pvcalls_exit();
+- return -ENOTCONN;
+- }
++ map = pvcalls_enter_sock(sock);
++ if (IS_ERR(map))
++ return PTR_ERR(map);
+ bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
+
+- map = (struct sock_mapping *) sock->sk->sk_send_head;
+- if (!map) {
+- pvcalls_exit();
+- return -ENOTSOCK;
+- }
+-
+ if (map->passive.status != PVCALLS_STATUS_BIND) {
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return -EOPNOTSUPP;
+ }
+
+@@ -717,7 +704,7 @@ int pvcalls_front_listen(struct socket *sock, int backlog)
+ ret = get_request(bedata, &req_id);
+ if (ret < 0) {
+ spin_unlock(&bedata->socket_lock);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return ret;
+ }
+ req = RING_GET_REQUEST(&bedata->ring, req_id);
+@@ -741,7 +728,7 @@ int pvcalls_front_listen(struct socket *sock, int backlog)
+ bedata->rsp[req_id].req_id = PVCALLS_INVALID_ID;
+
+ map->passive.status = PVCALLS_STATUS_LISTEN;
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return ret;
+ }
+
+@@ -753,21 +740,13 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
+ struct xen_pvcalls_request *req;
+ int notify, req_id, ret, evtchn, nonblock;
+
+- pvcalls_enter();
+- if (!pvcalls_front_dev) {
+- pvcalls_exit();
+- return -ENOTCONN;
+- }
++ map = pvcalls_enter_sock(sock);
++ if (IS_ERR(map))
++ return PTR_ERR(map);
+ bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
+
+- map = (struct sock_mapping *) sock->sk->sk_send_head;
+- if (!map) {
+- pvcalls_exit();
+- return -ENOTSOCK;
+- }
+-
+ if (map->passive.status != PVCALLS_STATUS_LISTEN) {
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return -EINVAL;
+ }
+
+@@ -785,13 +764,13 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
+ goto received;
+ }
+ if (nonblock) {
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return -EAGAIN;
+ }
+ if (wait_event_interruptible(map->passive.inflight_accept_req,
+ !test_and_set_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
+ (void *)&map->passive.flags))) {
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return -EINTR;
+ }
+ }
+@@ -802,7 +781,7 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
+ clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
+ (void *)&map->passive.flags);
+ spin_unlock(&bedata->socket_lock);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return ret;
+ }
+ map2 = kzalloc(sizeof(*map2), GFP_ATOMIC);
+@@ -810,7 +789,7 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
+ clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
+ (void *)&map->passive.flags);
+ spin_unlock(&bedata->socket_lock);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return -ENOMEM;
+ }
+ ret = create_active(map2, &evtchn);
+@@ -819,7 +798,7 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
+ clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
+ (void *)&map->passive.flags);
+ spin_unlock(&bedata->socket_lock);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return ret;
+ }
+ list_add_tail(&map2->list, &bedata->socket_mappings);
+@@ -841,13 +820,13 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
+ /* We could check if we have received a response before returning. */
+ if (nonblock) {
+ WRITE_ONCE(map->passive.inflight_req_id, req_id);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return -EAGAIN;
+ }
+
+ if (wait_event_interruptible(bedata->inflight_req,
+ READ_ONCE(bedata->rsp[req_id].req_id) == req_id)) {
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return -EINTR;
+ }
+ /* read req_id, then the content */
+@@ -862,7 +841,7 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
+ clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
+ (void *)&map->passive.flags);
+ pvcalls_front_free_map(bedata, map2);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return -ENOMEM;
+ }
+ newsock->sk->sk_send_head = (void *)map2;
+@@ -874,7 +853,7 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
+ clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, (void *)&map->passive.flags);
+ wake_up(&map->passive.inflight_accept_req);
+
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return ret;
+ }
+
+@@ -965,23 +944,16 @@ unsigned int pvcalls_front_poll(struct file *file, struct socket *sock,
+ struct sock_mapping *map;
+ int ret;
+
+- pvcalls_enter();
+- if (!pvcalls_front_dev) {
+- pvcalls_exit();
++ map = pvcalls_enter_sock(sock);
++ if (IS_ERR(map))
+ return POLLNVAL;
+- }
+ bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
+
+- map = (struct sock_mapping *) sock->sk->sk_send_head;
+- if (!map) {
+- pvcalls_exit();
+- return POLLNVAL;
+- }
+ if (map->active_socket)
+ ret = pvcalls_front_poll_active(file, bedata, map, wait);
+ else
+ ret = pvcalls_front_poll_passive(file, bedata, map, wait);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return ret;
+ }
+
+@@ -995,25 +967,20 @@ int pvcalls_front_release(struct socket *sock)
+ if (sock->sk == NULL)
+ return 0;
+
+- pvcalls_enter();
+- if (!pvcalls_front_dev) {
+- pvcalls_exit();
+- return -EIO;
++ map = pvcalls_enter_sock(sock);
++ if (IS_ERR(map)) {
++ if (PTR_ERR(map) == -ENOTCONN)
++ return -EIO;
++ else
++ return 0;
+ }
+-
+ bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
+
+- map = (struct sock_mapping *) sock->sk->sk_send_head;
+- if (map == NULL) {
+- pvcalls_exit();
+- return 0;
+- }
+-
+ spin_lock(&bedata->socket_lock);
+ ret = get_request(bedata, &req_id);
+ if (ret < 0) {
+ spin_unlock(&bedata->socket_lock);
+- pvcalls_exit();
++ pvcalls_exit_sock(sock);
+ return ret;
+ }
+ sock->sk->sk_send_head = NULL;
+@@ -1043,10 +1010,10 @@ int pvcalls_front_release(struct socket *sock)
+ /*
+ * We need to make sure that sendmsg/recvmsg on this socket have
+ * not started before we've cleared sk_send_head here. The
+- * easiest (though not optimal) way to guarantee this is to see
+- * that no pvcall (other than us) is in progress.
++ * easiest way to guarantee this is to see that no pvcalls
++ * (other than us) is in progress on this socket.
+ */
+- while (atomic_read(&pvcalls_refcount) > 1)
++ while (atomic_read(&map->refcount) > 1)
+ cpu_relax();
+
+ pvcalls_front_free_map(bedata, map);
+--
+1.9.1
+
+++ /dev/null
-From c9a13df465717fe7b5d5a600989317a98862820a Mon Sep 17 00:00:00 2001
-From: Stefano Stabellini <sstabellini@kernel.org>
-Date: Wed, 5 Apr 2017 12:03:56 -0700
-Subject: [PATCH 2/8] xen: introduce the header file for the Xen 9pfs transport
- protocol
-
-It uses the new ring.h macros to declare rings and interfaces.
-
-CC: konrad.wilk@oracle.com
-CC: boris.ostrovsky@oracle.com
-CC: jgross@suse.com
-CC: groug@kaod.org
-
-Signed-off-by: Stefano Stabellini <stefano@aporeto.com>
-Acked-by: Juergen Gross <jgross@suse.com>
-Signed-off-by: Juergen Gross <jgross@suse.com>
----
- include/xen/interface/io/9pfs.h | 36 ++++++++++++++++++++++++++++++++++++
- 1 file changed, 36 insertions(+)
- create mode 100644 include/xen/interface/io/9pfs.h
-
-diff --git a/include/xen/interface/io/9pfs.h b/include/xen/interface/io/9pfs.h
-new file mode 100644
-index 0000000..5b6c19d
---- /dev/null
-+++ b/include/xen/interface/io/9pfs.h
-@@ -0,0 +1,36 @@
-+/*
-+ * 9pfs.h -- Xen 9PFS transport
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to
-+ * deal in the Software without restriction, including without limitation the
-+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-+ * sell copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ * DEALINGS IN THE SOFTWARE.
-+ *
-+ * Copyright (C) 2017 Stefano Stabellini <stefano@aporeto.com>
-+ */
-+
-+#ifndef __XEN_PUBLIC_IO_9PFS_H__
-+#define __XEN_PUBLIC_IO_9PFS_H__
-+
-+#include "xen/interface/io/ring.h"
-+
-+/*
-+ * See docs/misc/9pfs.markdown in xen.git for the full specification:
-+ * https://xenbits.xen.org/docs/unstable/misc/9pfs.html
-+ */
-+DEFINE_XEN_FLEX_RING_AND_INTF(xen_9pfs);
-+
-+#endif
---
-1.9.1
-
--- /dev/null
+From 1eebb3bb08a7d88ab62069d54b62fcbdaf1a48f3 Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <sstabellini@kernel.org>
+Date: Mon, 26 Feb 2018 20:15:09 -0800
+Subject: [PATCH 3/4] pvcalls-front: wait for other operations to return when
+ release passive sockets
+
+Passive sockets can have ongoing operations on them, specifically, we
+have two wait_event_interruptable calls in pvcalls_front_accept.
+
+Add two wake_up calls in pvcalls_front_release, then wait for the
+potential waiters to return and release the sock_mapping refcount.
+
+Signed-off-by: Stefano Stabellini <stefano@aporeto.com>
+Acked-by: Juergen Gross <jgross@suse.com>
+---
+ drivers/xen/pvcalls-front.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c
+index 18d1bac..ca5b773 100644
+--- a/drivers/xen/pvcalls-front.c
++++ b/drivers/xen/pvcalls-front.c
+@@ -1018,6 +1018,12 @@ int pvcalls_front_release(struct socket *sock)
+
+ pvcalls_front_free_map(bedata, map);
+ } else {
++ wake_up(&bedata->inflight_req);
++ wake_up(&map->passive.inflight_accept_req);
++
++ while (atomic_read(&map->refcount) > 1)
++ cpu_relax();
++
+ spin_lock(&bedata->socket_lock);
+ list_del(&map->list);
+ spin_unlock(&bedata->socket_lock);
+--
+1.9.1
+
+++ /dev/null
-From d76732087cde8e8a2a950719e8719dbc51af8d5a Mon Sep 17 00:00:00 2001
-From: Stefano Stabellini <sstabellini@kernel.org>
-Date: Wed, 5 Apr 2017 12:03:57 -0700
-Subject: [PATCH 3/8] xen/9pfs: introduce Xen 9pfs transport driver
-
-Introduce the Xen 9pfs transport driver: add struct xenbus_driver to
-register as a xenbus driver and add struct p9_trans_module to register
-as v9fs driver.
-
-All functions are empty stubs for now.
-
-CC: groug@kaod.org
-CC: jgross@suse.com
-CC: Eric Van Hensbergen <ericvh@gmail.com>
-CC: Ron Minnich <rminnich@sandia.gov>
-CC: Latchesar Ionkov <lucho@ionkov.net>
-CC: v9fs-developer@lists.sourceforge.net
-
-Signed-off-by: Stefano Stabellini <stefano@aporeto.com>
-Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
-Reviewed-by: Juergen Gross <jgross@suse.com>
-Signed-off-by: Juergen Gross <jgross@suse.com>
----
- net/9p/trans_xen.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 125 insertions(+)
- create mode 100644 net/9p/trans_xen.c
-
-diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
-new file mode 100644
-index 0000000..3d07260
---- /dev/null
-+++ b/net/9p/trans_xen.c
-@@ -0,0 +1,125 @@
-+/*
-+ * linux/fs/9p/trans_xen
-+ *
-+ * Xen transport layer.
-+ *
-+ * Copyright (C) 2017 by Stefano Stabellini <stefano@aporeto.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License version 2
-+ * as published by the Free Software Foundation; or, when distributed
-+ * separately from the Linux kernel or incorporated into other
-+ * software packages, subject to the following license:
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this source file (the "Software"), to deal in the Software without
-+ * restriction, including without limitation the rights to use, copy, modify,
-+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
-+ * and to permit persons to whom the Software is furnished to do so, subject to
-+ * the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ */
-+
-+#include <xen/events.h>
-+#include <xen/grant_table.h>
-+#include <xen/xen.h>
-+#include <xen/xenbus.h>
-+#include <xen/interface/io/9pfs.h>
-+
-+#include <linux/module.h>
-+#include <net/9p/9p.h>
-+#include <net/9p/client.h>
-+#include <net/9p/transport.h>
-+
-+static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req)
-+{
-+ return 0;
-+}
-+
-+static int p9_xen_create(struct p9_client *client, const char *addr, char *args)
-+{
-+ return 0;
-+}
-+
-+static void p9_xen_close(struct p9_client *client)
-+{
-+}
-+
-+static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
-+{
-+ return 0;
-+}
-+
-+static struct p9_trans_module p9_xen_trans = {
-+ .name = "xen",
-+ .maxsize = 1 << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT),
-+ .def = 1,
-+ .create = p9_xen_create,
-+ .close = p9_xen_close,
-+ .request = p9_xen_request,
-+ .cancel = p9_xen_cancel,
-+ .owner = THIS_MODULE,
-+};
-+
-+static const struct xenbus_device_id xen_9pfs_front_ids[] = {
-+ { "9pfs" },
-+ { "" }
-+};
-+
-+static int xen_9pfs_front_remove(struct xenbus_device *dev)
-+{
-+ return 0;
-+}
-+
-+static int xen_9pfs_front_probe(struct xenbus_device *dev,
-+ const struct xenbus_device_id *id)
-+{
-+ return 0;
-+}
-+
-+static int xen_9pfs_front_resume(struct xenbus_device *dev)
-+{
-+ return 0;
-+}
-+
-+static void xen_9pfs_front_changed(struct xenbus_device *dev,
-+ enum xenbus_state backend_state)
-+{
-+}
-+
-+static struct xenbus_driver xen_9pfs_front_driver = {
-+ .ids = xen_9pfs_front_ids,
-+ .probe = xen_9pfs_front_probe,
-+ .remove = xen_9pfs_front_remove,
-+ .resume = xen_9pfs_front_resume,
-+ .otherend_changed = xen_9pfs_front_changed,
-+};
-+
-+int p9_trans_xen_init(void)
-+{
-+ if (!xen_domain())
-+ return -ENODEV;
-+
-+ pr_info("Initialising Xen transport for 9pfs\n");
-+
-+ v9fs_register_trans(&p9_xen_trans);
-+ return xenbus_register_frontend(&xen_9pfs_front_driver);
-+}
-+module_init(p9_trans_xen_init);
-+
-+void p9_trans_xen_exit(void)
-+{
-+ v9fs_unregister_trans(&p9_xen_trans);
-+ return xenbus_unregister_driver(&xen_9pfs_front_driver);
-+}
-+module_exit(p9_trans_xen_exit);
---
-1.9.1
-
--- /dev/null
+From 6eab83a68c6efb1d3ad37e1db478cfe25a8948ba Mon Sep 17 00:00:00 2001
+From: Stefano Stabellini <sstabellini@kernel.org>
+Date: Wed, 28 Feb 2018 17:50:34 -0800
+Subject: [PATCH 4/4] patch arm64_fix
+
+---
+ drivers/xen/pvcalls-front.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c
+index ca5b773..582929e 100644
+--- a/drivers/xen/pvcalls-front.c
++++ b/drivers/xen/pvcalls-front.c
+@@ -73,20 +73,25 @@ struct sock_mapping {
+ wait_queue_head_t inflight_conn_req;
+ } active;
+ struct {
+- /* Socket status */
++ /*
++ * Socket status, needs to be 64-bit aligned due to the
++ * test_and_* functions which have this requirement on arm64.
++ */
+ #define PVCALLS_STATUS_UNINITALIZED 0
+ #define PVCALLS_STATUS_BIND 1
+ #define PVCALLS_STATUS_LISTEN 2
+- uint8_t status;
++ uint8_t status __attribute__((aligned(8)));
+ /*
+ * Internal state-machine flags.
+ * Only one accept operation can be inflight for a socket.
+ * Only one poll operation can be inflight for a given socket.
++ * flags needs to be 64-bit aligned due to the test_and_*
++ * functions which have this requirement on arm64.
+ */
+ #define PVCALLS_FLAG_ACCEPT_INFLIGHT 0
+ #define PVCALLS_FLAG_POLL_INFLIGHT 1
+ #define PVCALLS_FLAG_POLL_RET 2
+- uint8_t flags;
++ uint8_t flags __attribute__((aligned(8)));
+ uint32_t inflight_req_id;
+ struct sock_mapping *accept_map;
+ wait_queue_head_t inflight_accept_req;
+--
+1.9.1
+
+++ /dev/null
-From e9c53da56ff36458b1b8df95573f5dac80a1a956 Mon Sep 17 00:00:00 2001
-From: Stefano Stabellini <sstabellini@kernel.org>
-Date: Wed, 5 Apr 2017 12:03:58 -0700
-Subject: [PATCH 4/8] xen/9pfs: connect to the backend
-
-Implement functions to handle the xenbus handshake. Upon connection,
-allocate the rings according to the protocol specification.
-
-Initialize a work_struct and a wait_queue. The work_struct will be used
-to schedule work upon receiving an event channel notification from the
-backend. The wait_queue will be used to wait when the ring is full and
-we need to send a new request.
-
-CC: groug@kaod.org
-CC: boris.ostrovsky@oracle.com
-CC: jgross@suse.com
-CC: Eric Van Hensbergen <ericvh@gmail.com>
-CC: Ron Minnich <rminnich@sandia.gov>
-CC: Latchesar Ionkov <lucho@ionkov.net>
-CC: v9fs-developer@lists.sourceforge.net
-
-Signed-off-by: Stefano Stabellini <stefano@aporeto.com>
-Reviewed-by: Juergen Gross <jgross@suse.com>
-Signed-off-by: Juergen Gross <jgross@suse.com>
----
- net/9p/trans_xen.c | 281 +++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 281 insertions(+)
-
-diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
-index 3d07260..fe3d172 100644
---- a/net/9p/trans_xen.c
-+++ b/net/9p/trans_xen.c
-@@ -37,10 +37,54 @@
- #include <xen/interface/io/9pfs.h>
-
- #include <linux/module.h>
-+#include <linux/spinlock.h>
-+#include <linux/rwlock.h>
- #include <net/9p/9p.h>
- #include <net/9p/client.h>
- #include <net/9p/transport.h>
-
-+#define XEN_9PFS_NUM_RINGS 2
-+#define XEN_9PFS_RING_ORDER 6
-+#define XEN_9PFS_RING_SIZE XEN_FLEX_RING_SIZE(XEN_9PFS_RING_ORDER)
-+
-+struct xen_9pfs_header {
-+ uint32_t size;
-+ uint8_t id;
-+ uint16_t tag;
-+
-+ /* uint8_t sdata[]; */
-+} __attribute__((packed));
-+
-+/* One per ring, more than one per 9pfs share */
-+struct xen_9pfs_dataring {
-+ struct xen_9pfs_front_priv *priv;
-+
-+ struct xen_9pfs_data_intf *intf;
-+ grant_ref_t ref;
-+ int evtchn;
-+ int irq;
-+ /* protect a ring from concurrent accesses */
-+ spinlock_t lock;
-+
-+ struct xen_9pfs_data data;
-+ wait_queue_head_t wq;
-+ struct work_struct work;
-+};
-+
-+/* One per 9pfs share */
-+struct xen_9pfs_front_priv {
-+ struct list_head list;
-+ struct xenbus_device *dev;
-+ char *tag;
-+ struct p9_client *client;
-+
-+ int num_rings;
-+ struct xen_9pfs_dataring *rings;
-+};
-+
-+static LIST_HEAD(xen_9pfs_devs);
-+static DEFINE_RWLOCK(xen_9pfs_lock);
-+
- static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req)
- {
- return 0;
-@@ -60,6 +104,25 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
- return 0;
- }
-
-+static void p9_xen_response(struct work_struct *work)
-+{
-+}
-+
-+static irqreturn_t xen_9pfs_front_event_handler(int irq, void *r)
-+{
-+ struct xen_9pfs_dataring *ring = r;
-+
-+ if (!ring || !ring->priv->client) {
-+ /* ignore spurious interrupt */
-+ return IRQ_HANDLED;
-+ }
-+
-+ wake_up_interruptible(&ring->wq);
-+ schedule_work(&ring->work);
-+
-+ return IRQ_HANDLED;
-+}
-+
- static struct p9_trans_module p9_xen_trans = {
- .name = "xen",
- .maxsize = 1 << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT),
-@@ -76,25 +139,243 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
- { "" }
- };
-
-+static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv)
-+{
-+ int i, j;
-+
-+ write_lock(&xen_9pfs_lock);
-+ list_del(&priv->list);
-+ write_unlock(&xen_9pfs_lock);
-+
-+ for (i = 0; i < priv->num_rings; i++) {
-+ if (!priv->rings[i].intf)
-+ break;
-+ if (priv->rings[i].irq > 0)
-+ unbind_from_irqhandler(priv->rings[i].irq, priv->dev);
-+ if (priv->rings[i].data.in) {
-+ for (j = 0; j < (1 << XEN_9PFS_RING_ORDER); j++) {
-+ grant_ref_t ref;
-+
-+ ref = priv->rings[i].intf->ref[j];
-+ gnttab_end_foreign_access(ref, 0, 0);
-+ }
-+ free_pages((unsigned long)priv->rings[i].data.in,
-+ XEN_9PFS_RING_ORDER -
-+ (PAGE_SHIFT - XEN_PAGE_SHIFT));
-+ }
-+ gnttab_end_foreign_access(priv->rings[i].ref, 0, 0);
-+ free_page((unsigned long)priv->rings[i].intf);
-+ }
-+ kfree(priv->rings);
-+ kfree(priv->tag);
-+ kfree(priv);
-+}
-+
- static int xen_9pfs_front_remove(struct xenbus_device *dev)
- {
-+ struct xen_9pfs_front_priv *priv = dev_get_drvdata(&dev->dev);
-+
-+ dev_set_drvdata(&dev->dev, NULL);
-+ xen_9pfs_front_free(priv);
- return 0;
- }
-
-+static int xen_9pfs_front_alloc_dataring(struct xenbus_device *dev,
-+ struct xen_9pfs_dataring *ring)
-+{
-+ int i = 0;
-+ int ret = -ENOMEM;
-+ void *bytes = NULL;
-+
-+ init_waitqueue_head(&ring->wq);
-+ spin_lock_init(&ring->lock);
-+ INIT_WORK(&ring->work, p9_xen_response);
-+
-+ ring->intf = (struct xen_9pfs_data_intf *)get_zeroed_page(GFP_KERNEL);
-+ if (!ring->intf)
-+ return ret;
-+ ret = gnttab_grant_foreign_access(dev->otherend_id,
-+ virt_to_gfn(ring->intf), 0);
-+ if (ret < 0)
-+ goto out;
-+ ring->ref = ret;
-+ bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
-+ XEN_9PFS_RING_ORDER - (PAGE_SHIFT - XEN_PAGE_SHIFT));
-+ if (!bytes) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+ for (; i < (1 << XEN_9PFS_RING_ORDER); i++) {
-+ ret = gnttab_grant_foreign_access(
-+ dev->otherend_id, virt_to_gfn(bytes) + i, 0);
-+ if (ret < 0)
-+ goto out;
-+ ring->intf->ref[i] = ret;
-+ }
-+ ring->intf->ring_order = XEN_9PFS_RING_ORDER;
-+ ring->data.in = bytes;
-+ ring->data.out = bytes + XEN_9PFS_RING_SIZE;
-+
-+ ret = xenbus_alloc_evtchn(dev, &ring->evtchn);
-+ if (ret)
-+ goto out;
-+ ring->irq = bind_evtchn_to_irqhandler(ring->evtchn,
-+ xen_9pfs_front_event_handler,
-+ 0, "xen_9pfs-frontend", ring);
-+ if (ring->irq >= 0)
-+ return 0;
-+
-+ xenbus_free_evtchn(dev, ring->evtchn);
-+ ret = ring->irq;
-+out:
-+ if (bytes) {
-+ for (i--; i >= 0; i--)
-+ gnttab_end_foreign_access(ring->intf->ref[i], 0, 0);
-+ free_pages((unsigned long)bytes,
-+ XEN_9PFS_RING_ORDER -
-+ (PAGE_SHIFT - XEN_PAGE_SHIFT));
-+ }
-+ gnttab_end_foreign_access(ring->ref, 0, 0);
-+ free_page((unsigned long)ring->intf);
-+ return ret;
-+}
-+
- static int xen_9pfs_front_probe(struct xenbus_device *dev,
- const struct xenbus_device_id *id)
- {
-+ int ret, i;
-+ struct xenbus_transaction xbt;
-+ struct xen_9pfs_front_priv *priv = NULL;
-+ char *versions;
-+ unsigned int max_rings, max_ring_order, len;
-+
-+ versions = xenbus_read(XBT_NIL, dev->otherend, "versions", &len);
-+ if (!len)
-+ return -EINVAL;
-+ if (strcmp(versions, "1")) {
-+ kfree(versions);
-+ return -EINVAL;
-+ }
-+ kfree(versions);
-+ max_rings = xenbus_read_unsigned(dev->otherend, "max-rings", 0);
-+ if (max_rings < XEN_9PFS_NUM_RINGS)
-+ return -EINVAL;
-+ max_ring_order = xenbus_read_unsigned(dev->otherend,
-+ "max-ring-page-order", 0);
-+ if (max_ring_order < XEN_9PFS_RING_ORDER)
-+ return -EINVAL;
-+
-+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-+ if (!priv)
-+ return -ENOMEM;
-+
-+ priv->dev = dev;
-+ priv->num_rings = XEN_9PFS_NUM_RINGS;
-+ priv->rings = kcalloc(priv->num_rings, sizeof(*priv->rings),
-+ GFP_KERNEL);
-+ if (!priv->rings) {
-+ kfree(priv);
-+ return -ENOMEM;
-+ }
-+
-+ for (i = 0; i < priv->num_rings; i++) {
-+ priv->rings[i].priv = priv;
-+ ret = xen_9pfs_front_alloc_dataring(dev, &priv->rings[i]);
-+ if (ret < 0)
-+ goto error;
-+ }
-+
-+ again:
-+ ret = xenbus_transaction_start(&xbt);
-+ if (ret) {
-+ xenbus_dev_fatal(dev, ret, "starting transaction");
-+ goto error;
-+ }
-+ ret = xenbus_printf(xbt, dev->nodename, "version", "%u", 1);
-+ if (ret)
-+ goto error_xenbus;
-+ ret = xenbus_printf(xbt, dev->nodename, "num-rings", "%u",
-+ priv->num_rings);
-+ if (ret)
-+ goto error_xenbus;
-+ for (i = 0; i < priv->num_rings; i++) {
-+ char str[16];
-+
-+ BUILD_BUG_ON(XEN_9PFS_NUM_RINGS > 9);
-+ sprintf(str, "ring-ref%u", i);
-+ ret = xenbus_printf(xbt, dev->nodename, str, "%d",
-+ priv->rings[i].ref);
-+ if (ret)
-+ goto error_xenbus;
-+
-+ sprintf(str, "event-channel-%u", i);
-+ ret = xenbus_printf(xbt, dev->nodename, str, "%u",
-+ priv->rings[i].evtchn);
-+ if (ret)
-+ goto error_xenbus;
-+ }
-+ priv->tag = xenbus_read(xbt, dev->nodename, "tag", NULL);
-+ if (!priv->tag) {
-+ ret = -EINVAL;
-+ goto error_xenbus;
-+ }
-+ ret = xenbus_transaction_end(xbt, 0);
-+ if (ret) {
-+ if (ret == -EAGAIN)
-+ goto again;
-+ xenbus_dev_fatal(dev, ret, "completing transaction");
-+ goto error;
-+ }
-+
-+ write_lock(&xen_9pfs_lock);
-+ list_add_tail(&priv->list, &xen_9pfs_devs);
-+ write_unlock(&xen_9pfs_lock);
-+ dev_set_drvdata(&dev->dev, priv);
-+ xenbus_switch_state(dev, XenbusStateInitialised);
-+
- return 0;
-+
-+ error_xenbus:
-+ xenbus_transaction_end(xbt, 1);
-+ xenbus_dev_fatal(dev, ret, "writing xenstore");
-+ error:
-+ dev_set_drvdata(&dev->dev, NULL);
-+ xen_9pfs_front_free(priv);
-+ return ret;
- }
-
- static int xen_9pfs_front_resume(struct xenbus_device *dev)
- {
-+ dev_warn(&dev->dev, "suspsend/resume unsupported\n");
- return 0;
- }
-
- static void xen_9pfs_front_changed(struct xenbus_device *dev,
- enum xenbus_state backend_state)
- {
-+ switch (backend_state) {
-+ case XenbusStateReconfiguring:
-+ case XenbusStateReconfigured:
-+ case XenbusStateInitialising:
-+ case XenbusStateInitialised:
-+ case XenbusStateUnknown:
-+ break;
-+
-+ case XenbusStateInitWait:
-+ break;
-+
-+ case XenbusStateConnected:
-+ xenbus_switch_state(dev, XenbusStateConnected);
-+ break;
-+
-+ case XenbusStateClosed:
-+ if (dev->state == XenbusStateClosed)
-+ break;
-+ /* Missed the backend's CLOSING state -- fallthrough */
-+ case XenbusStateClosing:
-+ xenbus_frontend_closed(dev);
-+ break;
-+ }
- }
-
- static struct xenbus_driver xen_9pfs_front_driver = {
---
-1.9.1
-
+++ /dev/null
-From 9037ec171d23ab5541ea72da6e2a0180c3f3cb62 Mon Sep 17 00:00:00 2001
-From: Stefano Stabellini <sstabellini@kernel.org>
-Date: Wed, 5 Apr 2017 12:03:59 -0700
-Subject: [PATCH 5/8] xen/9pfs: send requests to the backend
-
-Implement struct p9_trans_module create and close functions by looking
-at the available Xen 9pfs frontend-backend connections. We don't expect
-many frontend-backend connections, thus walking a list is OK.
-
-Send requests to the backend by copying each request to one of the
-available rings (each frontend-backend connection comes with multiple
-rings). Handle the ring and notifications following the 9pfs
-specification. If there are not enough free bytes on the ring for the
-request, wait on the wait_queue: the backend will send a notification
-after consuming more requests.
-
-CC: groug@kaod.org
-CC: jgross@suse.com
-CC: Eric Van Hensbergen <ericvh@gmail.com>
-CC: Ron Minnich <rminnich@sandia.gov>
-CC: Latchesar Ionkov <lucho@ionkov.net>
-CC: v9fs-developer@lists.sourceforge.net
-
-Signed-off-by: Stefano Stabellini <stefano@aporeto.com>
-Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
-Reviewed-by: Juergen Gross <jgross@suse.com>
-Signed-off-by: Juergen Gross <jgross@suse.com>
----
- net/9p/trans_xen.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
- 1 file changed, 85 insertions(+), 2 deletions(-)
-
-diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
-index fe3d172..28f30f4 100644
---- a/net/9p/trans_xen.c
-+++ b/net/9p/trans_xen.c
-@@ -85,22 +85,105 @@ struct xen_9pfs_front_priv {
- static LIST_HEAD(xen_9pfs_devs);
- static DEFINE_RWLOCK(xen_9pfs_lock);
-
-+/* We don't currently allow canceling of requests */
- static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req)
- {
-- return 0;
-+ return 1;
- }
-
- static int p9_xen_create(struct p9_client *client, const char *addr, char *args)
- {
-- return 0;
-+ struct xen_9pfs_front_priv *priv;
-+
-+ read_lock(&xen_9pfs_lock);
-+ list_for_each_entry(priv, &xen_9pfs_devs, list) {
-+ if (!strcmp(priv->tag, addr)) {
-+ priv->client = client;
-+ read_unlock(&xen_9pfs_lock);
-+ return 0;
-+ }
-+ }
-+ read_unlock(&xen_9pfs_lock);
-+ return -EINVAL;
- }
-
- static void p9_xen_close(struct p9_client *client)
- {
-+ struct xen_9pfs_front_priv *priv;
-+
-+ read_lock(&xen_9pfs_lock);
-+ list_for_each_entry(priv, &xen_9pfs_devs, list) {
-+ if (priv->client == client) {
-+ priv->client = NULL;
-+ read_unlock(&xen_9pfs_lock);
-+ return;
-+ }
-+ }
-+ read_unlock(&xen_9pfs_lock);
-+}
-+
-+static bool p9_xen_write_todo(struct xen_9pfs_dataring *ring, RING_IDX size)
-+{
-+ RING_IDX cons, prod;
-+
-+ cons = ring->intf->out_cons;
-+ prod = ring->intf->out_prod;
-+ virt_mb();
-+
-+ return XEN_9PFS_RING_SIZE -
-+ xen_9pfs_queued(prod, cons, XEN_9PFS_RING_SIZE) >= size;
- }
-
- static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
- {
-+ struct xen_9pfs_front_priv *priv = NULL;
-+ RING_IDX cons, prod, masked_cons, masked_prod;
-+ unsigned long flags;
-+ u32 size = p9_req->tc->size;
-+ struct xen_9pfs_dataring *ring;
-+ int num;
-+
-+ read_lock(&xen_9pfs_lock);
-+ list_for_each_entry(priv, &xen_9pfs_devs, list) {
-+ if (priv->client == client)
-+ break;
-+ }
-+ read_unlock(&xen_9pfs_lock);
-+ if (!priv || priv->client != client)
-+ return -EINVAL;
-+
-+ num = p9_req->tc->tag % priv->num_rings;
-+ ring = &priv->rings[num];
-+
-+again:
-+ while (wait_event_interruptible(ring->wq,
-+ p9_xen_write_todo(ring, size)) != 0)
-+ ;
-+
-+ spin_lock_irqsave(&ring->lock, flags);
-+ cons = ring->intf->out_cons;
-+ prod = ring->intf->out_prod;
-+ virt_mb();
-+
-+ if (XEN_9PFS_RING_SIZE - xen_9pfs_queued(prod, cons,
-+ XEN_9PFS_RING_SIZE) < size) {
-+ spin_unlock_irqrestore(&ring->lock, flags);
-+ goto again;
-+ }
-+
-+ masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE);
-+ masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE);
-+
-+ xen_9pfs_write_packet(ring->data.out, p9_req->tc->sdata, size,
-+ &masked_prod, masked_cons, XEN_9PFS_RING_SIZE);
-+
-+ p9_req->status = REQ_STATUS_SENT;
-+ virt_wmb(); /* write ring before updating pointer */
-+ prod += size;
-+ ring->intf->out_prod = prod;
-+ spin_unlock_irqrestore(&ring->lock, flags);
-+ notify_remote_via_irq(ring->irq);
-+
- return 0;
- }
-
---
-1.9.1
-
+++ /dev/null
-From 0152c96b8315a3cc30e76435893ea578f735baf2 Mon Sep 17 00:00:00 2001
-From: Stefano Stabellini <sstabellini@kernel.org>
-Date: Wed, 5 Apr 2017 12:04:00 -0700
-Subject: [PATCH 6/8] xen/9pfs: receive responses
-
-Upon receiving a notification from the backend, schedule the
-p9_xen_response work_struct. p9_xen_response checks if any responses are
-available, if so, it reads them one by one, calling p9_client_cb to send
-them up to the 9p layer (p9_client_cb completes the request). Handle the
-ring following the Xen 9pfs specification.
-
-CC: groug@kaod.org
-CC: jgross@suse.com
-CC: Eric Van Hensbergen <ericvh@gmail.com>
-CC: Ron Minnich <rminnich@sandia.gov>
-CC: Latchesar Ionkov <lucho@ionkov.net>
-CC: v9fs-developer@lists.sourceforge.net
-
-Signed-off-by: Stefano Stabellini <stefano@aporeto.com>
-Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
-Reviewed-by: Juergen Gross <jgross@suse.com>
-Signed-off-by: Juergen Gross <jgross@suse.com>
----
- net/9p/trans_xen.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 56 insertions(+)
-
-diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
-index 28f30f4..4786424 100644
---- a/net/9p/trans_xen.c
-+++ b/net/9p/trans_xen.c
-@@ -189,6 +189,62 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
-
- static void p9_xen_response(struct work_struct *work)
- {
-+ struct xen_9pfs_front_priv *priv;
-+ struct xen_9pfs_dataring *ring;
-+ RING_IDX cons, prod, masked_cons, masked_prod;
-+ struct xen_9pfs_header h;
-+ struct p9_req_t *req;
-+ int status;
-+
-+ ring = container_of(work, struct xen_9pfs_dataring, work);
-+ priv = ring->priv;
-+
-+ while (1) {
-+ cons = ring->intf->in_cons;
-+ prod = ring->intf->in_prod;
-+ virt_rmb();
-+
-+ if (xen_9pfs_queued(prod, cons, XEN_9PFS_RING_SIZE) <
-+ sizeof(h)) {
-+ notify_remote_via_irq(ring->irq);
-+ return;
-+ }
-+
-+ masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE);
-+ masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE);
-+
-+ /* First, read just the header */
-+ xen_9pfs_read_packet(&h, ring->data.in, sizeof(h),
-+ masked_prod, &masked_cons,
-+ XEN_9PFS_RING_SIZE);
-+
-+ req = p9_tag_lookup(priv->client, h.tag);
-+ if (!req || req->status != REQ_STATUS_SENT) {
-+ dev_warn(&priv->dev->dev, "Wrong req tag=%x\n", h.tag);
-+ cons += h.size;
-+ virt_mb();
-+ ring->intf->in_cons = cons;
-+ continue;
-+ }
-+
-+ memcpy(req->rc, &h, sizeof(h));
-+ req->rc->offset = 0;
-+
-+ masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE);
-+ /* Then, read the whole packet (including the header) */
-+ xen_9pfs_read_packet(req->rc->sdata, ring->data.in, h.size,
-+ masked_prod, &masked_cons,
-+ XEN_9PFS_RING_SIZE);
-+
-+ virt_mb();
-+ cons += h.size;
-+ ring->intf->in_cons = cons;
-+
-+ status = (req->status != REQ_STATUS_ERROR) ?
-+ REQ_STATUS_RCVD : REQ_STATUS_ERROR;
-+
-+ p9_client_cb(priv->client, req, status);
-+ }
- }
-
- static irqreturn_t xen_9pfs_front_event_handler(int irq, void *r)
---
-1.9.1
-
+++ /dev/null
-From d4b40a02f83777b5fdde2cc1dcce5272bd9abb9c Mon Sep 17 00:00:00 2001
-From: Stefano Stabellini <sstabellini@kernel.org>
-Date: Wed, 5 Apr 2017 12:04:01 -0700
-Subject: [PATCH 7/8] xen/9pfs: build 9pfs Xen transport driver
-
-This patch adds a Kconfig option and Makefile support for building the
-9pfs Xen driver.
-
-CC: groug@kaod.org
-CC: boris.ostrovsky@oracle.com
-CC: jgross@suse.com
-CC: Eric Van Hensbergen <ericvh@gmail.com>
-CC: Ron Minnich <rminnich@sandia.gov>
-CC: Latchesar Ionkov <lucho@ionkov.net>
-CC: v9fs-developer@lists.sourceforge.net
-
-Signed-off-by: Stefano Stabellini <stefano@aporeto.com>
-Reviewed-by: Juergen Gross <jgross@suse.com>
-Signed-off-by: Juergen Gross <jgross@suse.com>
----
- net/9p/Kconfig | 8 ++++++++
- net/9p/Makefile | 4 ++++
- 2 files changed, 12 insertions(+)
-
-diff --git a/net/9p/Kconfig b/net/9p/Kconfig
-index a75174a..3f286f1 100644
---- a/net/9p/Kconfig
-+++ b/net/9p/Kconfig
-@@ -22,6 +22,14 @@ config NET_9P_VIRTIO
- This builds support for a transports between
- guest partitions and a host partition.
-
-+config NET_9P_XEN
-+ depends on XEN
-+ tristate "9P Xen Transport"
-+ help
-+ This builds support for a transport for 9pfs between
-+ two Xen domains.
-+
-+
- config NET_9P_RDMA
- depends on INET && INFINIBAND && INFINIBAND_ADDR_TRANS
- tristate "9P RDMA Transport (Experimental)"
-diff --git a/net/9p/Makefile b/net/9p/Makefile
-index a0874cc..697ea7c 100644
---- a/net/9p/Makefile
-+++ b/net/9p/Makefile
-@@ -1,4 +1,5 @@
- obj-$(CONFIG_NET_9P) := 9pnet.o
-+obj-$(CONFIG_NET_9P_XEN) += 9pnet_xen.o
- obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o
- obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o
-
-@@ -14,5 +15,8 @@ obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o
- 9pnet_virtio-objs := \
- trans_virtio.o \
-
-+9pnet_xen-objs := \
-+ trans_xen.o \
-+
- 9pnet_rdma-objs := \
- trans_rdma.o \
---
-1.9.1
-
+++ /dev/null
-From cb85ed3f93ecbda799a561ad224d4ca7ad3b6b41 Mon Sep 17 00:00:00 2001
-From: Stefano Stabellini <sstabellini@kernel.org>
-Date: Thu, 13 Apr 2017 10:45:23 -0700
-Subject: [PATCH 8/8] xen/9pfs: initialize len to 0 to detect xenbus_read
- errors
-
-In order to use "len" to check for xenbus_read errors properly, we need
-to initialize len to 0 before passing it to xenbus_read.
-
-Signed-off-by: Stefano Stabellini <stefano@aporeto.com>
-CC: dan.carpenter@oracle.com
-CC: jgross@suse.com
-CC: boris.ostrovsky@oracle.com
-CC: Eric Van Hensbergen <ericvh@gmail.com>
-CC: Ron Minnich <rminnich@sandia.gov>
-CC: Latchesar Ionkov <lucho@ionkov.net>
-CC: v9fs-developer@lists.sourceforge.net
-
----
- net/9p/trans_xen.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
-index 4786424..71e8564 100644
---- a/net/9p/trans_xen.c
-+++ b/net/9p/trans_xen.c
-@@ -386,7 +386,7 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev,
- struct xenbus_transaction xbt;
- struct xen_9pfs_front_priv *priv = NULL;
- char *versions;
-- unsigned int max_rings, max_ring_order, len;
-+ unsigned int max_rings, max_ring_order, len = 0;
-
- versions = xenbus_read(XBT_NIL, dev->otherend, "versions", &len);
- if (!len)
---
-1.9.1
-