xref: /qemu/hw/virtio/vhost-user-fs.c (revision 98fc1ada4cf70af0f1df1a2d7183cf786fc7da05)
1*98fc1adaSDr. David Alan Gilbert /*
2*98fc1adaSDr. David Alan Gilbert  * Vhost-user filesystem virtio device
3*98fc1adaSDr. David Alan Gilbert  *
4*98fc1adaSDr. David Alan Gilbert  * Copyright 2018-2019 Red Hat, Inc.
5*98fc1adaSDr. David Alan Gilbert  *
6*98fc1adaSDr. David Alan Gilbert  * Authors:
7*98fc1adaSDr. David Alan Gilbert  *  Stefan Hajnoczi <stefanha@redhat.com>
8*98fc1adaSDr. David Alan Gilbert  *
9*98fc1adaSDr. David Alan Gilbert  * This work is licensed under the terms of the GNU GPL, version 2 or
10*98fc1adaSDr. David Alan Gilbert  * (at your option) any later version.  See the COPYING file in the
11*98fc1adaSDr. David Alan Gilbert  * top-level directory.
12*98fc1adaSDr. David Alan Gilbert  */
13*98fc1adaSDr. David Alan Gilbert 
14*98fc1adaSDr. David Alan Gilbert #include "qemu/osdep.h"
15*98fc1adaSDr. David Alan Gilbert #include <sys/ioctl.h>
16*98fc1adaSDr. David Alan Gilbert #include "standard-headers/linux/virtio_fs.h"
17*98fc1adaSDr. David Alan Gilbert #include "qapi/error.h"
18*98fc1adaSDr. David Alan Gilbert #include "hw/qdev-properties.h"
19*98fc1adaSDr. David Alan Gilbert #include "hw/virtio/virtio-bus.h"
20*98fc1adaSDr. David Alan Gilbert #include "hw/virtio/virtio-access.h"
21*98fc1adaSDr. David Alan Gilbert #include "qemu/error-report.h"
22*98fc1adaSDr. David Alan Gilbert #include "hw/virtio/vhost-user-fs.h"
23*98fc1adaSDr. David Alan Gilbert #include "monitor/monitor.h"
24*98fc1adaSDr. David Alan Gilbert 
25*98fc1adaSDr. David Alan Gilbert static void vuf_get_config(VirtIODevice *vdev, uint8_t *config)
26*98fc1adaSDr. David Alan Gilbert {
27*98fc1adaSDr. David Alan Gilbert     VHostUserFS *fs = VHOST_USER_FS(vdev);
28*98fc1adaSDr. David Alan Gilbert     struct virtio_fs_config fscfg = {};
29*98fc1adaSDr. David Alan Gilbert 
30*98fc1adaSDr. David Alan Gilbert     memcpy((char *)fscfg.tag, fs->conf.tag,
31*98fc1adaSDr. David Alan Gilbert            MIN(strlen(fs->conf.tag) + 1, sizeof(fscfg.tag)));
32*98fc1adaSDr. David Alan Gilbert 
33*98fc1adaSDr. David Alan Gilbert     virtio_stl_p(vdev, &fscfg.num_request_queues, fs->conf.num_request_queues);
34*98fc1adaSDr. David Alan Gilbert 
35*98fc1adaSDr. David Alan Gilbert     memcpy(config, &fscfg, sizeof(fscfg));
36*98fc1adaSDr. David Alan Gilbert }
37*98fc1adaSDr. David Alan Gilbert 
38*98fc1adaSDr. David Alan Gilbert static void vuf_start(VirtIODevice *vdev)
39*98fc1adaSDr. David Alan Gilbert {
40*98fc1adaSDr. David Alan Gilbert     VHostUserFS *fs = VHOST_USER_FS(vdev);
41*98fc1adaSDr. David Alan Gilbert     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
42*98fc1adaSDr. David Alan Gilbert     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
43*98fc1adaSDr. David Alan Gilbert     int ret;
44*98fc1adaSDr. David Alan Gilbert     int i;
45*98fc1adaSDr. David Alan Gilbert 
46*98fc1adaSDr. David Alan Gilbert     if (!k->set_guest_notifiers) {
47*98fc1adaSDr. David Alan Gilbert         error_report("binding does not support guest notifiers");
48*98fc1adaSDr. David Alan Gilbert         return;
49*98fc1adaSDr. David Alan Gilbert     }
50*98fc1adaSDr. David Alan Gilbert 
51*98fc1adaSDr. David Alan Gilbert     ret = vhost_dev_enable_notifiers(&fs->vhost_dev, vdev);
52*98fc1adaSDr. David Alan Gilbert     if (ret < 0) {
53*98fc1adaSDr. David Alan Gilbert         error_report("Error enabling host notifiers: %d", -ret);
54*98fc1adaSDr. David Alan Gilbert         return;
55*98fc1adaSDr. David Alan Gilbert     }
56*98fc1adaSDr. David Alan Gilbert 
57*98fc1adaSDr. David Alan Gilbert     ret = k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, true);
58*98fc1adaSDr. David Alan Gilbert     if (ret < 0) {
59*98fc1adaSDr. David Alan Gilbert         error_report("Error binding guest notifier: %d", -ret);
60*98fc1adaSDr. David Alan Gilbert         goto err_host_notifiers;
61*98fc1adaSDr. David Alan Gilbert     }
62*98fc1adaSDr. David Alan Gilbert 
63*98fc1adaSDr. David Alan Gilbert     fs->vhost_dev.acked_features = vdev->guest_features;
64*98fc1adaSDr. David Alan Gilbert     ret = vhost_dev_start(&fs->vhost_dev, vdev);
65*98fc1adaSDr. David Alan Gilbert     if (ret < 0) {
66*98fc1adaSDr. David Alan Gilbert         error_report("Error starting vhost: %d", -ret);
67*98fc1adaSDr. David Alan Gilbert         goto err_guest_notifiers;
68*98fc1adaSDr. David Alan Gilbert     }
69*98fc1adaSDr. David Alan Gilbert 
70*98fc1adaSDr. David Alan Gilbert     /*
71*98fc1adaSDr. David Alan Gilbert      * guest_notifier_mask/pending not used yet, so just unmask
72*98fc1adaSDr. David Alan Gilbert      * everything here.  virtio-pci will do the right thing by
73*98fc1adaSDr. David Alan Gilbert      * enabling/disabling irqfd.
74*98fc1adaSDr. David Alan Gilbert      */
75*98fc1adaSDr. David Alan Gilbert     for (i = 0; i < fs->vhost_dev.nvqs; i++) {
76*98fc1adaSDr. David Alan Gilbert         vhost_virtqueue_mask(&fs->vhost_dev, vdev, i, false);
77*98fc1adaSDr. David Alan Gilbert     }
78*98fc1adaSDr. David Alan Gilbert 
79*98fc1adaSDr. David Alan Gilbert     return;
80*98fc1adaSDr. David Alan Gilbert 
81*98fc1adaSDr. David Alan Gilbert err_guest_notifiers:
82*98fc1adaSDr. David Alan Gilbert     k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, false);
83*98fc1adaSDr. David Alan Gilbert err_host_notifiers:
84*98fc1adaSDr. David Alan Gilbert     vhost_dev_disable_notifiers(&fs->vhost_dev, vdev);
85*98fc1adaSDr. David Alan Gilbert }
86*98fc1adaSDr. David Alan Gilbert 
87*98fc1adaSDr. David Alan Gilbert static void vuf_stop(VirtIODevice *vdev)
88*98fc1adaSDr. David Alan Gilbert {
89*98fc1adaSDr. David Alan Gilbert     VHostUserFS *fs = VHOST_USER_FS(vdev);
90*98fc1adaSDr. David Alan Gilbert     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
91*98fc1adaSDr. David Alan Gilbert     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
92*98fc1adaSDr. David Alan Gilbert     int ret;
93*98fc1adaSDr. David Alan Gilbert 
94*98fc1adaSDr. David Alan Gilbert     if (!k->set_guest_notifiers) {
95*98fc1adaSDr. David Alan Gilbert         return;
96*98fc1adaSDr. David Alan Gilbert     }
97*98fc1adaSDr. David Alan Gilbert 
98*98fc1adaSDr. David Alan Gilbert     vhost_dev_stop(&fs->vhost_dev, vdev);
99*98fc1adaSDr. David Alan Gilbert 
100*98fc1adaSDr. David Alan Gilbert     ret = k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, false);
101*98fc1adaSDr. David Alan Gilbert     if (ret < 0) {
102*98fc1adaSDr. David Alan Gilbert         error_report("vhost guest notifier cleanup failed: %d", ret);
103*98fc1adaSDr. David Alan Gilbert         return;
104*98fc1adaSDr. David Alan Gilbert     }
105*98fc1adaSDr. David Alan Gilbert 
106*98fc1adaSDr. David Alan Gilbert     vhost_dev_disable_notifiers(&fs->vhost_dev, vdev);
107*98fc1adaSDr. David Alan Gilbert }
108*98fc1adaSDr. David Alan Gilbert 
109*98fc1adaSDr. David Alan Gilbert static void vuf_set_status(VirtIODevice *vdev, uint8_t status)
110*98fc1adaSDr. David Alan Gilbert {
111*98fc1adaSDr. David Alan Gilbert     VHostUserFS *fs = VHOST_USER_FS(vdev);
112*98fc1adaSDr. David Alan Gilbert     bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK;
113*98fc1adaSDr. David Alan Gilbert 
114*98fc1adaSDr. David Alan Gilbert     if (!vdev->vm_running) {
115*98fc1adaSDr. David Alan Gilbert         should_start = false;
116*98fc1adaSDr. David Alan Gilbert     }
117*98fc1adaSDr. David Alan Gilbert 
118*98fc1adaSDr. David Alan Gilbert     if (fs->vhost_dev.started == should_start) {
119*98fc1adaSDr. David Alan Gilbert         return;
120*98fc1adaSDr. David Alan Gilbert     }
121*98fc1adaSDr. David Alan Gilbert 
122*98fc1adaSDr. David Alan Gilbert     if (should_start) {
123*98fc1adaSDr. David Alan Gilbert         vuf_start(vdev);
124*98fc1adaSDr. David Alan Gilbert     } else {
125*98fc1adaSDr. David Alan Gilbert         vuf_stop(vdev);
126*98fc1adaSDr. David Alan Gilbert     }
127*98fc1adaSDr. David Alan Gilbert }
128*98fc1adaSDr. David Alan Gilbert 
129*98fc1adaSDr. David Alan Gilbert static uint64_t vuf_get_features(VirtIODevice *vdev,
130*98fc1adaSDr. David Alan Gilbert                                       uint64_t requested_features,
131*98fc1adaSDr. David Alan Gilbert                                       Error **errp)
132*98fc1adaSDr. David Alan Gilbert {
133*98fc1adaSDr. David Alan Gilbert     /* No feature bits used yet */
134*98fc1adaSDr. David Alan Gilbert     return requested_features;
135*98fc1adaSDr. David Alan Gilbert }
136*98fc1adaSDr. David Alan Gilbert 
137*98fc1adaSDr. David Alan Gilbert static void vuf_handle_output(VirtIODevice *vdev, VirtQueue *vq)
138*98fc1adaSDr. David Alan Gilbert {
139*98fc1adaSDr. David Alan Gilbert     /*
140*98fc1adaSDr. David Alan Gilbert      * Not normally called; it's the daemon that handles the queue;
141*98fc1adaSDr. David Alan Gilbert      * however virtio's cleanup path can call this.
142*98fc1adaSDr. David Alan Gilbert      */
143*98fc1adaSDr. David Alan Gilbert }
144*98fc1adaSDr. David Alan Gilbert 
145*98fc1adaSDr. David Alan Gilbert static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx,
146*98fc1adaSDr. David Alan Gilbert                                             bool mask)
147*98fc1adaSDr. David Alan Gilbert {
148*98fc1adaSDr. David Alan Gilbert     VHostUserFS *fs = VHOST_USER_FS(vdev);
149*98fc1adaSDr. David Alan Gilbert 
150*98fc1adaSDr. David Alan Gilbert     vhost_virtqueue_mask(&fs->vhost_dev, vdev, idx, mask);
151*98fc1adaSDr. David Alan Gilbert }
152*98fc1adaSDr. David Alan Gilbert 
153*98fc1adaSDr. David Alan Gilbert static bool vuf_guest_notifier_pending(VirtIODevice *vdev, int idx)
154*98fc1adaSDr. David Alan Gilbert {
155*98fc1adaSDr. David Alan Gilbert     VHostUserFS *fs = VHOST_USER_FS(vdev);
156*98fc1adaSDr. David Alan Gilbert 
157*98fc1adaSDr. David Alan Gilbert     return vhost_virtqueue_pending(&fs->vhost_dev, idx);
158*98fc1adaSDr. David Alan Gilbert }
159*98fc1adaSDr. David Alan Gilbert 
160*98fc1adaSDr. David Alan Gilbert static void vuf_device_realize(DeviceState *dev, Error **errp)
161*98fc1adaSDr. David Alan Gilbert {
162*98fc1adaSDr. David Alan Gilbert     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
163*98fc1adaSDr. David Alan Gilbert     VHostUserFS *fs = VHOST_USER_FS(dev);
164*98fc1adaSDr. David Alan Gilbert     unsigned int i;
165*98fc1adaSDr. David Alan Gilbert     size_t len;
166*98fc1adaSDr. David Alan Gilbert     int ret;
167*98fc1adaSDr. David Alan Gilbert 
168*98fc1adaSDr. David Alan Gilbert     if (!fs->conf.chardev.chr) {
169*98fc1adaSDr. David Alan Gilbert         error_setg(errp, "missing chardev");
170*98fc1adaSDr. David Alan Gilbert         return;
171*98fc1adaSDr. David Alan Gilbert     }
172*98fc1adaSDr. David Alan Gilbert 
173*98fc1adaSDr. David Alan Gilbert     if (!fs->conf.tag) {
174*98fc1adaSDr. David Alan Gilbert         error_setg(errp, "missing tag property");
175*98fc1adaSDr. David Alan Gilbert         return;
176*98fc1adaSDr. David Alan Gilbert     }
177*98fc1adaSDr. David Alan Gilbert     len = strlen(fs->conf.tag);
178*98fc1adaSDr. David Alan Gilbert     if (len == 0) {
179*98fc1adaSDr. David Alan Gilbert         error_setg(errp, "tag property cannot be empty");
180*98fc1adaSDr. David Alan Gilbert         return;
181*98fc1adaSDr. David Alan Gilbert     }
182*98fc1adaSDr. David Alan Gilbert     if (len > sizeof_field(struct virtio_fs_config, tag)) {
183*98fc1adaSDr. David Alan Gilbert         error_setg(errp, "tag property must be %zu bytes or less",
184*98fc1adaSDr. David Alan Gilbert                    sizeof_field(struct virtio_fs_config, tag));
185*98fc1adaSDr. David Alan Gilbert         return;
186*98fc1adaSDr. David Alan Gilbert     }
187*98fc1adaSDr. David Alan Gilbert 
188*98fc1adaSDr. David Alan Gilbert     if (fs->conf.num_request_queues == 0) {
189*98fc1adaSDr. David Alan Gilbert         error_setg(errp, "num-request-queues property must be larger than 0");
190*98fc1adaSDr. David Alan Gilbert         return;
191*98fc1adaSDr. David Alan Gilbert     }
192*98fc1adaSDr. David Alan Gilbert 
193*98fc1adaSDr. David Alan Gilbert     if (!is_power_of_2(fs->conf.queue_size)) {
194*98fc1adaSDr. David Alan Gilbert         error_setg(errp, "queue-size property must be a power of 2");
195*98fc1adaSDr. David Alan Gilbert         return;
196*98fc1adaSDr. David Alan Gilbert     }
197*98fc1adaSDr. David Alan Gilbert 
198*98fc1adaSDr. David Alan Gilbert     if (fs->conf.queue_size > VIRTQUEUE_MAX_SIZE) {
199*98fc1adaSDr. David Alan Gilbert         error_setg(errp, "queue-size property must be %u or smaller",
200*98fc1adaSDr. David Alan Gilbert                    VIRTQUEUE_MAX_SIZE);
201*98fc1adaSDr. David Alan Gilbert         return;
202*98fc1adaSDr. David Alan Gilbert     }
203*98fc1adaSDr. David Alan Gilbert 
204*98fc1adaSDr. David Alan Gilbert     if (!vhost_user_init(&fs->vhost_user, &fs->conf.chardev, errp)) {
205*98fc1adaSDr. David Alan Gilbert         return;
206*98fc1adaSDr. David Alan Gilbert     }
207*98fc1adaSDr. David Alan Gilbert 
208*98fc1adaSDr. David Alan Gilbert     virtio_init(vdev, "vhost-user-fs", VIRTIO_ID_FS,
209*98fc1adaSDr. David Alan Gilbert                 sizeof(struct virtio_fs_config));
210*98fc1adaSDr. David Alan Gilbert 
211*98fc1adaSDr. David Alan Gilbert     /* Hiprio queue */
212*98fc1adaSDr. David Alan Gilbert     virtio_add_queue(vdev, fs->conf.queue_size, vuf_handle_output);
213*98fc1adaSDr. David Alan Gilbert 
214*98fc1adaSDr. David Alan Gilbert     /* Request queues */
215*98fc1adaSDr. David Alan Gilbert     for (i = 0; i < fs->conf.num_request_queues; i++) {
216*98fc1adaSDr. David Alan Gilbert         virtio_add_queue(vdev, fs->conf.queue_size, vuf_handle_output);
217*98fc1adaSDr. David Alan Gilbert     }
218*98fc1adaSDr. David Alan Gilbert 
219*98fc1adaSDr. David Alan Gilbert     /* 1 high prio queue, plus the number configured */
220*98fc1adaSDr. David Alan Gilbert     fs->vhost_dev.nvqs = 1 + fs->conf.num_request_queues;
221*98fc1adaSDr. David Alan Gilbert     fs->vhost_dev.vqs = g_new0(struct vhost_virtqueue, fs->vhost_dev.nvqs);
222*98fc1adaSDr. David Alan Gilbert     ret = vhost_dev_init(&fs->vhost_dev, &fs->vhost_user,
223*98fc1adaSDr. David Alan Gilbert                          VHOST_BACKEND_TYPE_USER, 0);
224*98fc1adaSDr. David Alan Gilbert     if (ret < 0) {
225*98fc1adaSDr. David Alan Gilbert         error_setg_errno(errp, -ret, "vhost_dev_init failed");
226*98fc1adaSDr. David Alan Gilbert         goto err_virtio;
227*98fc1adaSDr. David Alan Gilbert     }
228*98fc1adaSDr. David Alan Gilbert 
229*98fc1adaSDr. David Alan Gilbert     return;
230*98fc1adaSDr. David Alan Gilbert 
231*98fc1adaSDr. David Alan Gilbert err_virtio:
232*98fc1adaSDr. David Alan Gilbert     vhost_user_cleanup(&fs->vhost_user);
233*98fc1adaSDr. David Alan Gilbert     virtio_cleanup(vdev);
234*98fc1adaSDr. David Alan Gilbert     g_free(fs->vhost_dev.vqs);
235*98fc1adaSDr. David Alan Gilbert     return;
236*98fc1adaSDr. David Alan Gilbert }
237*98fc1adaSDr. David Alan Gilbert 
238*98fc1adaSDr. David Alan Gilbert static void vuf_device_unrealize(DeviceState *dev, Error **errp)
239*98fc1adaSDr. David Alan Gilbert {
240*98fc1adaSDr. David Alan Gilbert     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
241*98fc1adaSDr. David Alan Gilbert     VHostUserFS *fs = VHOST_USER_FS(dev);
242*98fc1adaSDr. David Alan Gilbert 
243*98fc1adaSDr. David Alan Gilbert     /* This will stop vhost backend if appropriate. */
244*98fc1adaSDr. David Alan Gilbert     vuf_set_status(vdev, 0);
245*98fc1adaSDr. David Alan Gilbert 
246*98fc1adaSDr. David Alan Gilbert     vhost_dev_cleanup(&fs->vhost_dev);
247*98fc1adaSDr. David Alan Gilbert 
248*98fc1adaSDr. David Alan Gilbert     vhost_user_cleanup(&fs->vhost_user);
249*98fc1adaSDr. David Alan Gilbert 
250*98fc1adaSDr. David Alan Gilbert     virtio_cleanup(vdev);
251*98fc1adaSDr. David Alan Gilbert     g_free(fs->vhost_dev.vqs);
252*98fc1adaSDr. David Alan Gilbert     fs->vhost_dev.vqs = NULL;
253*98fc1adaSDr. David Alan Gilbert }
254*98fc1adaSDr. David Alan Gilbert 
255*98fc1adaSDr. David Alan Gilbert static const VMStateDescription vuf_vmstate = {
256*98fc1adaSDr. David Alan Gilbert     .name = "vhost-user-fs",
257*98fc1adaSDr. David Alan Gilbert     .unmigratable = 1,
258*98fc1adaSDr. David Alan Gilbert };
259*98fc1adaSDr. David Alan Gilbert 
260*98fc1adaSDr. David Alan Gilbert static Property vuf_properties[] = {
261*98fc1adaSDr. David Alan Gilbert     DEFINE_PROP_CHR("chardev", VHostUserFS, conf.chardev),
262*98fc1adaSDr. David Alan Gilbert     DEFINE_PROP_STRING("tag", VHostUserFS, conf.tag),
263*98fc1adaSDr. David Alan Gilbert     DEFINE_PROP_UINT16("num-request-queues", VHostUserFS,
264*98fc1adaSDr. David Alan Gilbert                        conf.num_request_queues, 1),
265*98fc1adaSDr. David Alan Gilbert     DEFINE_PROP_UINT16("queue-size", VHostUserFS, conf.queue_size, 128),
266*98fc1adaSDr. David Alan Gilbert     DEFINE_PROP_STRING("vhostfd", VHostUserFS, conf.vhostfd),
267*98fc1adaSDr. David Alan Gilbert     DEFINE_PROP_END_OF_LIST(),
268*98fc1adaSDr. David Alan Gilbert };
269*98fc1adaSDr. David Alan Gilbert 
270*98fc1adaSDr. David Alan Gilbert static void vuf_class_init(ObjectClass *klass, void *data)
271*98fc1adaSDr. David Alan Gilbert {
272*98fc1adaSDr. David Alan Gilbert     DeviceClass *dc = DEVICE_CLASS(klass);
273*98fc1adaSDr. David Alan Gilbert     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
274*98fc1adaSDr. David Alan Gilbert 
275*98fc1adaSDr. David Alan Gilbert     dc->props = vuf_properties;
276*98fc1adaSDr. David Alan Gilbert     dc->vmsd = &vuf_vmstate;
277*98fc1adaSDr. David Alan Gilbert     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
278*98fc1adaSDr. David Alan Gilbert     vdc->realize = vuf_device_realize;
279*98fc1adaSDr. David Alan Gilbert     vdc->unrealize = vuf_device_unrealize;
280*98fc1adaSDr. David Alan Gilbert     vdc->get_features = vuf_get_features;
281*98fc1adaSDr. David Alan Gilbert     vdc->get_config = vuf_get_config;
282*98fc1adaSDr. David Alan Gilbert     vdc->set_status = vuf_set_status;
283*98fc1adaSDr. David Alan Gilbert     vdc->guest_notifier_mask = vuf_guest_notifier_mask;
284*98fc1adaSDr. David Alan Gilbert     vdc->guest_notifier_pending = vuf_guest_notifier_pending;
285*98fc1adaSDr. David Alan Gilbert }
286*98fc1adaSDr. David Alan Gilbert 
287*98fc1adaSDr. David Alan Gilbert static const TypeInfo vuf_info = {
288*98fc1adaSDr. David Alan Gilbert     .name = TYPE_VHOST_USER_FS,
289*98fc1adaSDr. David Alan Gilbert     .parent = TYPE_VIRTIO_DEVICE,
290*98fc1adaSDr. David Alan Gilbert     .instance_size = sizeof(VHostUserFS),
291*98fc1adaSDr. David Alan Gilbert     .class_init = vuf_class_init,
292*98fc1adaSDr. David Alan Gilbert };
293*98fc1adaSDr. David Alan Gilbert 
294*98fc1adaSDr. David Alan Gilbert static void vuf_register_types(void)
295*98fc1adaSDr. David Alan Gilbert {
296*98fc1adaSDr. David Alan Gilbert     type_register_static(&vuf_info);
297*98fc1adaSDr. David Alan Gilbert }
298*98fc1adaSDr. David Alan Gilbert 
299*98fc1adaSDr. David Alan Gilbert type_init(vuf_register_types)
300