]> git.proxmox.com Git - qemu.git/blame - hw/virtio-9p-debug.c
virtio-blk: Avoid zeroing every request structure
[qemu.git] / hw / virtio-9p-debug.c
CommitLineData
9f107513
AL
1/*
2 * Virtio 9p PDU debug
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#include "virtio.h"
14#include "pc.h"
15#include "virtio-9p.h"
16#include "virtio-9p-debug.h"
17
18#define BUG_ON(cond) assert(!(cond))
19
20static FILE *llogfile;
21
22static struct iovec *get_sg(V9fsPDU *pdu, int rx)
23{
24 if (rx) {
25 return pdu->elem.in_sg;
26 }
27 return pdu->elem.out_sg;
28}
29
30static int get_sg_count(V9fsPDU *pdu, int rx)
31{
32 if (rx) {
33 return pdu->elem.in_num;
34 }
35 return pdu->elem.out_num;
36
37}
38
39static void pprint_int8(V9fsPDU *pdu, int rx, size_t *offsetp,
40 const char *name)
41{
42 size_t copied;
43 int count = get_sg_count(pdu, rx);
44 size_t offset = *offsetp;
45 struct iovec *sg = get_sg(pdu, rx);
46 int8_t value;
47
48 copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
49
50 BUG_ON(copied != sizeof(value));
51 offset += sizeof(value);
52 fprintf(llogfile, "%s=0x%x", name, value);
53 *offsetp = offset;
54}
55
56static void pprint_int16(V9fsPDU *pdu, int rx, size_t *offsetp,
57 const char *name)
58{
59 size_t copied;
60 int count = get_sg_count(pdu, rx);
61 struct iovec *sg = get_sg(pdu, rx);
62 size_t offset = *offsetp;
63 int16_t value;
64
65
66 copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
67
68 BUG_ON(copied != sizeof(value));
69 offset += sizeof(value);
70 fprintf(llogfile, "%s=0x%x", name, value);
71 *offsetp = offset;
72}
73
74static void pprint_int32(V9fsPDU *pdu, int rx, size_t *offsetp,
75 const char *name)
76{
77 size_t copied;
78 int count = get_sg_count(pdu, rx);
79 struct iovec *sg = get_sg(pdu, rx);
80 size_t offset = *offsetp;
81 int32_t value;
82
83
84 copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
85
86 BUG_ON(copied != sizeof(value));
87 offset += sizeof(value);
88 fprintf(llogfile, "%s=0x%x", name, value);
89 *offsetp = offset;
90}
91
92static void pprint_int64(V9fsPDU *pdu, int rx, size_t *offsetp,
93 const char *name)
94{
95 size_t copied;
96 int count = get_sg_count(pdu, rx);
97 struct iovec *sg = get_sg(pdu, rx);
98 size_t offset = *offsetp;
99 int64_t value;
100
101
102 copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
103
104 BUG_ON(copied != sizeof(value));
105 offset += sizeof(value);
106 fprintf(llogfile, "%s=0x%" PRIx64, name, value);
107 *offsetp = offset;
108}
109
110static void pprint_str(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
111{
112 int sg_count = get_sg_count(pdu, rx);
113 struct iovec *sg = get_sg(pdu, rx);
114 size_t offset = *offsetp;
115 uint16_t tmp_size, size;
116 size_t result;
117 size_t copied = 0;
118 int i = 0;
119
120 /* get the size */
121 copied = do_pdu_unpack(&tmp_size, sg, sg_count, offset, sizeof(tmp_size));
122 BUG_ON(copied != sizeof(tmp_size));
123 size = le16_to_cpupu(&tmp_size);
124 offset += copied;
125
126 fprintf(llogfile, "%s=", name);
127 for (i = 0; size && i < sg_count; i++) {
128 size_t len;
129 if (offset >= sg[i].iov_len) {
130 /* skip this sg */
131 offset -= sg[i].iov_len;
132 continue;
133 } else {
134 len = MIN(sg[i].iov_len - offset, size);
135 result = fwrite(sg[i].iov_base + offset, 1, len, llogfile);
136 BUG_ON(result != len);
137 size -= len;
138 copied += len;
139 if (size) {
140 offset = 0;
141 continue;
142 }
143 }
144 }
145 *offsetp += copied;
146}
147
148static void pprint_qid(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
149{
150 fprintf(llogfile, "%s={", name);
151 pprint_int8(pdu, rx, offsetp, "type");
152 pprint_int32(pdu, rx, offsetp, ", version");
153 pprint_int64(pdu, rx, offsetp, ", path");
154 fprintf(llogfile, "}");
155}
156
157static void pprint_stat(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
158{
159 fprintf(llogfile, "%s={", name);
160 pprint_int16(pdu, rx, offsetp, "size");
161 pprint_int16(pdu, rx, offsetp, ", type");
162 pprint_int32(pdu, rx, offsetp, ", dev");
163 pprint_qid(pdu, rx, offsetp, ", qid");
164 pprint_int32(pdu, rx, offsetp, ", mode");
165 pprint_int32(pdu, rx, offsetp, ", atime");
166 pprint_int32(pdu, rx, offsetp, ", mtime");
167 pprint_int64(pdu, rx, offsetp, ", length");
168 pprint_str(pdu, rx, offsetp, ", name");
169 pprint_str(pdu, rx, offsetp, ", uid");
170 pprint_str(pdu, rx, offsetp, ", gid");
171 pprint_str(pdu, rx, offsetp, ", muid");
172 if (dotu) {
173 pprint_str(pdu, rx, offsetp, ", extension");
174 pprint_int32(pdu, rx, offsetp, ", uid");
175 pprint_int32(pdu, rx, offsetp, ", gid");
176 pprint_int32(pdu, rx, offsetp, ", muid");
177 }
178 fprintf(llogfile, "}");
179}
180
181static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
182{
183 int sg_count = get_sg_count(pdu, rx);
184 struct iovec *sg = get_sg(pdu, rx);
185 size_t offset = *offsetp;
186 uint16_t tmp_count, count, i;
187 size_t copied = 0;
188
189 fprintf(llogfile, "%s={", name);
190
191 /* Get the count */
192 copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
193 BUG_ON(copied != sizeof(tmp_count));
194 count = le16_to_cpupu(&tmp_count);
195 offset += copied;
196
197 for (i = 0; i < count; i++) {
198 char str[512];
199 if (i) {
200 fprintf(llogfile, ", ");
201 }
202 snprintf(str, sizeof(str), "[%d]", i);
203 pprint_str(pdu, rx, &offset, str);
204 }
205
206 fprintf(llogfile, "}");
207
208 *offsetp = offset;
209}
210
211static void pprint_qids(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
212{
213 int sg_count = get_sg_count(pdu, rx);
214 struct iovec *sg = get_sg(pdu, rx);
215 size_t offset = *offsetp;
216 uint16_t tmp_count, count, i;
217 size_t copied = 0;
218
219 fprintf(llogfile, "%s={", name);
220
221 copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
222 BUG_ON(copied != sizeof(tmp_count));
223 count = le16_to_cpupu(&tmp_count);
224 offset += copied;
225
226 for (i = 0; i < count; i++) {
227 char str[512];
228 if (i) {
229 fprintf(llogfile, ", ");
230 }
231 snprintf(str, sizeof(str), "[%d]", i);
232 pprint_qid(pdu, rx, &offset, str);
233 }
234
235 fprintf(llogfile, "}");
236
237 *offsetp = offset;
238}
239
240static void pprint_sg(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
241{
242 struct iovec *sg = get_sg(pdu, rx);
243 unsigned int count;
244 int i;
245
246 if (rx) {
247 count = pdu->elem.in_num;
248 } else {
249 count = pdu->elem.out_num;
250 }
251
252 fprintf(llogfile, "%s={", name);
253 for (i = 0; i < count; i++) {
254 if (i) {
255 fprintf(llogfile, ", ");
256 }
257 fprintf(llogfile, "(%p, 0x%zx)", sg[i].iov_base, sg[i].iov_len);
258 }
259 fprintf(llogfile, "}");
260}
261
262/* FIXME: read from a directory fid returns serialized stat_t's */
263#ifdef DEBUG_DATA
264static void pprint_data(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
265{
266 struct iovec *sg = get_sg(pdu, rx);
267 size_t offset = *offsetp;
268 unsigned int count;
269 int32_t size;
270 int total, i, j;
271 ssize_t len;
272
273 if (rx) {
274 count = pdu->elem.in_num;
275 } else
276 count = pdu->elem.out_num;
277 }
278
279 BUG_ON((offset + sizeof(size)) > sg[0].iov_len);
280
281 memcpy(&size, sg[0].iov_base + offset, sizeof(size));
282 offset += sizeof(size);
283
284 fprintf(llogfile, "size: %x\n", size);
285
286 sg[0].iov_base += 11; /* skip header */
287 sg[0].iov_len -= 11;
288
289 total = 0;
290 for (i = 0; i < count; i++) {
291 total += sg[i].iov_len;
292 if (total >= size) {
293 /* trim sg list so writev does the right thing */
294 sg[i].iov_len -= (total - size);
295 i++;
296 break;
297 }
298 }
299
300 fprintf(llogfile, "%s={\"", name);
301 fflush(llogfile);
302 for (j = 0; j < i; j++) {
303 if (j) {
304 fprintf(llogfile, "\", \"");
305 fflush(llogfile);
306 }
307
308 do {
309 len = writev(fileno(llogfile), &sg[j], 1);
310 } while (len == -1 && errno == EINTR);
311 fprintf(llogfile, "len == %ld: %m\n", len);
312 BUG_ON(len != sg[j].iov_len);
313 }
314 fprintf(llogfile, "\"}");
315
316 sg[0].iov_base -= 11;
317 sg[0].iov_len += 11;
318
319}
320#endif
321
322void pprint_pdu(V9fsPDU *pdu)
323{
324 size_t offset = 7;
325
326 if (llogfile == NULL) {
327 llogfile = fopen("/tmp/pdu.log", "w");
328 }
329
330 switch (pdu->id) {
331 case P9_TVERSION:
332 fprintf(llogfile, "TVERSION: (");
333 pprint_int32(pdu, 0, &offset, "msize");
334 pprint_str(pdu, 0, &offset, ", version");
335 break;
336 case P9_RVERSION:
337 fprintf(llogfile, "RVERSION: (");
338 pprint_int32(pdu, 1, &offset, "msize");
339 pprint_str(pdu, 1, &offset, ", version");
340 break;
341 case P9_TAUTH:
342 fprintf(llogfile, "TAUTH: (");
343 pprint_int32(pdu, 0, &offset, "afid");
344 pprint_str(pdu, 0, &offset, ", uname");
345 pprint_str(pdu, 0, &offset, ", aname");
346 if (dotu) {
347 pprint_int32(pdu, 0, &offset, ", n_uname");
348 }
349 break;
350 case P9_RAUTH:
351 fprintf(llogfile, "RAUTH: (");
352 pprint_qid(pdu, 1, &offset, "qid");
353 break;
354 case P9_TATTACH:
355 fprintf(llogfile, "TATTACH: (");
356 pprint_int32(pdu, 0, &offset, "fid");
357 pprint_int32(pdu, 0, &offset, ", afid");
358 pprint_str(pdu, 0, &offset, ", uname");
359 pprint_str(pdu, 0, &offset, ", aname");
360 if (dotu) {
361 pprint_int32(pdu, 0, &offset, ", n_uname");
362 }
363 break;
364 case P9_RATTACH:
365 fprintf(llogfile, "RATTACH: (");
366 pprint_qid(pdu, 1, &offset, "qid");
367 break;
368 case P9_TERROR:
369 fprintf(llogfile, "TERROR: (");
370 break;
371 case P9_RERROR:
372 fprintf(llogfile, "RERROR: (");
373 pprint_str(pdu, 1, &offset, "ename");
374 if (dotu) {
375 pprint_int32(pdu, 1, &offset, ", ecode");
376 }
377 break;
378 case P9_TFLUSH:
379 fprintf(llogfile, "TFLUSH: (");
380 pprint_int16(pdu, 0, &offset, "oldtag");
381 break;
382 case P9_RFLUSH:
383 fprintf(llogfile, "RFLUSH: (");
384 break;
385 case P9_TWALK:
386 fprintf(llogfile, "TWALK: (");
387 pprint_int32(pdu, 0, &offset, "fid");
388 pprint_int32(pdu, 0, &offset, ", newfid");
389 pprint_strs(pdu, 0, &offset, ", wnames");
390 break;
391 case P9_RWALK:
392 fprintf(llogfile, "RWALK: (");
393 pprint_qids(pdu, 1, &offset, "wqids");
394 break;
395 case P9_TOPEN:
396 fprintf(llogfile, "TOPEN: (");
397 pprint_int32(pdu, 0, &offset, "fid");
398 pprint_int8(pdu, 0, &offset, ", mode");
399 break;
400 case P9_ROPEN:
401 fprintf(llogfile, "ROPEN: (");
402 pprint_qid(pdu, 1, &offset, "qid");
403 pprint_int32(pdu, 1, &offset, ", iounit");
404 break;
405 case P9_TCREATE:
406 fprintf(llogfile, "TCREATE: (");
407 pprint_int32(pdu, 0, &offset, "fid");
408 pprint_str(pdu, 0, &offset, ", name");
409 pprint_int32(pdu, 0, &offset, ", perm");
410 pprint_int8(pdu, 0, &offset, ", mode");
411 if (dotu) {
412 pprint_str(pdu, 0, &offset, ", extension");
413 }
414 break;
415 case P9_RCREATE:
416 fprintf(llogfile, "RCREATE: (");
417 pprint_qid(pdu, 1, &offset, "qid");
418 pprint_int32(pdu, 1, &offset, ", iounit");
419 break;
420 case P9_TREAD:
421 fprintf(llogfile, "TREAD: (");
422 pprint_int32(pdu, 0, &offset, "fid");
423 pprint_int64(pdu, 0, &offset, ", offset");
424 pprint_int32(pdu, 0, &offset, ", count");
425 pprint_sg(pdu, 0, &offset, ", sg");
426 break;
427 case P9_RREAD:
428 fprintf(llogfile, "RREAD: (");
429 pprint_int32(pdu, 1, &offset, "count");
430 pprint_sg(pdu, 1, &offset, ", sg");
431 offset = 7;
432#ifdef DEBUG_DATA
433 pprint_data(pdu, 1, &offset, ", data");
434#endif
435 break;
436 case P9_TWRITE:
437 fprintf(llogfile, "TWRITE: (");
438 pprint_int32(pdu, 0, &offset, "fid");
439 pprint_int64(pdu, 0, &offset, ", offset");
440 pprint_int32(pdu, 0, &offset, ", count");
441 break;
442 case P9_RWRITE:
443 fprintf(llogfile, "RWRITE: (");
444 pprint_int32(pdu, 1, &offset, "count");
445 break;
446 case P9_TCLUNK:
447 fprintf(llogfile, "TCLUNK: (");
448 pprint_int32(pdu, 0, &offset, "fid");
449 break;
450 case P9_RCLUNK:
451 fprintf(llogfile, "RCLUNK: (");
452 break;
453 case P9_TREMOVE:
454 fprintf(llogfile, "TREMOVE: (");
455 pprint_int32(pdu, 0, &offset, "fid");
456 break;
457 case P9_RREMOVE:
458 fprintf(llogfile, "RREMOVE: (");
459 break;
460 case P9_TSTAT:
461 fprintf(llogfile, "TSTAT: (");
462 pprint_int32(pdu, 0, &offset, "fid");
463 break;
464 case P9_RSTAT:
465 fprintf(llogfile, "RSTAT: (");
466 offset += 2; /* ignored */
467 pprint_stat(pdu, 1, &offset, "stat");
468 break;
469 case P9_TWSTAT:
470 fprintf(llogfile, "TWSTAT: (");
471 pprint_int32(pdu, 0, &offset, "fid");
472 offset += 2; /* ignored */
473 pprint_stat(pdu, 0, &offset, ", stat");
474 break;
475 case P9_RWSTAT:
476 fprintf(llogfile, "RWSTAT: (");
477 break;
478 default:
479 fprintf(llogfile, "unknown(%d): (", pdu->id);
480 break;
481 }
482
483 fprintf(llogfile, ")\n");
484}