Statistics
| Branch: | Revision:

root / hw / 9pfs / virtio-9p-device.c @ 9bba1eb1

History | View | Annotate | Download (5.1 kB)

1
/*
2
 * Virtio 9p backend
3
 *
4
 * Copyright IBM, Corp. 2010
5
 *
6
 * Authors:
7
 *  Anthony Liguori   <aliguori@us.ibm.com>
8
 *
9
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10
 * the COPYING file in the top-level directory.
11
 *
12
 */
13

    
14
#include "hw/virtio.h"
15
#include "hw/pc.h"
16
#include "qemu_socket.h"
17
#include "hw/virtio-pci.h"
18
#include "virtio-9p.h"
19
#include "fsdev/qemu-fsdev.h"
20
#include "virtio-9p-xattr.h"
21

    
22
static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
23
{
24
    features |= 1 << VIRTIO_9P_MOUNT_TAG;
25
    return features;
26
}
27

    
28
static V9fsState *to_virtio_9p(VirtIODevice *vdev)
29
{
30
    return (V9fsState *)vdev;
31
}
32

    
33
static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
34
{
35
    struct virtio_9p_config *cfg;
36
    V9fsState *s = to_virtio_9p(vdev);
37

    
38
    cfg = qemu_mallocz(sizeof(struct virtio_9p_config) +
39
                        s->tag_len);
40
    stw_raw(&cfg->tag_len, s->tag_len);
41
    memcpy(cfg->tag, s->tag, s->tag_len);
42
    memcpy(config, cfg, s->config_size);
43
    qemu_free(cfg);
44
}
45

    
46
VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
47
 {
48
    V9fsState *s;
49
    int i, len;
50
    struct stat stat;
51
    FsTypeEntry *fse;
52

    
53

    
54
    s = (V9fsState *)virtio_common_init("virtio-9p",
55
                                    VIRTIO_ID_9P,
56
                                    sizeof(struct virtio_9p_config)+
57
                                    MAX_TAG_LEN,
58
                                    sizeof(V9fsState));
59

    
60
    /* initialize pdu allocator */
61
    QLIST_INIT(&s->free_list);
62
    for (i = 0; i < (MAX_REQ - 1); i++) {
63
        QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next);
64
    }
65

    
66
    s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output);
67

    
68
    fse = get_fsdev_fsentry(conf->fsdev_id);
69

    
70
    if (!fse) {
71
        /* We don't have a fsdev identified by fsdev_id */
72
        fprintf(stderr, "Virtio-9p device couldn't find fsdev with the "
73
                "id = %s\n", conf->fsdev_id ? conf->fsdev_id : "NULL");
74
        exit(1);
75
    }
76

    
77
    if (!fse->path || !conf->tag) {
78
        /* we haven't specified a mount_tag or the path */
79
        fprintf(stderr, "fsdev with id %s needs path "
80
                "and Virtio-9p device needs mount_tag arguments\n",
81
                conf->fsdev_id);
82
        exit(1);
83
    }
84

    
85
    if (!strcmp(fse->security_model, "passthrough")) {
86
        /* Files on the Fileserver set to client user credentials */
87
        s->ctx.fs_sm = SM_PASSTHROUGH;
88
        s->ctx.xops = passthrough_xattr_ops;
89
    } else if (!strcmp(fse->security_model, "mapped")) {
90
        /* Files on the fileserver are set to QEMU credentials.
91
         * Client user credentials are saved in extended attributes.
92
         */
93
        s->ctx.fs_sm = SM_MAPPED;
94
        s->ctx.xops = mapped_xattr_ops;
95
    } else if (!strcmp(fse->security_model, "none")) {
96
        /*
97
         * Files on the fileserver are set to QEMU credentials.
98
         */
99
        s->ctx.fs_sm = SM_NONE;
100
        s->ctx.xops = none_xattr_ops;
101
    } else {
102
        fprintf(stderr, "Default to security_model=none. You may want"
103
                " enable advanced security model using "
104
                "security option:\n\t security_model=passthrough\n\t "
105
                "security_model=mapped\n");
106
        s->ctx.fs_sm = SM_NONE;
107
        s->ctx.xops = none_xattr_ops;
108
    }
109

    
110
    if (lstat(fse->path, &stat)) {
111
        fprintf(stderr, "share path %s does not exist\n", fse->path);
112
        exit(1);
113
    } else if (!S_ISDIR(stat.st_mode)) {
114
        fprintf(stderr, "share path %s is not a directory\n", fse->path);
115
        exit(1);
116
    }
117

    
118
    s->ctx.fs_root = qemu_strdup(fse->path);
119
    len = strlen(conf->tag);
120
    if (len > MAX_TAG_LEN) {
121
        len = MAX_TAG_LEN;
122
    }
123
    /* s->tag is non-NULL terminated string */
124
    s->tag = qemu_malloc(len);
125
    memcpy(s->tag, conf->tag, len);
126
    s->tag_len = len;
127
    s->ctx.uid = -1;
128

    
129
    s->ops = fse->ops;
130
    s->vdev.get_features = virtio_9p_get_features;
131
    s->config_size = sizeof(struct virtio_9p_config) +
132
                        s->tag_len;
133
    s->vdev.get_config = virtio_9p_get_config;
134

    
135
    return &s->vdev;
136
}
137

    
138
static int virtio_9p_init_pci(PCIDevice *pci_dev)
139
{
140
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
141
    VirtIODevice *vdev;
142

    
143
    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
144
    vdev->nvectors = proxy->nvectors;
145
    virtio_init_pci(proxy, vdev,
146
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
147
                    0x1009,
148
                    0x2,
149
                    0x00);
150
    /* make the actual value visible */
151
    proxy->nvectors = vdev->nvectors;
152
    return 0;
153
}
154

    
155
static PCIDeviceInfo virtio_9p_info = {
156
    .qdev.name = "virtio-9p-pci",
157
    .qdev.size = sizeof(VirtIOPCIProxy),
158
    .init      = virtio_9p_init_pci,
159
    .qdev.props = (Property[]) {
160
        DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
161
        DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
162
        DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
163
        DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
164
        DEFINE_PROP_END_OF_LIST(),
165
    }
166
};
167

    
168
static void virtio_9p_register_devices(void)
169
{
170
    pci_qdev_register(&virtio_9p_info);
171
}
172

    
173
device_init(virtio_9p_register_devices)