Merge remote branch 'kwolf/for-anthony' into staging
[qemu.git] / hw / virtio-9p-debug.c
blob6f6a0ec13bb5f8f4df68e474b8dc87093b8eb778
1 /*
2 * Virtio 9p PDU debug
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.
13 #include "virtio.h"
14 #include "pc.h"
15 #include "virtio-9p.h"
16 #include "virtio-9p-debug.h"
18 #define BUG_ON(cond) assert(!(cond))
20 static FILE *llogfile;
22 static struct iovec *get_sg(V9fsPDU *pdu, int rx)
24 if (rx) {
25 return pdu->elem.in_sg;
27 return pdu->elem.out_sg;
30 static int get_sg_count(V9fsPDU *pdu, int rx)
32 if (rx) {
33 return pdu->elem.in_num;
35 return pdu->elem.out_num;
39 static void pprint_int8(V9fsPDU *pdu, int rx, size_t *offsetp,
40 const char *name)
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;
48 copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
50 BUG_ON(copied != sizeof(value));
51 offset += sizeof(value);
52 fprintf(llogfile, "%s=0x%x", name, value);
53 *offsetp = offset;
56 static void pprint_int16(V9fsPDU *pdu, int rx, size_t *offsetp,
57 const char *name)
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;
66 copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
68 BUG_ON(copied != sizeof(value));
69 offset += sizeof(value);
70 fprintf(llogfile, "%s=0x%x", name, value);
71 *offsetp = offset;
74 static void pprint_int32(V9fsPDU *pdu, int rx, size_t *offsetp,
75 const char *name)
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;
84 copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
86 BUG_ON(copied != sizeof(value));
87 offset += sizeof(value);
88 fprintf(llogfile, "%s=0x%x", name, value);
89 *offsetp = offset;
92 static void pprint_int64(V9fsPDU *pdu, int rx, size_t *offsetp,
93 const char *name)
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;
102 copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
104 BUG_ON(copied != sizeof(value));
105 offset += sizeof(value);
106 fprintf(llogfile, "%s=0x%" PRIx64, name, value);
107 *offsetp = offset;
110 static void pprint_str(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
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;
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;
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;
145 *offsetp += copied;
148 static void pprint_qid(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
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, "}");
157 static void pprint_stat(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
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 pprint_str(pdu, rx, offsetp, ", extension");
173 pprint_int32(pdu, rx, offsetp, ", uid");
174 pprint_int32(pdu, rx, offsetp, ", gid");
175 pprint_int32(pdu, rx, offsetp, ", muid");
176 fprintf(llogfile, "}");
179 static void pprint_stat_dotl(V9fsPDU *pdu, int rx, size_t *offsetp,
180 const char *name)
182 fprintf(llogfile, "%s={", name);
183 pprint_qid(pdu, rx, offsetp, "qid");
184 pprint_int32(pdu, rx, offsetp, ", st_mode");
185 pprint_int64(pdu, rx, offsetp, ", st_nlink");
186 pprint_int32(pdu, rx, offsetp, ", st_uid");
187 pprint_int32(pdu, rx, offsetp, ", st_gid");
188 pprint_int64(pdu, rx, offsetp, ", st_rdev");
189 pprint_int64(pdu, rx, offsetp, ", st_size");
190 pprint_int64(pdu, rx, offsetp, ", st_blksize");
191 pprint_int64(pdu, rx, offsetp, ", st_blocks");
192 pprint_int64(pdu, rx, offsetp, ", atime");
193 pprint_int64(pdu, rx, offsetp, ", atime_nsec");
194 pprint_int64(pdu, rx, offsetp, ", mtime");
195 pprint_int64(pdu, rx, offsetp, ", mtime_nsec");
196 pprint_int64(pdu, rx, offsetp, ", ctime");
197 pprint_int64(pdu, rx, offsetp, ", ctime_nsec");
198 fprintf(llogfile, "}");
203 static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
205 int sg_count = get_sg_count(pdu, rx);
206 struct iovec *sg = get_sg(pdu, rx);
207 size_t offset = *offsetp;
208 uint16_t tmp_count, count, i;
209 size_t copied = 0;
211 fprintf(llogfile, "%s={", name);
213 /* Get the count */
214 copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
215 BUG_ON(copied != sizeof(tmp_count));
216 count = le16_to_cpupu(&tmp_count);
217 offset += copied;
219 for (i = 0; i < count; i++) {
220 char str[512];
221 if (i) {
222 fprintf(llogfile, ", ");
224 snprintf(str, sizeof(str), "[%d]", i);
225 pprint_str(pdu, rx, &offset, str);
228 fprintf(llogfile, "}");
230 *offsetp = offset;
233 static void pprint_qids(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
235 int sg_count = get_sg_count(pdu, rx);
236 struct iovec *sg = get_sg(pdu, rx);
237 size_t offset = *offsetp;
238 uint16_t tmp_count, count, i;
239 size_t copied = 0;
241 fprintf(llogfile, "%s={", name);
243 copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
244 BUG_ON(copied != sizeof(tmp_count));
245 count = le16_to_cpupu(&tmp_count);
246 offset += copied;
248 for (i = 0; i < count; i++) {
249 char str[512];
250 if (i) {
251 fprintf(llogfile, ", ");
253 snprintf(str, sizeof(str), "[%d]", i);
254 pprint_qid(pdu, rx, &offset, str);
257 fprintf(llogfile, "}");
259 *offsetp = offset;
262 static void pprint_sg(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
264 struct iovec *sg = get_sg(pdu, rx);
265 unsigned int count;
266 int i;
268 if (rx) {
269 count = pdu->elem.in_num;
270 } else {
271 count = pdu->elem.out_num;
274 fprintf(llogfile, "%s={", name);
275 for (i = 0; i < count; i++) {
276 if (i) {
277 fprintf(llogfile, ", ");
279 fprintf(llogfile, "(%p, 0x%zx)", sg[i].iov_base, sg[i].iov_len);
281 fprintf(llogfile, "}");
284 /* FIXME: read from a directory fid returns serialized stat_t's */
285 #ifdef DEBUG_DATA
286 static void pprint_data(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
288 struct iovec *sg = get_sg(pdu, rx);
289 size_t offset = *offsetp;
290 unsigned int count;
291 int32_t size;
292 int total, i, j;
293 ssize_t len;
295 if (rx) {
296 count = pdu->elem.in_num;
297 } else
298 count = pdu->elem.out_num;
301 BUG_ON((offset + sizeof(size)) > sg[0].iov_len);
303 memcpy(&size, sg[0].iov_base + offset, sizeof(size));
304 offset += sizeof(size);
306 fprintf(llogfile, "size: %x\n", size);
308 sg[0].iov_base += 11; /* skip header */
309 sg[0].iov_len -= 11;
311 total = 0;
312 for (i = 0; i < count; i++) {
313 total += sg[i].iov_len;
314 if (total >= size) {
315 /* trim sg list so writev does the right thing */
316 sg[i].iov_len -= (total - size);
317 i++;
318 break;
322 fprintf(llogfile, "%s={\"", name);
323 fflush(llogfile);
324 for (j = 0; j < i; j++) {
325 if (j) {
326 fprintf(llogfile, "\", \"");
327 fflush(llogfile);
330 do {
331 len = writev(fileno(llogfile), &sg[j], 1);
332 } while (len == -1 && errno == EINTR);
333 fprintf(llogfile, "len == %ld: %m\n", len);
334 BUG_ON(len != sg[j].iov_len);
336 fprintf(llogfile, "\"}");
338 sg[0].iov_base -= 11;
339 sg[0].iov_len += 11;
342 #endif
344 void pprint_pdu(V9fsPDU *pdu)
346 size_t offset = 7;
348 if (llogfile == NULL) {
349 llogfile = fopen("/tmp/pdu.log", "w");
352 BUG_ON(!llogfile);
354 switch (pdu->id) {
355 case P9_TREADDIR:
356 fprintf(llogfile, "TREADDIR: (");
357 pprint_int32(pdu, 0, &offset, "fid");
358 pprint_int64(pdu, 0, &offset, ", initial offset");
359 pprint_int32(pdu, 0, &offset, ", max count");
360 break;
361 case P9_RREADDIR:
362 fprintf(llogfile, "RREADDIR: (");
363 pprint_int32(pdu, 1, &offset, "count");
364 #ifdef DEBUG_DATA
365 pprint_data(pdu, 1, &offset, ", data");
366 #endif
367 break;
368 case P9_TMKDIR:
369 fprintf(llogfile, "TMKDIR: (");
370 pprint_int32(pdu, 0, &offset, "fid");
371 pprint_str(pdu, 0, &offset, "name");
372 pprint_int32(pdu, 0, &offset, "mode");
373 pprint_int32(pdu, 0, &offset, "gid");
374 break;
375 case P9_RMKDIR:
376 fprintf(llogfile, "RMKDIR: (");
377 pprint_qid(pdu, 0, &offset, "qid");
378 break;
379 case P9_TVERSION:
380 fprintf(llogfile, "TVERSION: (");
381 pprint_int32(pdu, 0, &offset, "msize");
382 pprint_str(pdu, 0, &offset, ", version");
383 break;
384 case P9_RVERSION:
385 fprintf(llogfile, "RVERSION: (");
386 pprint_int32(pdu, 1, &offset, "msize");
387 pprint_str(pdu, 1, &offset, ", version");
388 break;
389 case P9_TGETATTR:
390 fprintf(llogfile, "TGETATTR: (");
391 pprint_int32(pdu, 0, &offset, "fid");
392 break;
393 case P9_RGETATTR:
394 fprintf(llogfile, "RGETATTR: (");
395 pprint_stat_dotl(pdu, 1, &offset, "getattr");
396 break;
397 case P9_TAUTH:
398 fprintf(llogfile, "TAUTH: (");
399 pprint_int32(pdu, 0, &offset, "afid");
400 pprint_str(pdu, 0, &offset, ", uname");
401 pprint_str(pdu, 0, &offset, ", aname");
402 pprint_int32(pdu, 0, &offset, ", n_uname");
403 break;
404 case P9_RAUTH:
405 fprintf(llogfile, "RAUTH: (");
406 pprint_qid(pdu, 1, &offset, "qid");
407 break;
408 case P9_TATTACH:
409 fprintf(llogfile, "TATTACH: (");
410 pprint_int32(pdu, 0, &offset, "fid");
411 pprint_int32(pdu, 0, &offset, ", afid");
412 pprint_str(pdu, 0, &offset, ", uname");
413 pprint_str(pdu, 0, &offset, ", aname");
414 pprint_int32(pdu, 0, &offset, ", n_uname");
415 break;
416 case P9_RATTACH:
417 fprintf(llogfile, "RATTACH: (");
418 pprint_qid(pdu, 1, &offset, "qid");
419 break;
420 case P9_TERROR:
421 fprintf(llogfile, "TERROR: (");
422 break;
423 case P9_RERROR:
424 fprintf(llogfile, "RERROR: (");
425 pprint_str(pdu, 1, &offset, "ename");
426 pprint_int32(pdu, 1, &offset, ", ecode");
427 break;
428 case P9_TFLUSH:
429 fprintf(llogfile, "TFLUSH: (");
430 pprint_int16(pdu, 0, &offset, "oldtag");
431 break;
432 case P9_RFLUSH:
433 fprintf(llogfile, "RFLUSH: (");
434 break;
435 case P9_TWALK:
436 fprintf(llogfile, "TWALK: (");
437 pprint_int32(pdu, 0, &offset, "fid");
438 pprint_int32(pdu, 0, &offset, ", newfid");
439 pprint_strs(pdu, 0, &offset, ", wnames");
440 break;
441 case P9_RWALK:
442 fprintf(llogfile, "RWALK: (");
443 pprint_qids(pdu, 1, &offset, "wqids");
444 break;
445 case P9_TOPEN:
446 fprintf(llogfile, "TOPEN: (");
447 pprint_int32(pdu, 0, &offset, "fid");
448 pprint_int8(pdu, 0, &offset, ", mode");
449 break;
450 case P9_ROPEN:
451 fprintf(llogfile, "ROPEN: (");
452 pprint_qid(pdu, 1, &offset, "qid");
453 pprint_int32(pdu, 1, &offset, ", iounit");
454 break;
455 case P9_TCREATE:
456 fprintf(llogfile, "TCREATE: (");
457 pprint_int32(pdu, 0, &offset, "fid");
458 pprint_str(pdu, 0, &offset, ", name");
459 pprint_int32(pdu, 0, &offset, ", perm");
460 pprint_int8(pdu, 0, &offset, ", mode");
461 pprint_str(pdu, 0, &offset, ", extension");
462 break;
463 case P9_RCREATE:
464 fprintf(llogfile, "RCREATE: (");
465 pprint_qid(pdu, 1, &offset, "qid");
466 pprint_int32(pdu, 1, &offset, ", iounit");
467 break;
468 case P9_TSYMLINK:
469 fprintf(llogfile, "TSYMLINK: (");
470 pprint_int32(pdu, 0, &offset, "fid");
471 pprint_str(pdu, 0, &offset, ", name");
472 pprint_str(pdu, 0, &offset, ", symname");
473 pprint_int32(pdu, 0, &offset, ", gid");
474 break;
475 case P9_RSYMLINK:
476 fprintf(llogfile, "RSYMLINK: (");
477 pprint_qid(pdu, 1, &offset, "qid");
478 break;
479 case P9_TLCREATE:
480 fprintf(llogfile, "TLCREATE: (");
481 pprint_int32(pdu, 0, &offset, "dfid");
482 pprint_str(pdu, 0, &offset, ", name");
483 pprint_int32(pdu, 0, &offset, ", flags");
484 pprint_int32(pdu, 0, &offset, ", mode");
485 pprint_int32(pdu, 0, &offset, ", gid");
486 break;
487 case P9_RLCREATE:
488 fprintf(llogfile, "RLCREATE: (");
489 pprint_qid(pdu, 1, &offset, "qid");
490 pprint_int32(pdu, 1, &offset, ", iounit");
491 break;
492 case P9_TMKNOD:
493 fprintf(llogfile, "TMKNOD: (");
494 pprint_int32(pdu, 0, &offset, "fid");
495 pprint_str(pdu, 0, &offset, "name");
496 pprint_int32(pdu, 0, &offset, "mode");
497 pprint_int32(pdu, 0, &offset, "major");
498 pprint_int32(pdu, 0, &offset, "minor");
499 pprint_int32(pdu, 0, &offset, "gid");
500 break;
501 case P9_RMKNOD:
502 fprintf(llogfile, "RMKNOD: )");
503 pprint_qid(pdu, 0, &offset, "qid");
504 break;
505 case P9_TREAD:
506 fprintf(llogfile, "TREAD: (");
507 pprint_int32(pdu, 0, &offset, "fid");
508 pprint_int64(pdu, 0, &offset, ", offset");
509 pprint_int32(pdu, 0, &offset, ", count");
510 pprint_sg(pdu, 0, &offset, ", sg");
511 break;
512 case P9_RREAD:
513 fprintf(llogfile, "RREAD: (");
514 pprint_int32(pdu, 1, &offset, "count");
515 pprint_sg(pdu, 1, &offset, ", sg");
516 offset = 7;
517 #ifdef DEBUG_DATA
518 pprint_data(pdu, 1, &offset, ", data");
519 #endif
520 break;
521 case P9_TWRITE:
522 fprintf(llogfile, "TWRITE: (");
523 pprint_int32(pdu, 0, &offset, "fid");
524 pprint_int64(pdu, 0, &offset, ", offset");
525 pprint_int32(pdu, 0, &offset, ", count");
526 break;
527 case P9_RWRITE:
528 fprintf(llogfile, "RWRITE: (");
529 pprint_int32(pdu, 1, &offset, "count");
530 break;
531 case P9_TCLUNK:
532 fprintf(llogfile, "TCLUNK: (");
533 pprint_int32(pdu, 0, &offset, "fid");
534 break;
535 case P9_RCLUNK:
536 fprintf(llogfile, "RCLUNK: (");
537 break;
538 case P9_TLINK:
539 fprintf(llogfile, "TLINK: (");
540 pprint_int32(pdu, 0, &offset, "fid");
541 pprint_str(pdu, 0, &offset, ", oldpath");
542 pprint_str(pdu, 0, &offset, ", newpath");
543 break;
544 case P9_RLINK:
545 fprintf(llogfile, "RLINK: (");
546 break;
547 case P9_TREMOVE:
548 fprintf(llogfile, "TREMOVE: (");
549 pprint_int32(pdu, 0, &offset, "fid");
550 break;
551 case P9_RREMOVE:
552 fprintf(llogfile, "RREMOVE: (");
553 break;
554 case P9_TSTAT:
555 fprintf(llogfile, "TSTAT: (");
556 pprint_int32(pdu, 0, &offset, "fid");
557 break;
558 case P9_RSTAT:
559 fprintf(llogfile, "RSTAT: (");
560 offset += 2; /* ignored */
561 pprint_stat(pdu, 1, &offset, "stat");
562 break;
563 case P9_TWSTAT:
564 fprintf(llogfile, "TWSTAT: (");
565 pprint_int32(pdu, 0, &offset, "fid");
566 offset += 2; /* ignored */
567 pprint_stat(pdu, 0, &offset, ", stat");
568 break;
569 case P9_RWSTAT:
570 fprintf(llogfile, "RWSTAT: (");
571 break;
572 case P9_TXATTRWALK:
573 fprintf(llogfile, "TXATTRWALK: (");
574 pprint_int32(pdu, 0, &offset, "fid");
575 pprint_int32(pdu, 0, &offset, ", newfid");
576 pprint_str(pdu, 0, &offset, ", xattr name");
577 break;
578 case P9_RXATTRWALK:
579 fprintf(llogfile, "RXATTRWALK: (");
580 pprint_int64(pdu, 1, &offset, "xattrsize");
581 case P9_TXATTRCREATE:
582 fprintf(llogfile, "TXATTRCREATE: (");
583 pprint_int32(pdu, 0, &offset, "fid");
584 pprint_str(pdu, 0, &offset, ", name");
585 pprint_int64(pdu, 0, &offset, ", xattrsize");
586 pprint_int32(pdu, 0, &offset, ", flags");
587 break;
588 case P9_RXATTRCREATE:
589 fprintf(llogfile, "RXATTRCREATE: (");
590 break;
591 default:
592 fprintf(llogfile, "unknown(%d): (", pdu->id);
593 break;
596 fprintf(llogfile, ")\n");
597 /* Flush the log message out */
598 fflush(llogfile);