Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (5.3 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
#include "virtio-9p-coth.h"
22

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

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

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

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

    
47
VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
48
 {
49
    V9fsState *s;
50
    int i, len;
51
    struct stat stat;
52
    FsTypeEntry *fse;
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
    /* initialize pdu allocator */
60
    QLIST_INIT(&s->free_list);
61
    for (i = 0; i < (MAX_REQ - 1); i++) {
62
        QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next);
63
    }
64

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

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

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

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

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

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

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

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

    
134
    if (v9fs_init_worker_threads() < 0) {
135
        fprintf(stderr, "worker thread initialization failed\n");
136
        exit(1);
137
    }
138
    return &s->vdev;
139
}
140

    
141
static int virtio_9p_init_pci(PCIDevice *pci_dev)
142
{
143
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
144
    VirtIODevice *vdev;
145

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

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

    
171
static void virtio_9p_register_devices(void)
172
{
173
    pci_qdev_register(&virtio_9p_info);
174
}
175

    
176
device_init(virtio_9p_register_devices)