]>
Commit | Line | Data |
---|---|---|
f4f61d27 AK |
1 | /* |
2 | * Virtio 9p backend | |
3 | * | |
4 | * Copyright IBM, Corp. 2010 | |
5 | * | |
6 | * Authors: | |
7 | * Anthony Liguori <[email protected]> | |
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 | ||
0d09e41a | 14 | #include "hw/virtio/virtio.h" |
93b48c20 | 15 | #include "hw/virtio/virtio-9p.h" |
0d09e41a | 16 | #include "hw/i386/pc.h" |
1de7afc9 | 17 | #include "qemu/sockets.h" |
f4f61d27 AK |
18 | #include "virtio-9p.h" |
19 | #include "fsdev/qemu-fsdev.h" | |
20 | #include "virtio-9p-xattr.h" | |
39c0564e | 21 | #include "virtio-9p-coth.h" |
d64ccb91 | 22 | #include "hw/virtio/virtio-access.h" |
f4f61d27 AK |
23 | |
24 | static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features) | |
25 | { | |
26 | features |= 1 << VIRTIO_9P_MOUNT_TAG; | |
27 | return features; | |
28 | } | |
29 | ||
f4f61d27 AK |
30 | static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config) |
31 | { | |
e9a0152b | 32 | int len; |
f4f61d27 | 33 | struct virtio_9p_config *cfg; |
13daf6ca | 34 | V9fsState *s = VIRTIO_9P(vdev); |
f4f61d27 | 35 | |
e9a0152b AK |
36 | len = strlen(s->tag); |
37 | cfg = g_malloc0(sizeof(struct virtio_9p_config) + len); | |
d64ccb91 | 38 | virtio_stw_p(vdev, &cfg->tag_len, len); |
e9a0152b AK |
39 | /* We don't copy the terminating null to config space */ |
40 | memcpy(cfg->tag, s->tag, len); | |
f4f61d27 | 41 | memcpy(config, cfg, s->config_size); |
7267c094 | 42 | g_free(cfg); |
f4f61d27 AK |
43 | } |
44 | ||
59be7522 | 45 | static void virtio_9p_device_realize(DeviceState *dev, Error **errp) |
0174fe73 | 46 | { |
59be7522 AF |
47 | VirtIODevice *vdev = VIRTIO_DEVICE(dev); |
48 | V9fsState *s = VIRTIO_9P(dev); | |
f4f61d27 AK |
49 | int i, len; |
50 | struct stat stat; | |
fbcbf101 | 51 | FsDriverEntry *fse; |
7cca27df | 52 | V9fsPath path; |
f4f61d27 | 53 | |
0f3657ec | 54 | virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, |
e8111e50 | 55 | sizeof(struct virtio_9p_config) + MAX_TAG_LEN); |
e7303c43 | 56 | |
f4f61d27 AK |
57 | /* initialize pdu allocator */ |
58 | QLIST_INIT(&s->free_list); | |
bccacf6c | 59 | QLIST_INIT(&s->active_list); |
f4f61d27 AK |
60 | for (i = 0; i < (MAX_REQ - 1); i++) { |
61 | QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next); | |
62 | } | |
63 | ||
e8111e50 | 64 | s->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output); |
f4f61d27 | 65 | |
27915efb AF |
66 | v9fs_path_init(&path); |
67 | ||
e8111e50 | 68 | fse = get_fsdev_fsentry(s->fsconf.fsdev_id); |
f4f61d27 AK |
69 | |
70 | if (!fse) { | |
71 | /* We don't have a fsdev identified by fsdev_id */ | |
59be7522 AF |
72 | error_setg(errp, "Virtio-9p device couldn't find fsdev with the " |
73 | "id = %s", | |
74 | s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL"); | |
92304bf3 | 75 | goto out; |
f4f61d27 AK |
76 | } |
77 | ||
e8111e50 | 78 | if (!s->fsconf.tag) { |
99519f0a | 79 | /* we haven't specified a mount_tag */ |
59be7522 AF |
80 | error_setg(errp, "fsdev with id %s needs mount_tag arguments", |
81 | s->fsconf.fsdev_id); | |
92304bf3 | 82 | goto out; |
f4f61d27 AK |
83 | } |
84 | ||
b97400ca | 85 | s->ctx.export_flags = fse->export_flags; |
c64f50d1 | 86 | s->ctx.fs_root = g_strdup(fse->path); |
b97400ca | 87 | s->ctx.exops.get_st_gen = NULL; |
e8111e50 | 88 | len = strlen(s->fsconf.tag); |
e9a0152b | 89 | if (len > MAX_TAG_LEN - 1) { |
59be7522 AF |
90 | error_setg(errp, "mount tag '%s' (%d bytes) is longer than " |
91 | "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1); | |
92304bf3 | 92 | goto out; |
f4f61d27 | 93 | } |
e9a0152b | 94 | |
92304bf3 | 95 | s->tag = g_strdup(s->fsconf.tag); |
f4f61d27 AK |
96 | s->ctx.uid = -1; |
97 | ||
98 | s->ops = fse->ops; | |
e9a0152b | 99 | s->config_size = sizeof(struct virtio_9p_config) + len; |
9e5b2247 | 100 | s->fid_list = NULL; |
02cb7f3a | 101 | qemu_co_rwlock_init(&s->rename_lock); |
f4f61d27 | 102 | |
0174fe73 | 103 | if (s->ops->init(&s->ctx) < 0) { |
59be7522 AF |
104 | error_setg(errp, "Virtio-9p Failed to initialize fs-driver with id:%s" |
105 | " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root); | |
92304bf3 | 106 | goto out; |
0174fe73 | 107 | } |
39c0564e | 108 | if (v9fs_init_worker_threads() < 0) { |
59be7522 | 109 | error_setg(errp, "worker thread initialization failed"); |
92304bf3 | 110 | goto out; |
39c0564e | 111 | } |
7cca27df MK |
112 | |
113 | /* | |
114 | * Check details of export path, We need to use fs driver | |
115 | * call back to do that. Since we are in the init path, we don't | |
116 | * use co-routines here. | |
117 | */ | |
7cca27df | 118 | if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { |
59be7522 AF |
119 | error_setg(errp, |
120 | "error in converting name to path %s", strerror(errno)); | |
92304bf3 | 121 | goto out; |
7cca27df MK |
122 | } |
123 | if (s->ops->lstat(&s->ctx, &path, &stat)) { | |
59be7522 | 124 | error_setg(errp, "share path %s does not exist", fse->path); |
92304bf3 | 125 | goto out; |
7cca27df | 126 | } else if (!S_ISDIR(stat.st_mode)) { |
59be7522 | 127 | error_setg(errp, "share path %s is not a directory", fse->path); |
92304bf3 | 128 | goto out; |
7cca27df MK |
129 | } |
130 | v9fs_path_free(&path); | |
131 | ||
59be7522 | 132 | return; |
92304bf3 MK |
133 | out: |
134 | g_free(s->ctx.fs_root); | |
135 | g_free(s->tag); | |
136 | virtio_cleanup(vdev); | |
137 | v9fs_path_free(&path); | |
e7303c43 FK |
138 | } |
139 | ||
140 | /* virtio-9p device */ | |
141 | ||
e7303c43 FK |
142 | static Property virtio_9p_properties[] = { |
143 | DEFINE_VIRTIO_9P_PROPERTIES(V9fsState, fsconf), | |
144 | DEFINE_PROP_END_OF_LIST(), | |
145 | }; | |
146 | ||
147 | static void virtio_9p_class_init(ObjectClass *klass, void *data) | |
148 | { | |
149 | DeviceClass *dc = DEVICE_CLASS(klass); | |
150 | VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); | |
59be7522 | 151 | |
e7303c43 | 152 | dc->props = virtio_9p_properties; |
125ee0ed | 153 | set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); |
59be7522 | 154 | vdc->realize = virtio_9p_device_realize; |
e7303c43 FK |
155 | vdc->get_features = virtio_9p_get_features; |
156 | vdc->get_config = virtio_9p_get_config; | |
157 | } | |
158 | ||
159 | static const TypeInfo virtio_device_info = { | |
160 | .name = TYPE_VIRTIO_9P, | |
161 | .parent = TYPE_VIRTIO_DEVICE, | |
162 | .instance_size = sizeof(V9fsState), | |
163 | .class_init = virtio_9p_class_init, | |
164 | }; | |
165 | ||
166 | static void virtio_9p_register_types(void) | |
167 | { | |
168 | type_register_static(&virtio_device_info); | |
169 | } | |
170 | ||
171 | type_init(virtio_9p_register_types) |