]>
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 | ||
873c3213 SW |
14 | #include "hw/virtio.h" |
15 | #include "hw/pc.h" | |
f4f61d27 | 16 | #include "qemu_socket.h" |
873c3213 | 17 | #include "hw/virtio-pci.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 | ||
29 | static V9fsState *to_virtio_9p(VirtIODevice *vdev) | |
30 | { | |
31 | return (V9fsState *)vdev; | |
32 | } | |
33 | ||
34 | static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config) | |
35 | { | |
36 | struct virtio_9p_config *cfg; | |
37 | V9fsState *s = to_virtio_9p(vdev); | |
38 | ||
7267c094 | 39 | cfg = g_malloc0(sizeof(struct virtio_9p_config) + |
f4f61d27 AK |
40 | s->tag_len); |
41 | stw_raw(&cfg->tag_len, s->tag_len); | |
42 | memcpy(cfg->tag, s->tag, s->tag_len); | |
43 | memcpy(config, cfg, s->config_size); | |
7267c094 | 44 | g_free(cfg); |
f4f61d27 AK |
45 | } |
46 | ||
47 | VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf) | |
48 | { | |
49 | V9fsState *s; | |
50 | int i, len; | |
51 | struct stat stat; | |
52 | FsTypeEntry *fse; | |
53 | ||
f4f61d27 AK |
54 | s = (V9fsState *)virtio_common_init("virtio-9p", |
55 | VIRTIO_ID_9P, | |
56 | sizeof(struct virtio_9p_config)+ | |
57 | MAX_TAG_LEN, | |
58 | sizeof(V9fsState)); | |
f4f61d27 AK |
59 | /* initialize pdu allocator */ |
60 | QLIST_INIT(&s->free_list); | |
61 | for (i = 0; i < (MAX_REQ - 1); i++) { | |
62 | QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next); | |
63 | } | |
64 | ||
65 | s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output); | |
66 | ||
67 | fse = get_fsdev_fsentry(conf->fsdev_id); | |
68 | ||
69 | if (!fse) { | |
70 | /* We don't have a fsdev identified by fsdev_id */ | |
71 | fprintf(stderr, "Virtio-9p device couldn't find fsdev with the " | |
72 | "id = %s\n", conf->fsdev_id ? conf->fsdev_id : "NULL"); | |
73 | exit(1); | |
74 | } | |
75 | ||
76 | if (!fse->path || !conf->tag) { | |
77 | /* we haven't specified a mount_tag or the path */ | |
78 | fprintf(stderr, "fsdev with id %s needs path " | |
79 | "and Virtio-9p device needs mount_tag arguments\n", | |
80 | conf->fsdev_id); | |
81 | exit(1); | |
82 | } | |
83 | ||
84 | if (!strcmp(fse->security_model, "passthrough")) { | |
85 | /* Files on the Fileserver set to client user credentials */ | |
86 | s->ctx.fs_sm = SM_PASSTHROUGH; | |
87 | s->ctx.xops = passthrough_xattr_ops; | |
88 | } else if (!strcmp(fse->security_model, "mapped")) { | |
89 | /* Files on the fileserver are set to QEMU credentials. | |
90 | * Client user credentials are saved in extended attributes. | |
91 | */ | |
92 | s->ctx.fs_sm = SM_MAPPED; | |
93 | s->ctx.xops = mapped_xattr_ops; | |
94 | } else if (!strcmp(fse->security_model, "none")) { | |
95 | /* | |
96 | * Files on the fileserver are set to QEMU credentials. | |
97 | */ | |
98 | s->ctx.fs_sm = SM_NONE; | |
99 | s->ctx.xops = none_xattr_ops; | |
100 | } else { | |
101 | fprintf(stderr, "Default to security_model=none. You may want" | |
102 | " enable advanced security model using " | |
103 | "security option:\n\t security_model=passthrough\n\t " | |
104 | "security_model=mapped\n"); | |
105 | s->ctx.fs_sm = SM_NONE; | |
106 | s->ctx.xops = none_xattr_ops; | |
107 | } | |
108 | ||
109 | if (lstat(fse->path, &stat)) { | |
110 | fprintf(stderr, "share path %s does not exist\n", fse->path); | |
111 | exit(1); | |
112 | } else if (!S_ISDIR(stat.st_mode)) { | |
113 | fprintf(stderr, "share path %s is not a directory\n", fse->path); | |
114 | exit(1); | |
115 | } | |
116 | ||
7267c094 | 117 | s->ctx.fs_root = g_strdup(fse->path); |
f4f61d27 AK |
118 | len = strlen(conf->tag); |
119 | if (len > MAX_TAG_LEN) { | |
120 | len = MAX_TAG_LEN; | |
121 | } | |
122 | /* s->tag is non-NULL terminated string */ | |
7267c094 | 123 | s->tag = g_malloc(len); |
f4f61d27 AK |
124 | memcpy(s->tag, conf->tag, len); |
125 | s->tag_len = len; | |
126 | s->ctx.uid = -1; | |
127 | ||
128 | s->ops = fse->ops; | |
129 | s->vdev.get_features = virtio_9p_get_features; | |
130 | s->config_size = sizeof(struct virtio_9p_config) + | |
131 | s->tag_len; | |
132 | s->vdev.get_config = virtio_9p_get_config; | |
133 | ||
39c0564e VJ |
134 | if (v9fs_init_worker_threads() < 0) { |
135 | fprintf(stderr, "worker thread initialization failed\n"); | |
136 | exit(1); | |
137 | } | |
f4f61d27 AK |
138 | return &s->vdev; |
139 | } | |
140 | ||
141 | static int virtio_9p_init_pci(PCIDevice *pci_dev) | |
142 | { | |
143 | VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); | |
144 | VirtIODevice *vdev; | |
145 | ||
146 | vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf); | |
147 | vdev->nvectors = proxy->nvectors; | |
befeac45 | 148 | virtio_init_pci(proxy, vdev); |
f4f61d27 AK |
149 | /* make the actual value visible */ |
150 | proxy->nvectors = vdev->nvectors; | |
151 | return 0; | |
152 | } | |
153 | ||
154 | static PCIDeviceInfo virtio_9p_info = { | |
155 | .qdev.name = "virtio-9p-pci", | |
156 | .qdev.size = sizeof(VirtIOPCIProxy), | |
157 | .init = virtio_9p_init_pci, | |
befeac45 MT |
158 | .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET, |
159 | .device_id = 0x1009, | |
160 | .revision = VIRTIO_PCI_ABI_VERSION, | |
161 | .class_id = 0x2, | |
f4f61d27 AK |
162 | .qdev.props = (Property[]) { |
163 | DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), | |
164 | DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), | |
165 | DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag), | |
166 | DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id), | |
167 | DEFINE_PROP_END_OF_LIST(), | |
168 | } | |
169 | }; | |
170 | ||
171 | static void virtio_9p_register_devices(void) | |
172 | { | |
173 | pci_qdev_register(&virtio_9p_info); | |
174 | } | |
175 | ||
176 | device_init(virtio_9p_register_devices) |