[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 4/7] Mini-OS: add 9pfs frontend



Juergen Gross, le ven. 10 févr. 2023 11:46:25 +0100, a ecrit:
> Add a frontend for the 9pfs PV device. For now add only the code needed
> to connect to the backend and the related disconnect functionality. The
> 9pfs protocol support will be added later.
> 
> Due to its nature (ability to access files) the whole code is guarded
> by "#ifdef HAVE_LIBC".
> 
> Signed-off-by: Juergen Gross <jgross@xxxxxxxx>

Reviewed-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>

> ---
> V2:
> - add better error handling to version parsing (Samuel Thibault)
> ---
>  9pfront.c                     | 286 ++++++++++++++++++++++++++++++++++
>  Config.mk                     |   1 +
>  Makefile                      |   1 +
>  arch/x86/testbuild/all-no     |   1 +
>  arch/x86/testbuild/all-yes    |   1 +
>  arch/x86/testbuild/newxen-yes |   1 +
>  include/9pfront.h             |   7 +
>  7 files changed, 298 insertions(+)
>  create mode 100644 9pfront.c
>  create mode 100644 include/9pfront.h
> 
> diff --git a/9pfront.c b/9pfront.c
> new file mode 100644
> index 00000000..89ecb3a1
> --- /dev/null
> +++ b/9pfront.c
> @@ -0,0 +1,286 @@
> +/*
> + * Minimal 9pfs PV frontend for Mini-OS.
> + * Copyright (c) 2023 Juergen Gross, SUSE Software Solution GmbH
> + */
> +
> +#include <mini-os/os.h>
> +#include <mini-os/lib.h>
> +#include <mini-os/events.h>
> +#include <mini-os/gnttab.h>
> +#include <mini-os/xenbus.h>
> +#include <mini-os/xmalloc.h>
> +#include <errno.h>
> +#include <xen/io/9pfs.h>
> +#include <mini-os/9pfront.h>
> +
> +#ifdef HAVE_LIBC
> +struct dev_9pfs {
> +    int id;
> +    char nodename[20];
> +    unsigned int dom;
> +    char *backend;
> +
> +    char *tag;
> +    const char *mnt;
> +
> +    struct xen_9pfs_data_intf *intf;
> +    struct xen_9pfs_data data;
> +    RING_IDX prod_pvt_out;
> +    RING_IDX cons_pvt_in;
> +
> +    grant_ref_t ring_ref;
> +    evtchn_port_t evtchn;
> +    unsigned int ring_order;
> +    xenbus_event_queue events;
> +};
> +
> +#define DEFAULT_9PFS_RING_ORDER  4
> +
> +static unsigned int ftype_9pfs;
> +
> +static void intr_9pfs(evtchn_port_t port, struct pt_regs *regs, void *data)
> +{
> +}
> +
> +static int open_9pfs(struct mount_point *mnt, const char *pathname, int 
> flags,
> +                     mode_t mode)
> +{
> +    errno = ENOSYS;
> +
> +    return -1;
> +}
> +
> +static void free_9pfront(struct dev_9pfs *dev)
> +{
> +    unsigned int i;
> +
> +    if ( dev->data.in && dev->intf )
> +    {
> +        for ( i = 0; i < (1 << dev->ring_order); i++ )
> +            gnttab_end_access(dev->intf->ref[i]);
> +        free_pages(dev->data.in, dev->ring_order);
> +    }
> +    unbind_evtchn(dev->evtchn);
> +    gnttab_end_access(dev->ring_ref);
> +    free_page(dev->intf);
> +    free(dev->backend);
> +    free(dev->tag);
> +    free(dev);
> +}
> +
> +void *init_9pfront(unsigned int id, const char *mnt)
> +{
> +    struct dev_9pfs *dev;
> +    char *msg;
> +    char *reason = "";
> +    xenbus_transaction_t xbt;
> +    int retry = 1;
> +    char bepath[64] = { 0 };
> +    XenbusState state;
> +    unsigned int i;
> +    void *addr;
> +    char *version;
> +    char *v;
> +
> +    printk("9pfsfront add %u, for mount at %s\n", id, mnt);
> +    dev = malloc(sizeof(*dev));
> +    memset(dev, 0, sizeof(*dev));
> +    snprintf(dev->nodename, sizeof(dev->nodename), "device/9pfs/%u", id);
> +    dev->id = id;
> +
> +    msg = xenbus_read_unsigned(XBT_NIL, dev->nodename, "backend-id", 
> &dev->dom);
> +    if ( msg )
> +        goto err;
> +    msg = xenbus_read_string(XBT_NIL, dev->nodename, "backend", 
> &dev->backend);
> +    if ( msg )
> +        goto err;
> +    msg = xenbus_read_string(XBT_NIL, dev->nodename, "tag", &dev->tag);
> +    if ( msg )
> +        goto err;
> +
> +    snprintf(bepath, sizeof(bepath), "%s/state", dev->backend);
> +    free(xenbus_watch_path_token(XBT_NIL, bepath, bepath, &dev->events));
> +    state = xenbus_read_integer(bepath);
> +    while ( msg == NULL && state < XenbusStateInitWait )
> +        msg = xenbus_wait_for_state_change(bepath, &state, &dev->events);
> +    if ( msg || state != XenbusStateInitWait )
> +    {
> +        reason = "illegal backend state";
> +        goto err;
> +    }
> +
> +    msg = xenbus_read_unsigned(XBT_NIL, dev->backend, "max-ring-page-order",
> +                               &dev->ring_order);
> +    if ( msg )
> +        goto err;
> +    if ( dev->ring_order > DEFAULT_9PFS_RING_ORDER )
> +        dev->ring_order = DEFAULT_9PFS_RING_ORDER;
> +
> +    msg = xenbus_read_string(XBT_NIL, dev->backend, "versions", &version);
> +    if ( msg )
> +        goto err;
> +    for ( v = version; *v; v++ )
> +    {
> +        if ( strtoul(v, &v, 10) == 1 && (*v == ',' || *v == 0) )
> +        {
> +            v = NULL;
> +            break;
> +        }
> +        if ( *v != ',' && *v != 0 )
> +        {
> +            reason = "backend published illegal version string";
> +            free(version);
> +            goto err;
> +        }
> +    }
> +    free(version);
> +    if ( v )
> +    {
> +        reason = "backend doesn't support version 1";
> +        goto err;
> +    }
> +
> +    dev->ring_ref = gnttab_alloc_and_grant((void **)&dev->intf);
> +    memset(dev->intf, 0, PAGE_SIZE);
> +    if ( evtchn_alloc_unbound(dev->dom, intr_9pfs, dev, &dev->evtchn) )
> +    {
> +        reason = "no event channel";
> +        goto err;
> +    }
> +    dev->intf->ring_order = dev->ring_order;
> +    dev->data.in = (void *)alloc_pages(dev->ring_order);
> +    dev->data.out = dev->data.in + XEN_FLEX_RING_SIZE(dev->ring_order);
> +    for ( i = 0; i < (1 << dev->ring_order); i++ )
> +    {
> +        addr = dev->data.in + i * PAGE_SIZE;
> +        dev->intf->ref[i] = gnttab_grant_access(dev->dom, virt_to_mfn(addr), 
> 0);
> +    }
> +
> +    while ( retry )
> +    {
> +        msg = xenbus_transaction_start(&xbt);
> +        if ( msg )
> +        {
> +            free(msg);
> +            msg = NULL;
> +            reason = "starting transaction";
> +            goto err;
> +        }
> +
> +        msg = xenbus_printf(xbt, dev->nodename, "version", "%u", 1);
> +        if ( msg )
> +            goto err_tr;
> +        msg = xenbus_printf(xbt, dev->nodename, "num-rings", "%u", 1);
> +        if ( msg )
> +            goto err_tr;
> +        msg = xenbus_printf(xbt, dev->nodename, "ring-ref0", "%u",
> +                            dev->ring_ref);
> +        if ( msg )
> +            goto err_tr;
> +        msg = xenbus_printf(xbt, dev->nodename, "event-channel-0", "%u",
> +                            dev->evtchn);
> +        if ( msg )
> +            goto err_tr;
> +        msg = xenbus_printf(xbt, dev->nodename, "state", "%u",
> +                            XenbusStateInitialised);
> +        if ( msg )
> +            goto err_tr;
> +
> +        free(xenbus_transaction_end(xbt, 0, &retry));
> +    }
> +
> +    state = xenbus_read_integer(bepath);
> +    while ( msg == NULL && state < XenbusStateConnected )
> +        msg = xenbus_wait_for_state_change(bepath, &state, &dev->events);
> +    if ( msg || state != XenbusStateConnected )
> +    {
> +        reason = "illegal backend state";
> +        goto err;
> +    }
> +
> +    msg = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u",
> +                        XenbusStateConnected);
> +    if ( msg )
> +        goto err;
> +
> +    unmask_evtchn(dev->evtchn);
> +
> +    dev->mnt = mnt;
> +    if ( mount(dev->mnt, dev, open_9pfs) )
> +    {
> +        reason = "mount failed";
> +        goto err;
> +    }
> +
> +    return dev;
> +
> + err_tr:
> +    free(xenbus_transaction_end(xbt, 1, &retry));
> +
> + err:
> +    if ( bepath[0] )
> +        free(xenbus_unwatch_path_token(XBT_NIL, bepath, bepath));
> +    if ( msg )
> +        printk("9pfsfront add %u failed, error %s accessing Xenstore\n",
> +               id, msg);
> +    else
> +        printk("9pfsfront add %u failed, %s\n", id, reason);
> +    free_9pfront(dev);
> +    free(msg);
> +    return NULL;
> +}
> +
> +void shutdown_9pfront(void *dev)
> +{
> +    struct dev_9pfs *dev9p = dev;
> +    char bepath[64];
> +    XenbusState state;
> +    char *msg;
> +    char *reason = "";
> +
> +    umount(dev9p->mnt);
> +    snprintf(bepath, sizeof(bepath), "%s/state", dev9p->backend);
> +
> +    msg = xenbus_printf(XBT_NIL, dev9p->nodename, "state", "%u",
> +                        XenbusStateClosing);
> +    if ( msg )
> +        goto err;
> +
> +    state = xenbus_read_integer(bepath);
> +    while ( msg == NULL && state < XenbusStateClosing)
> +        msg = xenbus_wait_for_state_change(bepath, &state, &dev9p->events);
> +    if ( msg || state != XenbusStateClosing )
> +    {
> +        reason = "illegal backend state";
> +        goto err;
> +    }
> +
> +    msg = xenbus_printf(XBT_NIL, dev9p->nodename, "state", "%u",
> +                        XenbusStateClosed);
> +    if ( msg )
> +        goto err;
> +
> +    free_9pfront(dev9p);
> +
> +    return;
> +
> + err:
> +    if ( msg )
> +        printk("9pfsfront shutdown %u failed, error %s accessing Xenstore\n",
> +               dev9p->id, msg);
> +    else
> +        printk("9pfsfront shutdown %u failed, %s\n", dev9p->id, reason);
> +    free(msg);
> +}
> +
> +static const struct file_ops ops_9pfs = {
> +    .name = "9pfs",
> +};
> +
> +__attribute__((constructor))
> +static void initialize_9pfs(void)
> +{
> +    ftype_9pfs = alloc_file_type(&ops_9pfs);
> +}
> +
> +#endif /* HAVE_LIBC */
> diff --git a/Config.mk b/Config.mk
> index 1a24b30e..677e93df 100644
> --- a/Config.mk
> +++ b/Config.mk
> @@ -187,6 +187,7 @@ CONFIG-n += CONFIG_QEMU_XS_ARGS
>  CONFIG-n += CONFIG_TEST
>  CONFIG-n += CONFIG_PCIFRONT
>  CONFIG-n += CONFIG_TPMFRONT
> +CONFIG-n += CONFIG_9PFRONT
>  CONFIG-n += CONFIG_TPM_TIS
>  CONFIG-n += CONFIG_TPMBACK
>  CONFIG-n += CONFIG_BALLOON
> diff --git a/Makefile b/Makefile
> index 747c7c01..7ee181a2 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -39,6 +39,7 @@ SUBDIRS := lib
>  src-$(CONFIG_BLKFRONT) += blkfront.c
>  src-$(CONFIG_CONSFRONT) += consfront.c
>  src-$(CONFIG_TPMFRONT) += tpmfront.c
> +src-$(CONFIG_9PFRONT) += 9pfront.c
>  src-$(CONFIG_TPM_TIS) += tpm_tis.c
>  src-$(CONFIG_TPMBACK) += tpmback.c
>  src-y += console.c
> diff --git a/arch/x86/testbuild/all-no b/arch/x86/testbuild/all-no
> index f79a1012..5b3e99ed 100644
> --- a/arch/x86/testbuild/all-no
> +++ b/arch/x86/testbuild/all-no
> @@ -12,6 +12,7 @@ CONFIG_NETFRONT = n
>  CONFIG_FBFRONT = n
>  CONFIG_KBDFRONT = n
>  CONFIG_CONSFRONT = n
> +CONFIG_9PFRONT = n
>  CONFIG_XENBUS = n
>  CONFIG_LIBXS = n
>  CONFIG_LWIP = n
> diff --git a/arch/x86/testbuild/all-yes b/arch/x86/testbuild/all-yes
> index faa3af32..8ae489a4 100644
> --- a/arch/x86/testbuild/all-yes
> +++ b/arch/x86/testbuild/all-yes
> @@ -12,6 +12,7 @@ CONFIG_NETFRONT = y
>  CONFIG_FBFRONT = y
>  CONFIG_KBDFRONT = y
>  CONFIG_CONSFRONT = y
> +CONFIG_9PFRONT = y
>  CONFIG_XENBUS = y
>  CONFIG_LIBXS = y
>  CONFIG_BALLOON = y
> diff --git a/arch/x86/testbuild/newxen-yes b/arch/x86/testbuild/newxen-yes
> index dc83e670..ee27a328 100644
> --- a/arch/x86/testbuild/newxen-yes
> +++ b/arch/x86/testbuild/newxen-yes
> @@ -12,6 +12,7 @@ CONFIG_NETFRONT = y
>  CONFIG_FBFRONT = y
>  CONFIG_KBDFRONT = y
>  CONFIG_CONSFRONT = y
> +CONFIG_9PFRONT = y
>  CONFIG_XENBUS = y
>  CONFIG_LIBXS = y
>  CONFIG_BALLOON = y
> diff --git a/include/9pfront.h b/include/9pfront.h
> new file mode 100644
> index 00000000..722ec564
> --- /dev/null
> +++ b/include/9pfront.h
> @@ -0,0 +1,7 @@
> +#ifndef __9PFRONT_H__
> +#define __9PFRONT_H__
> +
> +void *init_9pfront(unsigned int id, const char *mnt);
> +void shutdown_9pfront(void *dev);
> +
> +#endif /* __9PFRONT_H__ */
> -- 
> 2.35.3
> 

-- 
Samuel
---
Pour une évaluation indépendante, transparente et rigoureuse !
Je soutiens la Commission d'Évaluation de l'Inria.



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.