aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefano Stabellini <sstabellini@kernel.org>2017-04-05 15:03:59 -0400
committerJuergen Gross <jgross@suse.com>2017-05-02 05:11:37 -0400
commitf023f18ddf41dda487241d1514075b1136eb8101 (patch)
treee01c66999a80caf727f1f36acbdc574523830f61
parent71ebd71921e451f0f942ddfe85d01e31ddc6eb88 (diff)
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>
-rw-r--r--net/9p/trans_xen.c87
1 files changed, 85 insertions, 2 deletions
diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
index fe3d172391c4..28f30f49d5dd 100644
--- a/net/9p/trans_xen.c
+++ b/net/9p/trans_xen.c
@@ -85,22 +85,105 @@ struct xen_9pfs_front_priv {
85static LIST_HEAD(xen_9pfs_devs); 85static LIST_HEAD(xen_9pfs_devs);
86static DEFINE_RWLOCK(xen_9pfs_lock); 86static DEFINE_RWLOCK(xen_9pfs_lock);
87 87
88/* We don't currently allow canceling of requests */
88static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req) 89static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req)
89{ 90{
90 return 0; 91 return 1;
91} 92}
92 93
93static int p9_xen_create(struct p9_client *client, const char *addr, char *args) 94static int p9_xen_create(struct p9_client *client, const char *addr, char *args)
94{ 95{
95 return 0; 96 struct xen_9pfs_front_priv *priv;
97
98 read_lock(&xen_9pfs_lock);
99 list_for_each_entry(priv, &xen_9pfs_devs, list) {
100 if (!strcmp(priv->tag, addr)) {
101 priv->client = client;
102 read_unlock(&xen_9pfs_lock);
103 return 0;
104 }
105 }
106 read_unlock(&xen_9pfs_lock);
107 return -EINVAL;
96} 108}
97 109
98static void p9_xen_close(struct p9_client *client) 110static void p9_xen_close(struct p9_client *client)
99{ 111{
112 struct xen_9pfs_front_priv *priv;
113
114 read_lock(&xen_9pfs_lock);
115 list_for_each_entry(priv, &xen_9pfs_devs, list) {
116 if (priv->client == client) {
117 priv->client = NULL;
118 read_unlock(&xen_9pfs_lock);
119 return;
120 }
121 }
122 read_unlock(&xen_9pfs_lock);
123}
124
125static bool p9_xen_write_todo(struct xen_9pfs_dataring *ring, RING_IDX size)
126{
127 RING_IDX cons, prod;
128
129 cons = ring->intf->out_cons;
130 prod = ring->intf->out_prod;
131 virt_mb();
132
133 return XEN_9PFS_RING_SIZE -
134 xen_9pfs_queued(prod, cons, XEN_9PFS_RING_SIZE) >= size;
100} 135}
101 136
102static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req) 137static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
103{ 138{
139 struct xen_9pfs_front_priv *priv = NULL;
140 RING_IDX cons, prod, masked_cons, masked_prod;
141 unsigned long flags;
142 u32 size = p9_req->tc->size;
143 struct xen_9pfs_dataring *ring;
144 int num;
145
146 read_lock(&xen_9pfs_lock);
147 list_for_each_entry(priv, &xen_9pfs_devs, list) {
148 if (priv->client == client)
149 break;
150 }
151 read_unlock(&xen_9pfs_lock);
152 if (!priv || priv->client != client)
153 return -EINVAL;
154
155 num = p9_req->tc->tag % priv->num_rings;
156 ring = &priv->rings[num];
157
158again:
159 while (wait_event_interruptible(ring->wq,
160 p9_xen_write_todo(ring, size)) != 0)
161 ;
162
163 spin_lock_irqsave(&ring->lock, flags);
164 cons = ring->intf->out_cons;
165 prod = ring->intf->out_prod;
166 virt_mb();
167
168 if (XEN_9PFS_RING_SIZE - xen_9pfs_queued(prod, cons,
169 XEN_9PFS_RING_SIZE) < size) {
170 spin_unlock_irqrestore(&ring->lock, flags);
171 goto again;
172 }
173
174 masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE);
175 masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE);
176
177 xen_9pfs_write_packet(ring->data.out, p9_req->tc->sdata, size,
178 &masked_prod, masked_cons, XEN_9PFS_RING_SIZE);
179
180 p9_req->status = REQ_STATUS_SENT;
181 virt_wmb(); /* write ring before updating pointer */
182 prod += size;
183 ring->intf->out_prod = prod;
184 spin_unlock_irqrestore(&ring->lock, flags);
185 notify_remote_via_irq(ring->irq);
186
104 return 0; 187 return 0;
105} 188}
106 189