]> git.proxmox.com Git - mirror_qemu.git/blame - hw/9pfs/virtio-9p-device.c
fsdev: fix some type definitions
[mirror_qemu.git] / hw / 9pfs / virtio-9p-device.c
CommitLineData
f4f61d27
AK
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
9b8bfe21 14#include "qemu/osdep.h"
0d09e41a 15#include "hw/virtio/virtio.h"
1de7afc9 16#include "qemu/sockets.h"
f4f61d27
AK
17#include "virtio-9p.h"
18#include "fsdev/qemu-fsdev.h"
fe52840c 19#include "coth.h"
d64ccb91 20#include "hw/virtio/virtio-access.h"
0192cc5d 21#include "qemu/iov.h"
f4f61d27 22
ea83441c 23static void virtio_9p_push_and_notify(V9fsPDU *pdu)
0d3716b4
WL
24{
25 V9fsState *s = pdu->s;
00588a0a 26 V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
51b19ebe 27 VirtQueueElement *elem = v->elems[pdu->idx];
0d3716b4
WL
28
29 /* push onto queue and notify */
00588a0a 30 virtqueue_push(v->vq, elem, pdu->size);
51b19ebe
PB
31 g_free(elem);
32 v->elems[pdu->idx] = NULL;
0d3716b4
WL
33
34 /* FIXME: we should batch these completions */
00588a0a 35 virtio_notify(VIRTIO_DEVICE(v), v->vq);
0d3716b4
WL
36}
37
0192cc5d
WL
38static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
39{
00588a0a
WL
40 V9fsVirtioState *v = (V9fsVirtioState *)vdev;
41 V9fsState *s = &v->state;
0192cc5d
WL
42 V9fsPDU *pdu;
43 ssize_t len;
d3d74d6f 44 VirtQueueElement *elem;
0192cc5d 45
00588a0a 46 while ((pdu = pdu_alloc(s))) {
c9fb47e7 47 P9MsgHeader out;
0192cc5d 48
51b19ebe
PB
49 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
50 if (!elem) {
d3d74d6f 51 goto out_free_pdu;
00588a0a
WL
52 }
53
a4d99854 54 if (iov_size(elem->in_sg, elem->in_num) < 7) {
d3d74d6f
GK
55 virtio_error(vdev,
56 "The guest sent a VirtFS request without space for "
57 "the reply");
58 goto out_free_req;
59 }
0192cc5d 60
a4d99854
GK
61 len = iov_to_buf(elem->out_sg, elem->out_num, 0, &out, 7);
62 if (len != 7) {
d3d74d6f
GK
63 virtio_error(vdev, "The guest sent a malformed VirtFS request: "
64 "header size is %zd, should be 7", len);
65 goto out_free_req;
66 }
0192cc5d 67
3a21fb2a
GK
68 v->elems[pdu->idx] = elem;
69
506f3275 70 pdu_submit(pdu, &out);
0192cc5d 71 }
d3d74d6f
GK
72
73 return;
74
75out_free_req:
76 virtqueue_detach_element(vq, elem, 0);
77 g_free(elem);
78out_free_pdu:
79 pdu_free(pdu);
0192cc5d
WL
80}
81
9d5b731d
JW
82static uint64_t virtio_9p_get_features(VirtIODevice *vdev, uint64_t features,
83 Error **errp)
f4f61d27 84{
0cd09c3a 85 virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG);
f4f61d27
AK
86 return features;
87}
88
f4f61d27
AK
89static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
90{
e9a0152b 91 int len;
f4f61d27 92 struct virtio_9p_config *cfg;
00588a0a
WL
93 V9fsVirtioState *v = VIRTIO_9P(vdev);
94 V9fsState *s = &v->state;
f4f61d27 95
e9a0152b
AK
96 len = strlen(s->tag);
97 cfg = g_malloc0(sizeof(struct virtio_9p_config) + len);
d64ccb91 98 virtio_stw_p(vdev, &cfg->tag_len, len);
e9a0152b
AK
99 /* We don't copy the terminating null to config space */
100 memcpy(cfg->tag, s->tag, len);
00588a0a 101 memcpy(config, cfg, v->config_size);
7267c094 102 g_free(cfg);
f4f61d27
AK
103}
104
0e44a0fd
GK
105static void virtio_9p_reset(VirtIODevice *vdev)
106{
107 V9fsVirtioState *v = (V9fsVirtioState *)vdev;
108
109 v9fs_reset(&v->state);
110}
111
ea83441c
SS
112static ssize_t virtio_pdu_vmarshal(V9fsPDU *pdu, size_t offset,
113 const char *fmt, va_list ap)
fe9fa96d 114{
00588a0a
WL
115 V9fsState *s = pdu->s;
116 V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
51b19ebe 117 VirtQueueElement *elem = v->elems[pdu->idx];
8d37de41 118 ssize_t ret;
00588a0a 119
8d37de41
GK
120 ret = v9fs_iov_vmarshal(elem->in_sg, elem->in_num, offset, 1, fmt, ap);
121 if (ret < 0) {
122 VirtIODevice *vdev = VIRTIO_DEVICE(v);
123
124 virtio_error(vdev, "Failed to encode VirtFS reply type %d",
125 pdu->id + 1);
126 }
127 return ret;
fe9fa96d
WL
128}
129
ea83441c
SS
130static ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset,
131 const char *fmt, va_list ap)
fe9fa96d 132{
00588a0a
WL
133 V9fsState *s = pdu->s;
134 V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
51b19ebe 135 VirtQueueElement *elem = v->elems[pdu->idx];
8d37de41
GK
136 ssize_t ret;
137
138 ret = v9fs_iov_vunmarshal(elem->out_sg, elem->out_num, offset, 1, fmt, ap);
139 if (ret < 0) {
140 VirtIODevice *vdev = VIRTIO_DEVICE(v);
00588a0a 141
8d37de41
GK
142 virtio_error(vdev, "Failed to decode VirtFS request type %d", pdu->id);
143 }
144 return ret;
fe9fa96d
WL
145}
146
88da0b03
SS
147static void virtio_init_in_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
148 unsigned int *pniov, size_t size)
592707af 149{
00588a0a
WL
150 V9fsState *s = pdu->s;
151 V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
51b19ebe 152 VirtQueueElement *elem = v->elems[pdu->idx];
8d37de41
GK
153 size_t buf_size = iov_size(elem->in_sg, elem->in_num);
154
155 if (buf_size < size) {
156 VirtIODevice *vdev = VIRTIO_DEVICE(v);
157
158 virtio_error(vdev,
159 "VirtFS reply type %d needs %zu bytes, buffer has %zu",
160 pdu->id + 1, size, buf_size);
161 }
00588a0a 162
88da0b03
SS
163 *piov = elem->in_sg;
164 *pniov = elem->in_num;
165}
166
167static void virtio_init_out_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
8d37de41 168 unsigned int *pniov, size_t size)
88da0b03
SS
169{
170 V9fsState *s = pdu->s;
171 V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
172 VirtQueueElement *elem = v->elems[pdu->idx];
8d37de41
GK
173 size_t buf_size = iov_size(elem->out_sg, elem->out_num);
174
175 if (buf_size < size) {
176 VirtIODevice *vdev = VIRTIO_DEVICE(v);
177
178 virtio_error(vdev,
179 "VirtFS request type %d needs %zu bytes, buffer has %zu",
180 pdu->id, size, buf_size);
181 }
88da0b03
SS
182
183 *piov = elem->out_sg;
184 *pniov = elem->out_num;
592707af
WL
185}
186
ea83441c
SS
187static const struct V9fsTransport virtio_9p_transport = {
188 .pdu_vmarshal = virtio_pdu_vmarshal,
189 .pdu_vunmarshal = virtio_pdu_vunmarshal,
88da0b03
SS
190 .init_in_iov_from_pdu = virtio_init_in_iov_from_pdu,
191 .init_out_iov_from_pdu = virtio_init_out_iov_from_pdu,
ea83441c
SS
192 .push_and_notify = virtio_9p_push_and_notify,
193};
194
bd3be4db
GK
195static void virtio_9p_device_realize(DeviceState *dev, Error **errp)
196{
197 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
198 V9fsVirtioState *v = VIRTIO_9P(dev);
199 V9fsState *s = &v->state;
200
201 if (v9fs_device_realize_common(s, errp)) {
202 goto out;
203 }
204
205 v->config_size = sizeof(struct virtio_9p_config) + strlen(s->fsconf.tag);
206 virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, v->config_size);
207 v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output);
208 v9fs_register_transport(s, &virtio_9p_transport);
209
210out:
211 return;
212}
213
214static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp)
215{
216 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
217 V9fsVirtioState *v = VIRTIO_9P(dev);
218 V9fsState *s = &v->state;
219
220 virtio_cleanup(vdev);
221 v9fs_device_unrealize_common(s, errp);
222}
223
e7303c43
FK
224/* virtio-9p device */
225
dcaf8dda
HP
226static const VMStateDescription vmstate_virtio_9p = {
227 .name = "virtio-9p",
228 .minimum_version_id = 1,
229 .version_id = 1,
230 .fields = (VMStateField[]) {
231 VMSTATE_VIRTIO_DEVICE,
232 VMSTATE_END_OF_LIST()
233 },
234};
18e0e5b2 235
e7303c43 236static Property virtio_9p_properties[] = {
00588a0a
WL
237 DEFINE_PROP_STRING("mount_tag", V9fsVirtioState, state.fsconf.tag),
238 DEFINE_PROP_STRING("fsdev", V9fsVirtioState, state.fsconf.fsdev_id),
e7303c43
FK
239 DEFINE_PROP_END_OF_LIST(),
240};
241
242static void virtio_9p_class_init(ObjectClass *klass, void *data)
243{
244 DeviceClass *dc = DEVICE_CLASS(klass);
245 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
59be7522 246
e7303c43 247 dc->props = virtio_9p_properties;
18e0e5b2 248 dc->vmsd = &vmstate_virtio_9p;
125ee0ed 249 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
59be7522 250 vdc->realize = virtio_9p_device_realize;
6cecf093 251 vdc->unrealize = virtio_9p_device_unrealize;
e7303c43
FK
252 vdc->get_features = virtio_9p_get_features;
253 vdc->get_config = virtio_9p_get_config;
0e44a0fd 254 vdc->reset = virtio_9p_reset;
e7303c43
FK
255}
256
257static const TypeInfo virtio_device_info = {
258 .name = TYPE_VIRTIO_9P,
259 .parent = TYPE_VIRTIO_DEVICE,
00588a0a 260 .instance_size = sizeof(V9fsVirtioState),
e7303c43
FK
261 .class_init = virtio_9p_class_init,
262};
263
264static void virtio_9p_register_types(void)
265{
266 type_register_static(&virtio_device_info);
267}
268
269type_init(virtio_9p_register_types)