]>
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 | ||
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) | |
0174fe73 | 48 | { |
f4f61d27 AK |
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); | |
bccacf6c | 61 | QLIST_INIT(&s->active_list); |
f4f61d27 AK |
62 | for (i = 0; i < (MAX_REQ - 1); i++) { |
63 | QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next); | |
64 | } | |
65 | ||
66 | s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output); | |
67 | ||
68 | fse = get_fsdev_fsentry(conf->fsdev_id); | |
69 | ||
70 | if (!fse) { | |
71 | /* We don't have a fsdev identified by fsdev_id */ | |
72 | fprintf(stderr, "Virtio-9p device couldn't find fsdev with the " | |
73 | "id = %s\n", conf->fsdev_id ? conf->fsdev_id : "NULL"); | |
74 | exit(1); | |
75 | } | |
76 | ||
77 | if (!fse->path || !conf->tag) { | |
78 | /* we haven't specified a mount_tag or the path */ | |
79 | fprintf(stderr, "fsdev with id %s needs path " | |
80 | "and Virtio-9p device needs mount_tag arguments\n", | |
81 | conf->fsdev_id); | |
82 | exit(1); | |
83 | } | |
84 | ||
85 | if (!strcmp(fse->security_model, "passthrough")) { | |
86 | /* Files on the Fileserver set to client user credentials */ | |
87 | s->ctx.fs_sm = SM_PASSTHROUGH; | |
88 | s->ctx.xops = passthrough_xattr_ops; | |
89 | } else if (!strcmp(fse->security_model, "mapped")) { | |
90 | /* Files on the fileserver are set to QEMU credentials. | |
91 | * Client user credentials are saved in extended attributes. | |
92 | */ | |
93 | s->ctx.fs_sm = SM_MAPPED; | |
94 | s->ctx.xops = mapped_xattr_ops; | |
95 | } else if (!strcmp(fse->security_model, "none")) { | |
96 | /* | |
97 | * Files on the fileserver are set to QEMU credentials. | |
98 | */ | |
99 | s->ctx.fs_sm = SM_NONE; | |
100 | s->ctx.xops = none_xattr_ops; | |
101 | } else { | |
102 | fprintf(stderr, "Default to security_model=none. You may want" | |
103 | " enable advanced security model using " | |
104 | "security option:\n\t security_model=passthrough\n\t " | |
105 | "security_model=mapped\n"); | |
106 | s->ctx.fs_sm = SM_NONE; | |
107 | s->ctx.xops = none_xattr_ops; | |
108 | } | |
109 | ||
110 | if (lstat(fse->path, &stat)) { | |
111 | fprintf(stderr, "share path %s does not exist\n", fse->path); | |
112 | exit(1); | |
113 | } else if (!S_ISDIR(stat.st_mode)) { | |
114 | fprintf(stderr, "share path %s is not a directory\n", fse->path); | |
115 | exit(1); | |
116 | } | |
117 | ||
7267c094 | 118 | s->ctx.fs_root = g_strdup(fse->path); |
f4f61d27 AK |
119 | len = strlen(conf->tag); |
120 | if (len > MAX_TAG_LEN) { | |
121 | len = MAX_TAG_LEN; | |
122 | } | |
123 | /* s->tag is non-NULL terminated string */ | |
7267c094 | 124 | s->tag = g_malloc(len); |
f4f61d27 AK |
125 | memcpy(s->tag, conf->tag, len); |
126 | s->tag_len = len; | |
127 | s->ctx.uid = -1; | |
532decb7 | 128 | s->ctx.flags = 0; |
f4f61d27 AK |
129 | |
130 | s->ops = fse->ops; | |
131 | s->vdev.get_features = virtio_9p_get_features; | |
132 | s->config_size = sizeof(struct virtio_9p_config) + | |
133 | s->tag_len; | |
134 | s->vdev.get_config = virtio_9p_get_config; | |
9e5b2247 | 135 | s->fid_list = NULL; |
02cb7f3a | 136 | qemu_co_rwlock_init(&s->rename_lock); |
f4f61d27 | 137 | |
0174fe73 AK |
138 | if (s->ops->init(&s->ctx) < 0) { |
139 | fprintf(stderr, "Virtio-9p Failed to initialize fs-driver with id:%s" | |
140 | " and export path:%s\n", conf->fsdev_id, s->ctx.fs_root); | |
141 | exit(1); | |
142 | } | |
39c0564e VJ |
143 | if (v9fs_init_worker_threads() < 0) { |
144 | fprintf(stderr, "worker thread initialization failed\n"); | |
145 | exit(1); | |
146 | } | |
f4f61d27 AK |
147 | return &s->vdev; |
148 | } | |
149 | ||
150 | static int virtio_9p_init_pci(PCIDevice *pci_dev) | |
151 | { | |
152 | VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); | |
153 | VirtIODevice *vdev; | |
154 | ||
155 | vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf); | |
156 | vdev->nvectors = proxy->nvectors; | |
befeac45 | 157 | virtio_init_pci(proxy, vdev); |
f4f61d27 AK |
158 | /* make the actual value visible */ |
159 | proxy->nvectors = vdev->nvectors; | |
160 | return 0; | |
161 | } | |
162 | ||
163 | static PCIDeviceInfo virtio_9p_info = { | |
164 | .qdev.name = "virtio-9p-pci", | |
165 | .qdev.size = sizeof(VirtIOPCIProxy), | |
166 | .init = virtio_9p_init_pci, | |
befeac45 MT |
167 | .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET, |
168 | .device_id = 0x1009, | |
169 | .revision = VIRTIO_PCI_ABI_VERSION, | |
170 | .class_id = 0x2, | |
f4f61d27 AK |
171 | .qdev.props = (Property[]) { |
172 | DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), | |
173 | DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), | |
174 | DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag), | |
175 | DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id), | |
176 | DEFINE_PROP_END_OF_LIST(), | |
177 | } | |
178 | }; | |
179 | ||
180 | static void virtio_9p_register_devices(void) | |
181 | { | |
182 | pci_qdev_register(&virtio_9p_info); | |
7a462745 | 183 | virtio_9p_set_fd_limit(); |
f4f61d27 AK |
184 | } |
185 | ||
186 | device_init(virtio_9p_register_devices) |