]>
Commit | Line | Data |
---|---|---|
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 | ||
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" |
f4f61d27 AK |
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 | ||
f4f61d27 AK |
29 | static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config) |
30 | { | |
e9a0152b | 31 | int len; |
f4f61d27 | 32 | struct virtio_9p_config *cfg; |
13daf6ca | 33 | V9fsState *s = VIRTIO_9P(vdev); |
f4f61d27 | 34 | |
e9a0152b AK |
35 | len = strlen(s->tag); |
36 | cfg = g_malloc0(sizeof(struct virtio_9p_config) + len); | |
37 | stw_raw(&cfg->tag_len, len); | |
38 | /* We don't copy the terminating null to config space */ | |
39 | memcpy(cfg->tag, s->tag, len); | |
f4f61d27 | 40 | memcpy(config, cfg, s->config_size); |
7267c094 | 41 | g_free(cfg); |
f4f61d27 AK |
42 | } |
43 | ||
e8111e50 | 44 | static int virtio_9p_device_init(VirtIODevice *vdev) |
0174fe73 | 45 | { |
e8111e50 | 46 | V9fsState *s = VIRTIO_9P(vdev); |
f4f61d27 AK |
47 | int i, len; |
48 | struct stat stat; | |
fbcbf101 | 49 | FsDriverEntry *fse; |
7cca27df | 50 | V9fsPath path; |
f4f61d27 | 51 | |
e8111e50 FK |
52 | virtio_init(VIRTIO_DEVICE(s), "virtio-9p", VIRTIO_ID_9P, |
53 | sizeof(struct virtio_9p_config) + MAX_TAG_LEN); | |
e7303c43 | 54 | |
f4f61d27 AK |
55 | /* initialize pdu allocator */ |
56 | QLIST_INIT(&s->free_list); | |
bccacf6c | 57 | QLIST_INIT(&s->active_list); |
f4f61d27 AK |
58 | for (i = 0; i < (MAX_REQ - 1); i++) { |
59 | QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next); | |
60 | } | |
61 | ||
e8111e50 | 62 | s->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output); |
f4f61d27 | 63 | |
27915efb AF |
64 | v9fs_path_init(&path); |
65 | ||
e8111e50 | 66 | fse = get_fsdev_fsentry(s->fsconf.fsdev_id); |
f4f61d27 AK |
67 | |
68 | if (!fse) { | |
69 | /* We don't have a fsdev identified by fsdev_id */ | |
70 | fprintf(stderr, "Virtio-9p device couldn't find fsdev with the " | |
e8111e50 FK |
71 | "id = %s\n", |
72 | s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL"); | |
92304bf3 | 73 | goto out; |
f4f61d27 AK |
74 | } |
75 | ||
e8111e50 | 76 | if (!s->fsconf.tag) { |
99519f0a AK |
77 | /* we haven't specified a mount_tag */ |
78 | fprintf(stderr, "fsdev with id %s needs mount_tag arguments\n", | |
e8111e50 | 79 | s->fsconf.fsdev_id); |
92304bf3 | 80 | goto out; |
f4f61d27 AK |
81 | } |
82 | ||
b97400ca | 83 | s->ctx.export_flags = fse->export_flags; |
c64f50d1 | 84 | s->ctx.fs_root = g_strdup(fse->path); |
b97400ca | 85 | s->ctx.exops.get_st_gen = NULL; |
e8111e50 | 86 | len = strlen(s->fsconf.tag); |
e9a0152b | 87 | if (len > MAX_TAG_LEN - 1) { |
a2f507d9 | 88 | fprintf(stderr, "mount tag '%s' (%d bytes) is longer than " |
e8111e50 | 89 | "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1); |
92304bf3 | 90 | goto out; |
f4f61d27 | 91 | } |
e9a0152b | 92 | |
92304bf3 | 93 | s->tag = g_strdup(s->fsconf.tag); |
f4f61d27 AK |
94 | s->ctx.uid = -1; |
95 | ||
96 | s->ops = fse->ops; | |
e9a0152b | 97 | s->config_size = sizeof(struct virtio_9p_config) + len; |
9e5b2247 | 98 | s->fid_list = NULL; |
02cb7f3a | 99 | qemu_co_rwlock_init(&s->rename_lock); |
f4f61d27 | 100 | |
0174fe73 AK |
101 | if (s->ops->init(&s->ctx) < 0) { |
102 | fprintf(stderr, "Virtio-9p Failed to initialize fs-driver with id:%s" | |
e8111e50 | 103 | " and export path:%s\n", s->fsconf.fsdev_id, s->ctx.fs_root); |
92304bf3 | 104 | goto out; |
0174fe73 | 105 | } |
39c0564e VJ |
106 | if (v9fs_init_worker_threads() < 0) { |
107 | fprintf(stderr, "worker thread initialization failed\n"); | |
92304bf3 | 108 | goto out; |
39c0564e | 109 | } |
7cca27df MK |
110 | |
111 | /* | |
112 | * Check details of export path, We need to use fs driver | |
113 | * call back to do that. Since we are in the init path, we don't | |
114 | * use co-routines here. | |
115 | */ | |
7cca27df MK |
116 | if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { |
117 | fprintf(stderr, | |
118 | "error in converting name to path %s", strerror(errno)); | |
92304bf3 | 119 | goto out; |
7cca27df MK |
120 | } |
121 | if (s->ops->lstat(&s->ctx, &path, &stat)) { | |
122 | fprintf(stderr, "share path %s does not exist\n", fse->path); | |
92304bf3 | 123 | goto out; |
7cca27df MK |
124 | } else if (!S_ISDIR(stat.st_mode)) { |
125 | fprintf(stderr, "share path %s is not a directory\n", fse->path); | |
92304bf3 | 126 | goto out; |
7cca27df MK |
127 | } |
128 | v9fs_path_free(&path); | |
129 | ||
e8111e50 | 130 | return 0; |
92304bf3 MK |
131 | out: |
132 | g_free(s->ctx.fs_root); | |
133 | g_free(s->tag); | |
134 | virtio_cleanup(vdev); | |
135 | v9fs_path_free(&path); | |
136 | ||
137 | return -1; | |
138 | ||
e7303c43 FK |
139 | } |
140 | ||
141 | /* virtio-9p device */ | |
142 | ||
e7303c43 FK |
143 | static Property virtio_9p_properties[] = { |
144 | DEFINE_VIRTIO_9P_PROPERTIES(V9fsState, fsconf), | |
145 | DEFINE_PROP_END_OF_LIST(), | |
146 | }; | |
147 | ||
148 | static void virtio_9p_class_init(ObjectClass *klass, void *data) | |
149 | { | |
150 | DeviceClass *dc = DEVICE_CLASS(klass); | |
151 | VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); | |
152 | dc->props = virtio_9p_properties; | |
125ee0ed | 153 | set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); |
e7303c43 FK |
154 | vdc->init = virtio_9p_device_init; |
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) |