nbd: add missed aio_context_acquire in nbd_export_new
[qemu/ar7.git] / fsdev / 9p-iov-marshal.c
blob08d783ca1172c6ec397469cdf21c1f3e3422ad09
1 /*
2 * 9p backend
4 * Copyright IBM, Corp. 2010
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
14 #include <glib.h>
15 #include <glib/gprintf.h>
16 #include <sys/types.h>
17 #include <sys/time.h>
18 #include <utime.h>
19 #include <sys/uio.h>
20 #include <string.h>
21 #include <stdint.h>
22 #include <errno.h>
24 #include "qemu/compiler.h"
25 #include "9p-iov-marshal.h"
26 #include "qemu/bswap.h"
28 static ssize_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
29 size_t offset, size_t size, int pack)
31 int i = 0;
32 size_t copied = 0;
33 size_t req_size = size;
36 for (i = 0; size && i < sg_count; i++) {
37 size_t len;
38 if (offset >= sg[i].iov_len) {
39 /* skip this sg */
40 offset -= sg[i].iov_len;
41 continue;
42 } else {
43 len = MIN(sg[i].iov_len - offset, size);
44 if (pack) {
45 memcpy(sg[i].iov_base + offset, addr, len);
46 } else {
47 memcpy(addr, sg[i].iov_base + offset, len);
49 size -= len;
50 copied += len;
51 addr += len;
52 if (size) {
53 offset = 0;
54 continue;
58 if (copied < req_size) {
60 * We copied less that requested size. error out
62 return -ENOBUFS;
64 return copied;
67 static ssize_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num,
68 size_t offset, size_t size)
70 return v9fs_packunpack(dst, out_sg, out_num, offset, size, 0);
73 ssize_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset,
74 const void *src, size_t size)
76 return v9fs_packunpack((void *)src, in_sg, in_num, offset, size, 1);
79 ssize_t v9fs_iov_vunmarshal(struct iovec *out_sg, int out_num, size_t offset,
80 int bswap, const char *fmt, va_list ap)
82 int i;
83 ssize_t copied = 0;
84 size_t old_offset = offset;
86 for (i = 0; fmt[i]; i++) {
87 switch (fmt[i]) {
88 case 'b': {
89 uint8_t *valp = va_arg(ap, uint8_t *);
90 copied = v9fs_unpack(valp, out_sg, out_num, offset, sizeof(*valp));
91 break;
93 case 'w': {
94 uint16_t val, *valp;
95 valp = va_arg(ap, uint16_t *);
96 copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
97 if (bswap) {
98 *valp = le16_to_cpu(val);
99 } else {
100 *valp = val;
102 break;
104 case 'd': {
105 uint32_t val, *valp;
106 valp = va_arg(ap, uint32_t *);
107 copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
108 if (bswap) {
109 *valp = le32_to_cpu(val);
110 } else {
111 *valp = val;
113 break;
115 case 'q': {
116 uint64_t val, *valp;
117 valp = va_arg(ap, uint64_t *);
118 copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
119 if (bswap) {
120 *valp = le64_to_cpu(val);
121 } else {
122 *valp = val;
124 break;
126 case 's': {
127 V9fsString *str = va_arg(ap, V9fsString *);
128 copied = v9fs_iov_unmarshal(out_sg, out_num, offset, bswap,
129 "w", &str->size);
130 if (copied > 0) {
131 offset += copied;
132 str->data = g_malloc(str->size + 1);
133 copied = v9fs_unpack(str->data, out_sg, out_num, offset,
134 str->size);
135 if (copied > 0) {
136 str->data[str->size] = 0;
137 } else {
138 v9fs_string_free(str);
141 break;
143 case 'Q': {
144 V9fsQID *qidp = va_arg(ap, V9fsQID *);
145 copied = v9fs_iov_unmarshal(out_sg, out_num, offset, bswap,
146 "bdq", &qidp->type, &qidp->version,
147 &qidp->path);
148 break;
150 case 'S': {
151 V9fsStat *statp = va_arg(ap, V9fsStat *);
152 copied = v9fs_iov_unmarshal(out_sg, out_num, offset, bswap,
153 "wwdQdddqsssssddd",
154 &statp->size, &statp->type,
155 &statp->dev, &statp->qid,
156 &statp->mode, &statp->atime,
157 &statp->mtime, &statp->length,
158 &statp->name, &statp->uid,
159 &statp->gid, &statp->muid,
160 &statp->extension,
161 &statp->n_uid, &statp->n_gid,
162 &statp->n_muid);
163 break;
165 case 'I': {
166 V9fsIattr *iattr = va_arg(ap, V9fsIattr *);
167 copied = v9fs_iov_unmarshal(out_sg, out_num, offset, bswap,
168 "ddddqqqqq",
169 &iattr->valid, &iattr->mode,
170 &iattr->uid, &iattr->gid,
171 &iattr->size, &iattr->atime_sec,
172 &iattr->atime_nsec,
173 &iattr->mtime_sec,
174 &iattr->mtime_nsec);
175 break;
177 default:
178 break;
180 if (copied < 0) {
181 return copied;
183 offset += copied;
186 return offset - old_offset;
189 ssize_t v9fs_iov_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
190 int bswap, const char *fmt, ...)
192 ssize_t ret;
193 va_list ap;
195 va_start(ap, fmt);
196 ret = v9fs_iov_vunmarshal(out_sg, out_num, offset, bswap, fmt, ap);
197 va_end(ap);
199 return ret;
202 ssize_t v9fs_iov_vmarshal(struct iovec *in_sg, int in_num, size_t offset,
203 int bswap, const char *fmt, va_list ap)
205 int i;
206 ssize_t copied = 0;
207 size_t old_offset = offset;
209 for (i = 0; fmt[i]; i++) {
210 switch (fmt[i]) {
211 case 'b': {
212 uint8_t val = va_arg(ap, int);
213 copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
214 break;
216 case 'w': {
217 uint16_t val;
218 if (bswap) {
219 cpu_to_le16w(&val, va_arg(ap, int));
220 } else {
221 val = va_arg(ap, int);
223 copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
224 break;
226 case 'd': {
227 uint32_t val;
228 if (bswap) {
229 cpu_to_le32w(&val, va_arg(ap, uint32_t));
230 } else {
231 val = va_arg(ap, uint32_t);
233 copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
234 break;
236 case 'q': {
237 uint64_t val;
238 if (bswap) {
239 cpu_to_le64w(&val, va_arg(ap, uint64_t));
240 } else {
241 val = va_arg(ap, uint64_t);
243 copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
244 break;
246 case 's': {
247 V9fsString *str = va_arg(ap, V9fsString *);
248 copied = v9fs_iov_marshal(in_sg, in_num, offset, bswap,
249 "w", str->size);
250 if (copied > 0) {
251 offset += copied;
252 copied = v9fs_pack(in_sg, in_num, offset, str->data, str->size);
254 break;
256 case 'Q': {
257 V9fsQID *qidp = va_arg(ap, V9fsQID *);
258 copied = v9fs_iov_marshal(in_sg, in_num, offset, bswap, "bdq",
259 qidp->type, qidp->version,
260 qidp->path);
261 break;
263 case 'S': {
264 V9fsStat *statp = va_arg(ap, V9fsStat *);
265 copied = v9fs_iov_marshal(in_sg, in_num, offset, bswap,
266 "wwdQdddqsssssddd",
267 statp->size, statp->type, statp->dev,
268 &statp->qid, statp->mode, statp->atime,
269 statp->mtime, statp->length,
270 &statp->name,
271 &statp->uid, &statp->gid, &statp->muid,
272 &statp->extension, statp->n_uid,
273 statp->n_gid, statp->n_muid);
274 break;
276 case 'A': {
277 V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *);
278 copied = v9fs_iov_marshal(in_sg, in_num, offset, bswap,
279 "qQdddqqqqqqqqqqqqqqq",
280 statp->st_result_mask,
281 &statp->qid, statp->st_mode,
282 statp->st_uid, statp->st_gid,
283 statp->st_nlink, statp->st_rdev,
284 statp->st_size, statp->st_blksize,
285 statp->st_blocks, statp->st_atime_sec,
286 statp->st_atime_nsec,
287 statp->st_mtime_sec,
288 statp->st_mtime_nsec,
289 statp->st_ctime_sec,
290 statp->st_ctime_nsec,
291 statp->st_btime_sec,
292 statp->st_btime_nsec, statp->st_gen,
293 statp->st_data_version);
294 break;
296 default:
297 break;
299 if (copied < 0) {
300 return copied;
302 offset += copied;
305 return offset - old_offset;
308 ssize_t v9fs_iov_marshal(struct iovec *in_sg, int in_num, size_t offset,
309 int bswap, const char *fmt, ...)
311 ssize_t ret;
312 va_list ap;
314 va_start(ap, fmt);
315 ret = v9fs_iov_vmarshal(in_sg, in_num, offset, bswap, fmt, ap);
316 va_end(ap);
318 return ret;