-
Notifications
You must be signed in to change notification settings - Fork 4
/
fs.c
112 lines (85 loc) · 2.88 KB
/
fs.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "vhost/fs.h"
#include "virtio/virtio_fs.h"
#include "bio.h"
#include "logging.h"
#include "server_internal.h"
#include "vdev.h"
/******************************************************************************/
struct vhd_fsdev {
/* Base vdev */
struct vhd_vdev vdev;
/* VM-facing interface type */
struct virtio_fs_dev vfs;
LIST_ENTRY(vhd_fsdev) fsdevs;
};
static LIST_HEAD(, vhd_fsdev) g_fsdev_list = LIST_HEAD_INITIALIZER(g_fsdev_list);
#define VHD_FSDEV_FROM_VDEV(ptr) containerof(ptr, struct vhd_fsdev, vdev)
/******************************************************************************/
static uint64_t vfs_get_features(struct vhd_vdev *vdev)
{
return VIRTIO_FS_DEFAULT_FEATURES;
}
static int vfs_set_features(struct vhd_vdev *vdev, uint64_t features)
{
return 0;
}
static size_t vfs_get_config(struct vhd_vdev *vdev, void *cfgbuf,
size_t bufsize, size_t offset)
{
struct vhd_fsdev *dev = VHD_FSDEV_FROM_VDEV(vdev);
if (offset >= sizeof(dev->vfs.config)) {
return 0;
}
size_t data_size = MIN(bufsize, sizeof(dev->vfs.config) - offset);
memcpy(cfgbuf, (char *)(&dev->vfs.config) + offset, data_size);
return data_size;
}
static int vfs_dispatch_requests(struct vhd_vdev *vdev,
struct vhd_vring *vring)
{
struct vhd_fsdev *dev = VHD_FSDEV_FROM_VDEV(vdev);
return virtio_fs_dispatch_requests(&dev->vfs, &vring->vq);
}
static void vfs_free(struct vhd_vdev *vdev)
{
struct vhd_fsdev *dev = VHD_FSDEV_FROM_VDEV(vdev);
LIST_REMOVE(dev, fsdevs);
vhd_free(dev);
}
static const struct vhd_vdev_type g_virtio_fs_vdev_type = {
.desc = "virtio-fs",
.get_features = vfs_get_features,
.set_features = vfs_set_features,
.get_config = vfs_get_config,
.dispatch_requests = vfs_dispatch_requests,
.free = vfs_free,
};
/******************************************************************************/
struct vhd_vdev *vhd_register_fs(struct vhd_fsdev_info *fsdev,
struct vhd_request_queue *rq,
void *priv)
{
VHD_VERIFY(fsdev);
VHD_VERIFY(rq);
struct vhd_fsdev *dev = vhd_zalloc(sizeof(*dev));
int res = virtio_fs_init_dev(&dev->vfs, fsdev);
if (res != 0) {
goto error_out;
}
res = vhd_vdev_init_server(&dev->vdev, fsdev->socket_path, &g_virtio_fs_vdev_type,
fsdev->num_queues, &rq, 1, priv, NULL, NULL);
if (res != 0) {
goto error_out;
}
LIST_INSERT_HEAD(&g_fsdev_list, dev, fsdevs);
return &dev->vdev;
error_out:
vhd_free(dev);
return NULL;
}
void vhd_unregister_fs(struct vhd_vdev *vdev,
void (*unregister_complete)(void *),
void *arg)
{
vhd_vdev_stop_server(vdev, unregister_complete, arg);
}