linux/net/9p/trans_xen.c
<<
>>
Prefs
   1/*
   2 * linux/fs/9p/trans_xen
   3 *
   4 * Xen transport layer.
   5 *
   6 * Copyright (C) 2017 by Stefano Stabellini <stefano@aporeto.com>
   7 *
   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:
  13 *
  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:
  20 *
  21 * The above copyright notice and this permission notice shall be included in
  22 * all copies or substantial portions of the Software.
  23 *
  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
  30 * IN THE SOFTWARE.
  31 */
  32
  33#include <xen/events.h>
  34#include <xen/grant_table.h>
  35#include <xen/xen.h>
  36#include <xen/xenbus.h>
  37#include <xen/interface/io/9pfs.h>
  38
  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>
  44
  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)
  48
  49struct xen_9pfs_header {
  50        uint32_t size;
  51        uint8_t id;
  52        uint16_t tag;
  53
  54        /* uint8_t sdata[]; */
  55} __attribute__((packed));
  56
  57/* One per ring, more than one per 9pfs share */
  58struct xen_9pfs_dataring {
  59        struct xen_9pfs_front_priv *priv;
  60
  61        struct xen_9pfs_data_intf *intf;
  62        grant_ref_t ref;
  63        int evtchn;
  64        int irq;
  65        /* protect a ring from concurrent accesses */
  66        spinlock_t lock;
  67
  68        struct xen_9pfs_data data;
  69        wait_queue_head_t wq;
  70        struct work_struct work;
  71};
  72
  73/* One per 9pfs share */
  74struct xen_9pfs_front_priv {
  75        struct list_head list;
  76        struct xenbus_device *dev;
  77        char *tag;
  78        struct p9_client *client;
  79
  80        int num_rings;
  81        struct xen_9pfs_dataring *rings;
  82};
  83
  84static LIST_HEAD(xen_9pfs_devs);
  85static DEFINE_RWLOCK(xen_9pfs_lock);
  86
  87/* We don't currently allow canceling of requests */
  88static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req)
  89{
  90        return 1;
  91}
  92
  93static int p9_xen_create(struct p9_client *client, const char *addr, char *args)
  94{
  95        struct xen_9pfs_front_priv *priv;
  96
  97        if (addr == NULL)
  98                return -EINVAL;
  99
 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);
 105                        return 0;
 106                }
 107        }
 108        read_unlock(&xen_9pfs_lock);
 109        return -EINVAL;
 110}
 111
 112static void p9_xen_close(struct p9_client *client)
 113{
 114        struct xen_9pfs_front_priv *priv;
 115
 116        read_lock(&xen_9pfs_lock);
 117        list_for_each_entry(priv, &xen_9pfs_devs, list) {
 118                if (priv->client == client) {
 119                        priv->client = NULL;
 120                        read_unlock(&xen_9pfs_lock);
 121                        return;
 122                }
 123        }
 124        read_unlock(&xen_9pfs_lock);
 125}
 126
 127static bool p9_xen_write_todo(struct xen_9pfs_dataring *ring, RING_IDX size)
 128{
 129        RING_IDX cons, prod;
 130
 131        cons = ring->intf->out_cons;
 132        prod = ring->intf->out_prod;
 133        virt_mb();
 134
 135        return XEN_9PFS_RING_SIZE -
 136                xen_9pfs_queued(prod, cons, XEN_9PFS_RING_SIZE) >= size;
 137}
 138
 139static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
 140{
 141        struct xen_9pfs_front_priv *priv = NULL;
 142        RING_IDX cons, prod, masked_cons, masked_prod;
 143        unsigned long flags;
 144        u32 size = p9_req->tc.size;
 145        struct xen_9pfs_dataring *ring;
 146        int num;
 147
 148        read_lock(&xen_9pfs_lock);
 149        list_for_each_entry(priv, &xen_9pfs_devs, list) {
 150                if (priv->client == client)
 151                        break;
 152        }
 153        read_unlock(&xen_9pfs_lock);
 154        if (!priv || priv->client != client)
 155                return -EINVAL;
 156
 157        num = p9_req->tc.tag % priv->num_rings;
 158        ring = &priv->rings[num];
 159
 160again:
 161        while (wait_event_killable(ring->wq,
 162                                   p9_xen_write_todo(ring, size)) != 0)
 163                ;
 164
 165        spin_lock_irqsave(&ring->lock, flags);
 166        cons = ring->intf->out_cons;
 167        prod = ring->intf->out_prod;
 168        virt_mb();
 169
 170        if (XEN_9PFS_RING_SIZE - xen_9pfs_queued(prod, cons,
 171                                                 XEN_9PFS_RING_SIZE) < size) {
 172                spin_unlock_irqrestore(&ring->lock, flags);
 173                goto again;
 174        }
 175
 176        masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE);
 177        masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE);
 178
 179        xen_9pfs_write_packet(ring->data.out, p9_req->tc.sdata, size,
 180                              &masked_prod, masked_cons, XEN_9PFS_RING_SIZE);
 181
 182        p9_req->status = REQ_STATUS_SENT;
 183        virt_wmb();                     /* write ring before updating pointer */
 184        prod += size;
 185        ring->intf->out_prod = prod;
 186        spin_unlock_irqrestore(&ring->lock, flags);
 187        notify_remote_via_irq(ring->irq);
 188        p9_req_put(p9_req);
 189
 190        return 0;
 191}
 192
 193static void p9_xen_response(struct work_struct *work)
 194{
 195        struct xen_9pfs_front_priv *priv;
 196        struct xen_9pfs_dataring *ring;
 197        RING_IDX cons, prod, masked_cons, masked_prod;
 198        struct xen_9pfs_header h;
 199        struct p9_req_t *req;
 200        int status;
 201
 202        ring = container_of(work, struct xen_9pfs_dataring, work);
 203        priv = ring->priv;
 204
 205        while (1) {
 206                cons = ring->intf->in_cons;
 207                prod = ring->intf->in_prod;
 208                virt_rmb();
 209
 210                if (xen_9pfs_queued(prod, cons, XEN_9PFS_RING_SIZE) <
 211                    sizeof(h)) {
 212                        notify_remote_via_irq(ring->irq);
 213                        return;
 214                }
 215
 216                masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE);
 217                masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE);
 218
 219                /* First, read just the header */
 220                xen_9pfs_read_packet(&h, ring->data.in, sizeof(h),
 221                                     masked_prod, &masked_cons,
 222                                     XEN_9PFS_RING_SIZE);
 223
 224                req = p9_tag_lookup(priv->client, h.tag);
 225                if (!req || req->status != REQ_STATUS_SENT) {
 226                        dev_warn(&priv->dev->dev, "Wrong req tag=%x\n", h.tag);
 227                        cons += h.size;
 228                        virt_mb();
 229                        ring->intf->in_cons = cons;
 230                        continue;
 231                }
 232
 233                memcpy(&req->rc, &h, sizeof(h));
 234                req->rc.offset = 0;
 235
 236                masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE);
 237                /* Then, read the whole packet (including the header) */
 238                xen_9pfs_read_packet(req->rc.sdata, ring->data.in, h.size,
 239                                     masked_prod, &masked_cons,
 240                                     XEN_9PFS_RING_SIZE);
 241
 242                virt_mb();
 243                cons += h.size;
 244                ring->intf->in_cons = cons;
 245
 246                status = (req->status != REQ_STATUS_ERROR) ?
 247                        REQ_STATUS_RCVD : REQ_STATUS_ERROR;
 248
 249                p9_client_cb(priv->client, req, status);
 250        }
 251}
 252
 253static irqreturn_t xen_9pfs_front_event_handler(int irq, void *r)
 254{
 255        struct xen_9pfs_dataring *ring = r;
 256
 257        if (!ring || !ring->priv->client) {
 258                /* ignore spurious interrupt */
 259                return IRQ_HANDLED;
 260        }
 261
 262        wake_up_interruptible(&ring->wq);
 263        schedule_work(&ring->work);
 264
 265        return IRQ_HANDLED;
 266}
 267
 268static struct p9_trans_module p9_xen_trans = {
 269        .name = "xen",
 270        .maxsize = 1 << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT),
 271        .def = 1,
 272        .create = p9_xen_create,
 273        .close = p9_xen_close,
 274        .request = p9_xen_request,
 275        .cancel = p9_xen_cancel,
 276        .owner = THIS_MODULE,
 277};
 278
 279static const struct xenbus_device_id xen_9pfs_front_ids[] = {
 280        { "9pfs" },
 281        { "" }
 282};
 283
 284static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv)
 285{
 286        int i, j;
 287
 288        write_lock(&xen_9pfs_lock);
 289        list_del(&priv->list);
 290        write_unlock(&xen_9pfs_lock);
 291
 292        for (i = 0; i < priv->num_rings; i++) {
 293                if (!priv->rings[i].intf)
 294                        break;
 295                if (priv->rings[i].irq > 0)
 296                        unbind_from_irqhandler(priv->rings[i].irq, priv->dev);
 297                if (priv->rings[i].data.in) {
 298                        for (j = 0; j < (1 << XEN_9PFS_RING_ORDER); j++) {
 299                                grant_ref_t ref;
 300
 301                                ref = priv->rings[i].intf->ref[j];
 302                                gnttab_end_foreign_access(ref, 0, 0);
 303                        }
 304                        free_pages((unsigned long)priv->rings[i].data.in,
 305                                   XEN_9PFS_RING_ORDER -
 306                                   (PAGE_SHIFT - XEN_PAGE_SHIFT));
 307                }
 308                gnttab_end_foreign_access(priv->rings[i].ref, 0, 0);
 309                free_page((unsigned long)priv->rings[i].intf);
 310        }
 311        kfree(priv->rings);
 312        kfree(priv->tag);
 313        kfree(priv);
 314}
 315
 316static int xen_9pfs_front_remove(struct xenbus_device *dev)
 317{
 318        struct xen_9pfs_front_priv *priv = dev_get_drvdata(&dev->dev);
 319
 320        dev_set_drvdata(&dev->dev, NULL);
 321        xen_9pfs_front_free(priv);
 322        return 0;
 323}
 324
 325static int xen_9pfs_front_alloc_dataring(struct xenbus_device *dev,
 326                                         struct xen_9pfs_dataring *ring)
 327{
 328        int i = 0;
 329        int ret = -ENOMEM;
 330        void *bytes = NULL;
 331
 332        init_waitqueue_head(&ring->wq);
 333        spin_lock_init(&ring->lock);
 334        INIT_WORK(&ring->work, p9_xen_response);
 335
 336        ring->intf = (struct xen_9pfs_data_intf *)get_zeroed_page(GFP_KERNEL);
 337        if (!ring->intf)
 338                return ret;
 339        ret = gnttab_grant_foreign_access(dev->otherend_id,
 340                                          virt_to_gfn(ring->intf), 0);
 341        if (ret < 0)
 342                goto out;
 343        ring->ref = ret;
 344        bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
 345                        XEN_9PFS_RING_ORDER - (PAGE_SHIFT - XEN_PAGE_SHIFT));
 346        if (!bytes) {
 347                ret = -ENOMEM;
 348                goto out;
 349        }
 350        for (; i < (1 << XEN_9PFS_RING_ORDER); i++) {
 351                ret = gnttab_grant_foreign_access(
 352                                dev->otherend_id, virt_to_gfn(bytes) + i, 0);
 353                if (ret < 0)
 354                        goto out;
 355                ring->intf->ref[i] = ret;
 356        }
 357        ring->intf->ring_order = XEN_9PFS_RING_ORDER;
 358        ring->data.in = bytes;
 359        ring->data.out = bytes + XEN_9PFS_RING_SIZE;
 360
 361        ret = xenbus_alloc_evtchn(dev, &ring->evtchn);
 362        if (ret)
 363                goto out;
 364        ring->irq = bind_evtchn_to_irqhandler(ring->evtchn,
 365                                              xen_9pfs_front_event_handler,
 366                                              0, "xen_9pfs-frontend", ring);
 367        if (ring->irq >= 0)
 368                return 0;
 369
 370        xenbus_free_evtchn(dev, ring->evtchn);
 371        ret = ring->irq;
 372out:
 373        if (bytes) {
 374                for (i--; i >= 0; i--)
 375                        gnttab_end_foreign_access(ring->intf->ref[i], 0, 0);
 376                free_pages((unsigned long)bytes,
 377                           XEN_9PFS_RING_ORDER -
 378                           (PAGE_SHIFT - XEN_PAGE_SHIFT));
 379        }
 380        gnttab_end_foreign_access(ring->ref, 0, 0);
 381        free_page((unsigned long)ring->intf);
 382        return ret;
 383}
 384
 385static int xen_9pfs_front_probe(struct xenbus_device *dev,
 386                                const struct xenbus_device_id *id)
 387{
 388        int ret, i;
 389        struct xenbus_transaction xbt;
 390        struct xen_9pfs_front_priv *priv = NULL;
 391        char *versions;
 392        unsigned int max_rings, max_ring_order, len = 0;
 393
 394        versions = xenbus_read(XBT_NIL, dev->otherend, "versions", &len);
 395        if (IS_ERR(versions))
 396                return PTR_ERR(versions);
 397        if (strcmp(versions, "1")) {
 398                kfree(versions);
 399                return -EINVAL;
 400        }
 401        kfree(versions);
 402        max_rings = xenbus_read_unsigned(dev->otherend, "max-rings", 0);
 403        if (max_rings < XEN_9PFS_NUM_RINGS)
 404                return -EINVAL;
 405        max_ring_order = xenbus_read_unsigned(dev->otherend,
 406                                              "max-ring-page-order", 0);
 407        if (max_ring_order < XEN_9PFS_RING_ORDER)
 408                return -EINVAL;
 409
 410        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 411        if (!priv)
 412                return -ENOMEM;
 413
 414        priv->dev = dev;
 415        priv->num_rings = XEN_9PFS_NUM_RINGS;
 416        priv->rings = kcalloc(priv->num_rings, sizeof(*priv->rings),
 417                              GFP_KERNEL);
 418        if (!priv->rings) {
 419                kfree(priv);
 420                return -ENOMEM;
 421        }
 422
 423        for (i = 0; i < priv->num_rings; i++) {
 424                priv->rings[i].priv = priv;
 425                ret = xen_9pfs_front_alloc_dataring(dev, &priv->rings[i]);
 426                if (ret < 0)
 427                        goto error;
 428        }
 429
 430 again:
 431        ret = xenbus_transaction_start(&xbt);
 432        if (ret) {
 433                xenbus_dev_fatal(dev, ret, "starting transaction");
 434                goto error;
 435        }
 436        ret = xenbus_printf(xbt, dev->nodename, "version", "%u", 1);
 437        if (ret)
 438                goto error_xenbus;
 439        ret = xenbus_printf(xbt, dev->nodename, "num-rings", "%u",
 440                            priv->num_rings);
 441        if (ret)
 442                goto error_xenbus;
 443        for (i = 0; i < priv->num_rings; i++) {
 444                char str[16];
 445
 446                BUILD_BUG_ON(XEN_9PFS_NUM_RINGS > 9);
 447                sprintf(str, "ring-ref%u", i);
 448                ret = xenbus_printf(xbt, dev->nodename, str, "%d",
 449                                    priv->rings[i].ref);
 450                if (ret)
 451                        goto error_xenbus;
 452
 453                sprintf(str, "event-channel-%u", i);
 454                ret = xenbus_printf(xbt, dev->nodename, str, "%u",
 455                                    priv->rings[i].evtchn);
 456                if (ret)
 457                        goto error_xenbus;
 458        }
 459        priv->tag = xenbus_read(xbt, dev->nodename, "tag", NULL);
 460        if (IS_ERR(priv->tag)) {
 461                ret = PTR_ERR(priv->tag);
 462                goto error_xenbus;
 463        }
 464        ret = xenbus_transaction_end(xbt, 0);
 465        if (ret) {
 466                if (ret == -EAGAIN)
 467                        goto again;
 468                xenbus_dev_fatal(dev, ret, "completing transaction");
 469                goto error;
 470        }
 471
 472        write_lock(&xen_9pfs_lock);
 473        list_add_tail(&priv->list, &xen_9pfs_devs);
 474        write_unlock(&xen_9pfs_lock);
 475        dev_set_drvdata(&dev->dev, priv);
 476        xenbus_switch_state(dev, XenbusStateInitialised);
 477
 478        return 0;
 479
 480 error_xenbus:
 481        xenbus_transaction_end(xbt, 1);
 482        xenbus_dev_fatal(dev, ret, "writing xenstore");
 483 error:
 484        dev_set_drvdata(&dev->dev, NULL);
 485        xen_9pfs_front_free(priv);
 486        return ret;
 487}
 488
 489static int xen_9pfs_front_resume(struct xenbus_device *dev)
 490{
 491        dev_warn(&dev->dev, "suspend/resume unsupported\n");
 492        return 0;
 493}
 494
 495static void xen_9pfs_front_changed(struct xenbus_device *dev,
 496                                   enum xenbus_state backend_state)
 497{
 498        switch (backend_state) {
 499        case XenbusStateReconfiguring:
 500        case XenbusStateReconfigured:
 501        case XenbusStateInitialising:
 502        case XenbusStateInitialised:
 503        case XenbusStateUnknown:
 504                break;
 505
 506        case XenbusStateInitWait:
 507                break;
 508
 509        case XenbusStateConnected:
 510                xenbus_switch_state(dev, XenbusStateConnected);
 511                break;
 512
 513        case XenbusStateClosed:
 514                if (dev->state == XenbusStateClosed)
 515                        break;
 516                /* Missed the backend's CLOSING state -- fallthrough */
 517        case XenbusStateClosing:
 518                xenbus_frontend_closed(dev);
 519                break;
 520        }
 521}
 522
 523static struct xenbus_driver xen_9pfs_front_driver = {
 524        .ids = xen_9pfs_front_ids,
 525        .probe = xen_9pfs_front_probe,
 526        .remove = xen_9pfs_front_remove,
 527        .resume = xen_9pfs_front_resume,
 528        .otherend_changed = xen_9pfs_front_changed,
 529};
 530
 531static int p9_trans_xen_init(void)
 532{
 533        if (!xen_domain())
 534                return -ENODEV;
 535
 536        pr_info("Initialising Xen transport for 9pfs\n");
 537
 538        v9fs_register_trans(&p9_xen_trans);
 539        return xenbus_register_frontend(&xen_9pfs_front_driver);
 540}
 541module_init(p9_trans_xen_init);
 542
 543static void p9_trans_xen_exit(void)
 544{
 545        v9fs_unregister_trans(&p9_xen_trans);
 546        return xenbus_unregister_driver(&xen_9pfs_front_driver);
 547}
 548module_exit(p9_trans_xen_exit);
 549
 550MODULE_AUTHOR("Stefano Stabellini <stefano@aporeto.com>");
 551MODULE_DESCRIPTION("Xen Transport for 9P");
 552MODULE_LICENSE("GPL");
 553