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 <net/9p/9p.h>
42 #include <net/9p/client.h>
43 #include <net/9p/transport.h>
45 #define XEN_9PFS_NUM_RINGS 2
46 #define XEN_9PFS_RING_ORDER 6
47 #define XEN_9PFS_RING_SIZE XEN_FLEX_RING_SIZE(XEN_9PFS_RING_ORDER)
49 struct xen_9pfs_header
{
54 /* uint8_t sdata[]; */
55 } __attribute__((packed
));
57 /* One per ring, more than one per 9pfs share */
58 struct xen_9pfs_dataring
{
59 struct xen_9pfs_front_priv
*priv
;
61 struct xen_9pfs_data_intf
*intf
;
65 /* protect a ring from concurrent accesses */
68 struct xen_9pfs_data data
;
70 struct work_struct work
;
73 /* One per 9pfs share */
74 struct xen_9pfs_front_priv
{
75 struct list_head list
;
76 struct xenbus_device
*dev
;
78 struct p9_client
*client
;
81 struct xen_9pfs_dataring
*rings
;
84 static LIST_HEAD(xen_9pfs_devs
);
85 static DEFINE_RWLOCK(xen_9pfs_lock
);
87 /* We don't currently allow canceling of requests */
88 static int p9_xen_cancel(struct p9_client
*client
, struct p9_req_t
*req
)
93 static int p9_xen_create(struct p9_client
*client
, const char *addr
, char *args
)
95 struct xen_9pfs_front_priv
*priv
;
100 read_lock(&xen_9pfs_lock
);
101 list_for_each_entry(priv
, &xen_9pfs_devs
, list
) {
102 if (!strcmp(priv
->tag
, addr
)) {
103 priv
->client
= client
;
104 read_unlock(&xen_9pfs_lock
);
108 read_unlock(&xen_9pfs_lock
);
112 static void p9_xen_close(struct p9_client
*client
)
114 struct xen_9pfs_front_priv
*priv
;
116 read_lock(&xen_9pfs_lock
);
117 list_for_each_entry(priv
, &xen_9pfs_devs
, list
) {
118 if (priv
->client
== client
) {
120 read_unlock(&xen_9pfs_lock
);
124 read_unlock(&xen_9pfs_lock
);
127 static bool p9_xen_write_todo(struct xen_9pfs_dataring
*ring
, RING_IDX size
)
131 cons
= ring
->intf
->out_cons
;
132 prod
= ring
->intf
->out_prod
;
135 return XEN_9PFS_RING_SIZE
-
136 xen_9pfs_queued(prod
, cons
, XEN_9PFS_RING_SIZE
) >= size
;
139 static int p9_xen_request(struct p9_client
*client
, struct p9_req_t
*p9_req
)
141 struct xen_9pfs_front_priv
*priv
= NULL
;
142 RING_IDX cons
, prod
, masked_cons
, masked_prod
;
144 u32 size
= p9_req
->tc
->size
;
145 struct xen_9pfs_dataring
*ring
;
148 read_lock(&xen_9pfs_lock
);
149 list_for_each_entry(priv
, &xen_9pfs_devs
, list
) {
150 if (priv
->client
== client
)
153 read_unlock(&xen_9pfs_lock
);
154 if (!priv
|| priv
->client
!= client
)
157 num
= p9_req
->tc
->tag
% priv
->num_rings
;
158 ring
= &priv
->rings
[num
];
161 while (wait_event_killable(ring
->wq
,
162 p9_xen_write_todo(ring
, size
)) != 0)
165 spin_lock_irqsave(&ring
->lock
, flags
);
166 cons
= ring
->intf
->out_cons
;
167 prod
= ring
->intf
->out_prod
;
170 if (XEN_9PFS_RING_SIZE
- xen_9pfs_queued(prod
, cons
,
171 XEN_9PFS_RING_SIZE
) < size
) {
172 spin_unlock_irqrestore(&ring
->lock
, flags
);
176 masked_prod
= xen_9pfs_mask(prod
, XEN_9PFS_RING_SIZE
);
177 masked_cons
= xen_9pfs_mask(cons
, XEN_9PFS_RING_SIZE
);
179 xen_9pfs_write_packet(ring
->data
.out
, p9_req
->tc
->sdata
, size
,
180 &masked_prod
, masked_cons
, XEN_9PFS_RING_SIZE
);
182 p9_req
->status
= REQ_STATUS_SENT
;
183 virt_wmb(); /* write ring before updating pointer */
185 ring
->intf
->out_prod
= prod
;
186 spin_unlock_irqrestore(&ring
->lock
, flags
);
187 notify_remote_via_irq(ring
->irq
);
192 static void p9_xen_response(struct work_struct
*work
)
194 struct xen_9pfs_front_priv
*priv
;
195 struct xen_9pfs_dataring
*ring
;
196 RING_IDX cons
, prod
, masked_cons
, masked_prod
;
197 struct xen_9pfs_header h
;
198 struct p9_req_t
*req
;
201 ring
= container_of(work
, struct xen_9pfs_dataring
, work
);
205 cons
= ring
->intf
->in_cons
;
206 prod
= ring
->intf
->in_prod
;
209 if (xen_9pfs_queued(prod
, cons
, XEN_9PFS_RING_SIZE
) <
211 notify_remote_via_irq(ring
->irq
);
215 masked_prod
= xen_9pfs_mask(prod
, XEN_9PFS_RING_SIZE
);
216 masked_cons
= xen_9pfs_mask(cons
, XEN_9PFS_RING_SIZE
);
218 /* First, read just the header */
219 xen_9pfs_read_packet(&h
, ring
->data
.in
, sizeof(h
),
220 masked_prod
, &masked_cons
,
223 req
= p9_tag_lookup(priv
->client
, h
.tag
);
224 if (!req
|| req
->status
!= REQ_STATUS_SENT
) {
225 dev_warn(&priv
->dev
->dev
, "Wrong req tag=%x\n", h
.tag
);
228 ring
->intf
->in_cons
= cons
;
232 memcpy(req
->rc
, &h
, sizeof(h
));
235 masked_cons
= xen_9pfs_mask(cons
, XEN_9PFS_RING_SIZE
);
236 /* Then, read the whole packet (including the header) */
237 xen_9pfs_read_packet(req
->rc
->sdata
, ring
->data
.in
, h
.size
,
238 masked_prod
, &masked_cons
,
243 ring
->intf
->in_cons
= cons
;
245 status
= (req
->status
!= REQ_STATUS_ERROR
) ?
246 REQ_STATUS_RCVD
: REQ_STATUS_ERROR
;
248 p9_client_cb(priv
->client
, req
, status
);
252 static irqreturn_t
xen_9pfs_front_event_handler(int irq
, void *r
)
254 struct xen_9pfs_dataring
*ring
= r
;
256 if (!ring
|| !ring
->priv
->client
) {
257 /* ignore spurious interrupt */
261 wake_up_interruptible(&ring
->wq
);
262 schedule_work(&ring
->work
);
267 static struct p9_trans_module p9_xen_trans
= {
269 .maxsize
= 1 << (XEN_9PFS_RING_ORDER
+ XEN_PAGE_SHIFT
),
271 .create
= p9_xen_create
,
272 .close
= p9_xen_close
,
273 .request
= p9_xen_request
,
274 .cancel
= p9_xen_cancel
,
275 .owner
= THIS_MODULE
,
278 static const struct xenbus_device_id xen_9pfs_front_ids
[] = {
283 static void xen_9pfs_front_free(struct xen_9pfs_front_priv
*priv
)
287 write_lock(&xen_9pfs_lock
);
288 list_del(&priv
->list
);
289 write_unlock(&xen_9pfs_lock
);
291 for (i
= 0; i
< priv
->num_rings
; i
++) {
292 if (!priv
->rings
[i
].intf
)
294 if (priv
->rings
[i
].irq
> 0)
295 unbind_from_irqhandler(priv
->rings
[i
].irq
, priv
->dev
);
296 if (priv
->rings
[i
].data
.in
) {
297 for (j
= 0; j
< (1 << XEN_9PFS_RING_ORDER
); j
++) {
300 ref
= priv
->rings
[i
].intf
->ref
[j
];
301 gnttab_end_foreign_access(ref
, 0, 0);
303 free_pages((unsigned long)priv
->rings
[i
].data
.in
,
304 XEN_9PFS_RING_ORDER
-
305 (PAGE_SHIFT
- XEN_PAGE_SHIFT
));
307 gnttab_end_foreign_access(priv
->rings
[i
].ref
, 0, 0);
308 free_page((unsigned long)priv
->rings
[i
].intf
);
315 static int xen_9pfs_front_remove(struct xenbus_device
*dev
)
317 struct xen_9pfs_front_priv
*priv
= dev_get_drvdata(&dev
->dev
);
319 dev_set_drvdata(&dev
->dev
, NULL
);
320 xen_9pfs_front_free(priv
);
324 static int xen_9pfs_front_alloc_dataring(struct xenbus_device
*dev
,
325 struct xen_9pfs_dataring
*ring
)
331 init_waitqueue_head(&ring
->wq
);
332 spin_lock_init(&ring
->lock
);
333 INIT_WORK(&ring
->work
, p9_xen_response
);
335 ring
->intf
= (struct xen_9pfs_data_intf
*)get_zeroed_page(GFP_KERNEL
);
338 ret
= gnttab_grant_foreign_access(dev
->otherend_id
,
339 virt_to_gfn(ring
->intf
), 0);
343 bytes
= (void *)__get_free_pages(GFP_KERNEL
| __GFP_ZERO
,
344 XEN_9PFS_RING_ORDER
- (PAGE_SHIFT
- XEN_PAGE_SHIFT
));
349 for (; i
< (1 << XEN_9PFS_RING_ORDER
); i
++) {
350 ret
= gnttab_grant_foreign_access(
351 dev
->otherend_id
, virt_to_gfn(bytes
) + i
, 0);
354 ring
->intf
->ref
[i
] = ret
;
356 ring
->intf
->ring_order
= XEN_9PFS_RING_ORDER
;
357 ring
->data
.in
= bytes
;
358 ring
->data
.out
= bytes
+ XEN_9PFS_RING_SIZE
;
360 ret
= xenbus_alloc_evtchn(dev
, &ring
->evtchn
);
363 ring
->irq
= bind_evtchn_to_irqhandler(ring
->evtchn
,
364 xen_9pfs_front_event_handler
,
365 0, "xen_9pfs-frontend", ring
);
369 xenbus_free_evtchn(dev
, ring
->evtchn
);
373 for (i
--; i
>= 0; i
--)
374 gnttab_end_foreign_access(ring
->intf
->ref
[i
], 0, 0);
375 free_pages((unsigned long)bytes
,
376 XEN_9PFS_RING_ORDER
-
377 (PAGE_SHIFT
- XEN_PAGE_SHIFT
));
379 gnttab_end_foreign_access(ring
->ref
, 0, 0);
380 free_page((unsigned long)ring
->intf
);
384 static int xen_9pfs_front_probe(struct xenbus_device
*dev
,
385 const struct xenbus_device_id
*id
)
388 struct xenbus_transaction xbt
;
389 struct xen_9pfs_front_priv
*priv
= NULL
;
391 unsigned int max_rings
, max_ring_order
, len
= 0;
393 versions
= xenbus_read(XBT_NIL
, dev
->otherend
, "versions", &len
);
396 if (strcmp(versions
, "1")) {
401 max_rings
= xenbus_read_unsigned(dev
->otherend
, "max-rings", 0);
402 if (max_rings
< XEN_9PFS_NUM_RINGS
)
404 max_ring_order
= xenbus_read_unsigned(dev
->otherend
,
405 "max-ring-page-order", 0);
406 if (max_ring_order
< XEN_9PFS_RING_ORDER
)
409 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
414 priv
->num_rings
= XEN_9PFS_NUM_RINGS
;
415 priv
->rings
= kcalloc(priv
->num_rings
, sizeof(*priv
->rings
),
422 for (i
= 0; i
< priv
->num_rings
; i
++) {
423 priv
->rings
[i
].priv
= priv
;
424 ret
= xen_9pfs_front_alloc_dataring(dev
, &priv
->rings
[i
]);
430 ret
= xenbus_transaction_start(&xbt
);
432 xenbus_dev_fatal(dev
, ret
, "starting transaction");
435 ret
= xenbus_printf(xbt
, dev
->nodename
, "version", "%u", 1);
438 ret
= xenbus_printf(xbt
, dev
->nodename
, "num-rings", "%u",
442 for (i
= 0; i
< priv
->num_rings
; i
++) {
445 BUILD_BUG_ON(XEN_9PFS_NUM_RINGS
> 9);
446 sprintf(str
, "ring-ref%u", i
);
447 ret
= xenbus_printf(xbt
, dev
->nodename
, str
, "%d",
452 sprintf(str
, "event-channel-%u", i
);
453 ret
= xenbus_printf(xbt
, dev
->nodename
, str
, "%u",
454 priv
->rings
[i
].evtchn
);
458 priv
->tag
= xenbus_read(xbt
, dev
->nodename
, "tag", NULL
);
459 if (IS_ERR(priv
->tag
)) {
460 ret
= PTR_ERR(priv
->tag
);
463 ret
= xenbus_transaction_end(xbt
, 0);
467 xenbus_dev_fatal(dev
, ret
, "completing transaction");
471 write_lock(&xen_9pfs_lock
);
472 list_add_tail(&priv
->list
, &xen_9pfs_devs
);
473 write_unlock(&xen_9pfs_lock
);
474 dev_set_drvdata(&dev
->dev
, priv
);
475 xenbus_switch_state(dev
, XenbusStateInitialised
);
480 xenbus_transaction_end(xbt
, 1);
481 xenbus_dev_fatal(dev
, ret
, "writing xenstore");
483 dev_set_drvdata(&dev
->dev
, NULL
);
484 xen_9pfs_front_free(priv
);
488 static int xen_9pfs_front_resume(struct xenbus_device
*dev
)
490 dev_warn(&dev
->dev
, "suspend/resume unsupported\n");
494 static void xen_9pfs_front_changed(struct xenbus_device
*dev
,
495 enum xenbus_state backend_state
)
497 switch (backend_state
) {
498 case XenbusStateReconfiguring
:
499 case XenbusStateReconfigured
:
500 case XenbusStateInitialising
:
501 case XenbusStateInitialised
:
502 case XenbusStateUnknown
:
505 case XenbusStateInitWait
:
508 case XenbusStateConnected
:
509 xenbus_switch_state(dev
, XenbusStateConnected
);
512 case XenbusStateClosed
:
513 if (dev
->state
== XenbusStateClosed
)
515 /* Missed the backend's CLOSING state -- fallthrough */
516 case XenbusStateClosing
:
517 xenbus_frontend_closed(dev
);
522 static struct xenbus_driver xen_9pfs_front_driver
= {
523 .ids
= xen_9pfs_front_ids
,
524 .probe
= xen_9pfs_front_probe
,
525 .remove
= xen_9pfs_front_remove
,
526 .resume
= xen_9pfs_front_resume
,
527 .otherend_changed
= xen_9pfs_front_changed
,
530 static int p9_trans_xen_init(void)
535 pr_info("Initialising Xen transport for 9pfs\n");
537 v9fs_register_trans(&p9_xen_trans
);
538 return xenbus_register_frontend(&xen_9pfs_front_driver
);
540 module_init(p9_trans_xen_init
);
542 static void p9_trans_xen_exit(void)
544 v9fs_unregister_trans(&p9_xen_trans
);
545 return xenbus_unregister_driver(&xen_9pfs_front_driver
);
547 module_exit(p9_trans_xen_exit
);
549 MODULE_AUTHOR("Stefano Stabellini <stefano@aporeto.com>");
550 MODULE_DESCRIPTION("Xen Transport for 9P");
551 MODULE_LICENSE("GPL");