2 * linux/fs/9p/trans_xen
6 * Copyright (C) 2017 by Stefano Stabellini <stefano@aporeto.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation; or, when distributed
11 * separately from the Linux kernel or incorporated into other
12 * software packages, subject to the following license:
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this source file (the "Software"), to deal in the Software without
16 * restriction, including without limitation the rights to use, copy, modify,
17 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18 * and to permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
33 #include <xen/events.h>
34 #include <xen/grant_table.h>
36 #include <xen/xenbus.h>
37 #include <xen/interface/io/9pfs.h>
39 #include <linux/module.h>
40 #include <linux/spinlock.h>
41 #include <linux/rwlock.h>
42 #include <net/9p/9p.h>
43 #include <net/9p/client.h>
44 #include <net/9p/transport.h>
46 #define XEN_9PFS_NUM_RINGS 2
47 #define XEN_9PFS_RING_ORDER 6
48 #define XEN_9PFS_RING_SIZE XEN_FLEX_RING_SIZE(XEN_9PFS_RING_ORDER)
50 struct xen_9pfs_header
{
55 /* uint8_t sdata[]; */
56 } __attribute__((packed
));
58 /* One per ring, more than one per 9pfs share */
59 struct xen_9pfs_dataring
{
60 struct xen_9pfs_front_priv
*priv
;
62 struct xen_9pfs_data_intf
*intf
;
66 /* protect a ring from concurrent accesses */
69 struct xen_9pfs_data data
;
71 struct work_struct work
;
74 /* One per 9pfs share */
75 struct xen_9pfs_front_priv
{
76 struct list_head list
;
77 struct xenbus_device
*dev
;
79 struct p9_client
*client
;
82 struct xen_9pfs_dataring
*rings
;
85 static LIST_HEAD(xen_9pfs_devs
);
86 static DEFINE_RWLOCK(xen_9pfs_lock
);
88 /* We don't currently allow canceling of requests */
89 static int p9_xen_cancel(struct p9_client
*client
, struct p9_req_t
*req
)
94 static int p9_xen_create(struct p9_client
*client
, const char *addr
, char *args
)
96 struct xen_9pfs_front_priv
*priv
;
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
);
106 read_unlock(&xen_9pfs_lock
);
110 static void p9_xen_close(struct p9_client
*client
)
112 struct xen_9pfs_front_priv
*priv
;
114 read_lock(&xen_9pfs_lock
);
115 list_for_each_entry(priv
, &xen_9pfs_devs
, list
) {
116 if (priv
->client
== client
) {
118 read_unlock(&xen_9pfs_lock
);
122 read_unlock(&xen_9pfs_lock
);
125 static bool p9_xen_write_todo(struct xen_9pfs_dataring
*ring
, RING_IDX size
)
129 cons
= ring
->intf
->out_cons
;
130 prod
= ring
->intf
->out_prod
;
133 return XEN_9PFS_RING_SIZE
-
134 xen_9pfs_queued(prod
, cons
, XEN_9PFS_RING_SIZE
) >= size
;
137 static int p9_xen_request(struct p9_client
*client
, struct p9_req_t
*p9_req
)
139 struct xen_9pfs_front_priv
*priv
= NULL
;
140 RING_IDX cons
, prod
, masked_cons
, masked_prod
;
142 u32 size
= p9_req
->tc
->size
;
143 struct xen_9pfs_dataring
*ring
;
146 read_lock(&xen_9pfs_lock
);
147 list_for_each_entry(priv
, &xen_9pfs_devs
, list
) {
148 if (priv
->client
== client
)
151 read_unlock(&xen_9pfs_lock
);
152 if (!priv
|| priv
->client
!= client
)
155 num
= p9_req
->tc
->tag
% priv
->num_rings
;
156 ring
= &priv
->rings
[num
];
159 while (wait_event_killable(ring
->wq
,
160 p9_xen_write_todo(ring
, size
)) != 0)
163 spin_lock_irqsave(&ring
->lock
, flags
);
164 cons
= ring
->intf
->out_cons
;
165 prod
= ring
->intf
->out_prod
;
168 if (XEN_9PFS_RING_SIZE
- xen_9pfs_queued(prod
, cons
,
169 XEN_9PFS_RING_SIZE
) < size
) {
170 spin_unlock_irqrestore(&ring
->lock
, flags
);
174 masked_prod
= xen_9pfs_mask(prod
, XEN_9PFS_RING_SIZE
);
175 masked_cons
= xen_9pfs_mask(cons
, XEN_9PFS_RING_SIZE
);
177 xen_9pfs_write_packet(ring
->data
.out
, p9_req
->tc
->sdata
, size
,
178 &masked_prod
, masked_cons
, XEN_9PFS_RING_SIZE
);
180 p9_req
->status
= REQ_STATUS_SENT
;
181 virt_wmb(); /* write ring before updating pointer */
183 ring
->intf
->out_prod
= prod
;
184 spin_unlock_irqrestore(&ring
->lock
, flags
);
185 notify_remote_via_irq(ring
->irq
);
190 static void p9_xen_response(struct work_struct
*work
)
192 struct xen_9pfs_front_priv
*priv
;
193 struct xen_9pfs_dataring
*ring
;
194 RING_IDX cons
, prod
, masked_cons
, masked_prod
;
195 struct xen_9pfs_header h
;
196 struct p9_req_t
*req
;
199 ring
= container_of(work
, struct xen_9pfs_dataring
, work
);
203 cons
= ring
->intf
->in_cons
;
204 prod
= ring
->intf
->in_prod
;
207 if (xen_9pfs_queued(prod
, cons
, XEN_9PFS_RING_SIZE
) <
209 notify_remote_via_irq(ring
->irq
);
213 masked_prod
= xen_9pfs_mask(prod
, XEN_9PFS_RING_SIZE
);
214 masked_cons
= xen_9pfs_mask(cons
, XEN_9PFS_RING_SIZE
);
216 /* First, read just the header */
217 xen_9pfs_read_packet(&h
, ring
->data
.in
, sizeof(h
),
218 masked_prod
, &masked_cons
,
221 req
= p9_tag_lookup(priv
->client
, h
.tag
);
222 if (!req
|| req
->status
!= REQ_STATUS_SENT
) {
223 dev_warn(&priv
->dev
->dev
, "Wrong req tag=%x\n", h
.tag
);
226 ring
->intf
->in_cons
= cons
;
230 memcpy(req
->rc
, &h
, sizeof(h
));
233 masked_cons
= xen_9pfs_mask(cons
, XEN_9PFS_RING_SIZE
);
234 /* Then, read the whole packet (including the header) */
235 xen_9pfs_read_packet(req
->rc
->sdata
, ring
->data
.in
, h
.size
,
236 masked_prod
, &masked_cons
,
241 ring
->intf
->in_cons
= cons
;
243 status
= (req
->status
!= REQ_STATUS_ERROR
) ?
244 REQ_STATUS_RCVD
: REQ_STATUS_ERROR
;
246 p9_client_cb(priv
->client
, req
, status
);
250 static irqreturn_t
xen_9pfs_front_event_handler(int irq
, void *r
)
252 struct xen_9pfs_dataring
*ring
= r
;
254 if (!ring
|| !ring
->priv
->client
) {
255 /* ignore spurious interrupt */
259 wake_up_interruptible(&ring
->wq
);
260 schedule_work(&ring
->work
);
265 static struct p9_trans_module p9_xen_trans
= {
267 .maxsize
= 1 << (XEN_9PFS_RING_ORDER
+ XEN_PAGE_SHIFT
),
269 .create
= p9_xen_create
,
270 .close
= p9_xen_close
,
271 .request
= p9_xen_request
,
272 .cancel
= p9_xen_cancel
,
273 .owner
= THIS_MODULE
,
276 static const struct xenbus_device_id xen_9pfs_front_ids
[] = {
281 static void xen_9pfs_front_free(struct xen_9pfs_front_priv
*priv
)
285 write_lock(&xen_9pfs_lock
);
286 list_del(&priv
->list
);
287 write_unlock(&xen_9pfs_lock
);
289 for (i
= 0; i
< priv
->num_rings
; i
++) {
290 if (!priv
->rings
[i
].intf
)
292 if (priv
->rings
[i
].irq
> 0)
293 unbind_from_irqhandler(priv
->rings
[i
].irq
, priv
->dev
);
294 if (priv
->rings
[i
].data
.in
) {
295 for (j
= 0; j
< (1 << XEN_9PFS_RING_ORDER
); j
++) {
298 ref
= priv
->rings
[i
].intf
->ref
[j
];
299 gnttab_end_foreign_access(ref
, 0, 0);
301 free_pages((unsigned long)priv
->rings
[i
].data
.in
,
302 XEN_9PFS_RING_ORDER
-
303 (PAGE_SHIFT
- XEN_PAGE_SHIFT
));
305 gnttab_end_foreign_access(priv
->rings
[i
].ref
, 0, 0);
306 free_page((unsigned long)priv
->rings
[i
].intf
);
313 static int xen_9pfs_front_remove(struct xenbus_device
*dev
)
315 struct xen_9pfs_front_priv
*priv
= dev_get_drvdata(&dev
->dev
);
317 dev_set_drvdata(&dev
->dev
, NULL
);
318 xen_9pfs_front_free(priv
);
322 static int xen_9pfs_front_alloc_dataring(struct xenbus_device
*dev
,
323 struct xen_9pfs_dataring
*ring
)
329 init_waitqueue_head(&ring
->wq
);
330 spin_lock_init(&ring
->lock
);
331 INIT_WORK(&ring
->work
, p9_xen_response
);
333 ring
->intf
= (struct xen_9pfs_data_intf
*)get_zeroed_page(GFP_KERNEL
);
336 ret
= gnttab_grant_foreign_access(dev
->otherend_id
,
337 virt_to_gfn(ring
->intf
), 0);
341 bytes
= (void *)__get_free_pages(GFP_KERNEL
| __GFP_ZERO
,
342 XEN_9PFS_RING_ORDER
- (PAGE_SHIFT
- XEN_PAGE_SHIFT
));
347 for (; i
< (1 << XEN_9PFS_RING_ORDER
); i
++) {
348 ret
= gnttab_grant_foreign_access(
349 dev
->otherend_id
, virt_to_gfn(bytes
) + i
, 0);
352 ring
->intf
->ref
[i
] = ret
;
354 ring
->intf
->ring_order
= XEN_9PFS_RING_ORDER
;
355 ring
->data
.in
= bytes
;
356 ring
->data
.out
= bytes
+ XEN_9PFS_RING_SIZE
;
358 ret
= xenbus_alloc_evtchn(dev
, &ring
->evtchn
);
361 ring
->irq
= bind_evtchn_to_irqhandler(ring
->evtchn
,
362 xen_9pfs_front_event_handler
,
363 0, "xen_9pfs-frontend", ring
);
367 xenbus_free_evtchn(dev
, ring
->evtchn
);
371 for (i
--; i
>= 0; i
--)
372 gnttab_end_foreign_access(ring
->intf
->ref
[i
], 0, 0);
373 free_pages((unsigned long)bytes
,
374 XEN_9PFS_RING_ORDER
-
375 (PAGE_SHIFT
- XEN_PAGE_SHIFT
));
377 gnttab_end_foreign_access(ring
->ref
, 0, 0);
378 free_page((unsigned long)ring
->intf
);
382 static int xen_9pfs_front_probe(struct xenbus_device
*dev
,
383 const struct xenbus_device_id
*id
)
386 struct xenbus_transaction xbt
;
387 struct xen_9pfs_front_priv
*priv
= NULL
;
389 unsigned int max_rings
, max_ring_order
, len
= 0;
391 versions
= xenbus_read(XBT_NIL
, dev
->otherend
, "versions", &len
);
394 if (strcmp(versions
, "1")) {
399 max_rings
= xenbus_read_unsigned(dev
->otherend
, "max-rings", 0);
400 if (max_rings
< XEN_9PFS_NUM_RINGS
)
402 max_ring_order
= xenbus_read_unsigned(dev
->otherend
,
403 "max-ring-page-order", 0);
404 if (max_ring_order
< XEN_9PFS_RING_ORDER
)
407 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
412 priv
->num_rings
= XEN_9PFS_NUM_RINGS
;
413 priv
->rings
= kcalloc(priv
->num_rings
, sizeof(*priv
->rings
),
420 for (i
= 0; i
< priv
->num_rings
; i
++) {
421 priv
->rings
[i
].priv
= priv
;
422 ret
= xen_9pfs_front_alloc_dataring(dev
, &priv
->rings
[i
]);
428 ret
= xenbus_transaction_start(&xbt
);
430 xenbus_dev_fatal(dev
, ret
, "starting transaction");
433 ret
= xenbus_printf(xbt
, dev
->nodename
, "version", "%u", 1);
436 ret
= xenbus_printf(xbt
, dev
->nodename
, "num-rings", "%u",
440 for (i
= 0; i
< priv
->num_rings
; i
++) {
443 BUILD_BUG_ON(XEN_9PFS_NUM_RINGS
> 9);
444 sprintf(str
, "ring-ref%u", i
);
445 ret
= xenbus_printf(xbt
, dev
->nodename
, str
, "%d",
450 sprintf(str
, "event-channel-%u", i
);
451 ret
= xenbus_printf(xbt
, dev
->nodename
, str
, "%u",
452 priv
->rings
[i
].evtchn
);
456 priv
->tag
= xenbus_read(xbt
, dev
->nodename
, "tag", NULL
);
457 if (IS_ERR(priv
->tag
)) {
458 ret
= PTR_ERR(priv
->tag
);
461 ret
= xenbus_transaction_end(xbt
, 0);
465 xenbus_dev_fatal(dev
, ret
, "completing transaction");
469 write_lock(&xen_9pfs_lock
);
470 list_add_tail(&priv
->list
, &xen_9pfs_devs
);
471 write_unlock(&xen_9pfs_lock
);
472 dev_set_drvdata(&dev
->dev
, priv
);
473 xenbus_switch_state(dev
, XenbusStateInitialised
);
478 xenbus_transaction_end(xbt
, 1);
479 xenbus_dev_fatal(dev
, ret
, "writing xenstore");
481 dev_set_drvdata(&dev
->dev
, NULL
);
482 xen_9pfs_front_free(priv
);
486 static int xen_9pfs_front_resume(struct xenbus_device
*dev
)
488 dev_warn(&dev
->dev
, "suspsend/resume unsupported\n");
492 static void xen_9pfs_front_changed(struct xenbus_device
*dev
,
493 enum xenbus_state backend_state
)
495 switch (backend_state
) {
496 case XenbusStateReconfiguring
:
497 case XenbusStateReconfigured
:
498 case XenbusStateInitialising
:
499 case XenbusStateInitialised
:
500 case XenbusStateUnknown
:
503 case XenbusStateInitWait
:
506 case XenbusStateConnected
:
507 xenbus_switch_state(dev
, XenbusStateConnected
);
510 case XenbusStateClosed
:
511 if (dev
->state
== XenbusStateClosed
)
513 /* Missed the backend's CLOSING state -- fallthrough */
514 case XenbusStateClosing
:
515 xenbus_frontend_closed(dev
);
520 static struct xenbus_driver xen_9pfs_front_driver
= {
521 .ids
= xen_9pfs_front_ids
,
522 .probe
= xen_9pfs_front_probe
,
523 .remove
= xen_9pfs_front_remove
,
524 .resume
= xen_9pfs_front_resume
,
525 .otherend_changed
= xen_9pfs_front_changed
,
528 static int p9_trans_xen_init(void)
533 pr_info("Initialising Xen transport for 9pfs\n");
535 v9fs_register_trans(&p9_xen_trans
);
536 return xenbus_register_frontend(&xen_9pfs_front_driver
);
538 module_init(p9_trans_xen_init
);
540 static void p9_trans_xen_exit(void)
542 v9fs_unregister_trans(&p9_xen_trans
);
543 return xenbus_unregister_driver(&xen_9pfs_front_driver
);
545 module_exit(p9_trans_xen_exit
);
547 MODULE_AUTHOR("Stefano Stabellini <stefano@aporeto.com>");
548 MODULE_DESCRIPTION("Xen Transport for 9P");
549 MODULE_LICENSE("GPL");