virtio-9p: Implement TXATTRCREATE
[qemu/stefanha.git] / hw / virtio-9p-debug.c
blobad680545c6b92c709f5a1efe314f29515107c606
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 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");
178 fprintf(llogfile, "}");
181 static void pprint_stat_dotl(V9fsPDU *pdu, int rx, size_t *offsetp,
182 const char *name)
184 fprintf(llogfile, "%s={", name);
185 pprint_qid(pdu, rx, offsetp, "qid");
186 pprint_int32(pdu, rx, offsetp, ", st_mode");
187 pprint_int64(pdu, rx, offsetp, ", st_nlink");
188 pprint_int32(pdu, rx, offsetp, ", st_uid");
189 pprint_int32(pdu, rx, offsetp, ", st_gid");
190 pprint_int64(pdu, rx, offsetp, ", st_rdev");
191 pprint_int64(pdu, rx, offsetp, ", st_size");
192 pprint_int64(pdu, rx, offsetp, ", st_blksize");
193 pprint_int64(pdu, rx, offsetp, ", st_blocks");
194 pprint_int64(pdu, rx, offsetp, ", atime");
195 pprint_int64(pdu, rx, offsetp, ", atime_nsec");
196 pprint_int64(pdu, rx, offsetp, ", mtime");
197 pprint_int64(pdu, rx, offsetp, ", mtime_nsec");
198 pprint_int64(pdu, rx, offsetp, ", ctime");
199 pprint_int64(pdu, rx, offsetp, ", ctime_nsec");
200 fprintf(llogfile, "}");
205 static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
207 int sg_count = get_sg_count(pdu, rx);
208 struct iovec *sg = get_sg(pdu, rx);
209 size_t offset = *offsetp;
210 uint16_t tmp_count, count, i;
211 size_t copied = 0;
213 fprintf(llogfile, "%s={", name);
215 /* Get the count */
216 copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
217 BUG_ON(copied != sizeof(tmp_count));
218 count = le16_to_cpupu(&tmp_count);
219 offset += copied;
221 for (i = 0; i < count; i++) {
222 char str[512];
223 if (i) {
224 fprintf(llogfile, ", ");
226 snprintf(str, sizeof(str), "[%d]", i);
227 pprint_str(pdu, rx, &offset, str);
230 fprintf(llogfile, "}");
232 *offsetp = offset;
235 static void pprint_qids(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
237 int sg_count = get_sg_count(pdu, rx);
238 struct iovec *sg = get_sg(pdu, rx);
239 size_t offset = *offsetp;
240 uint16_t tmp_count, count, i;
241 size_t copied = 0;
243 fprintf(llogfile, "%s={", name);
245 copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
246 BUG_ON(copied != sizeof(tmp_count));
247 count = le16_to_cpupu(&tmp_count);
248 offset += copied;
250 for (i = 0; i < count; i++) {
251 char str[512];
252 if (i) {
253 fprintf(llogfile, ", ");
255 snprintf(str, sizeof(str), "[%d]", i);
256 pprint_qid(pdu, rx, &offset, str);
259 fprintf(llogfile, "}");
261 *offsetp = offset;
264 static void pprint_sg(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
266 struct iovec *sg = get_sg(pdu, rx);
267 unsigned int count;
268 int i;
270 if (rx) {
271 count = pdu->elem.in_num;
272 } else {
273 count = pdu->elem.out_num;
276 fprintf(llogfile, "%s={", name);
277 for (i = 0; i < count; i++) {
278 if (i) {
279 fprintf(llogfile, ", ");
281 fprintf(llogfile, "(%p, 0x%zx)", sg[i].iov_base, sg[i].iov_len);
283 fprintf(llogfile, "}");
286 /* FIXME: read from a directory fid returns serialized stat_t's */
287 #ifdef DEBUG_DATA
288 static void pprint_data(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
290 struct iovec *sg = get_sg(pdu, rx);
291 size_t offset = *offsetp;
292 unsigned int count;
293 int32_t size;
294 int total, i, j;
295 ssize_t len;
297 if (rx) {
298 count = pdu->elem.in_num;
299 } else
300 count = pdu->elem.out_num;
303 BUG_ON((offset + sizeof(size)) > sg[0].iov_len);
305 memcpy(&size, sg[0].iov_base + offset, sizeof(size));
306 offset += sizeof(size);
308 fprintf(llogfile, "size: %x\n", size);
310 sg[0].iov_base += 11; /* skip header */
311 sg[0].iov_len -= 11;
313 total = 0;
314 for (i = 0; i < count; i++) {
315 total += sg[i].iov_len;
316 if (total >= size) {
317 /* trim sg list so writev does the right thing */
318 sg[i].iov_len -= (total - size);
319 i++;
320 break;
324 fprintf(llogfile, "%s={\"", name);
325 fflush(llogfile);
326 for (j = 0; j < i; j++) {
327 if (j) {
328 fprintf(llogfile, "\", \"");
329 fflush(llogfile);
332 do {
333 len = writev(fileno(llogfile), &sg[j], 1);
334 } while (len == -1 && errno == EINTR);
335 fprintf(llogfile, "len == %ld: %m\n", len);
336 BUG_ON(len != sg[j].iov_len);
338 fprintf(llogfile, "\"}");
340 sg[0].iov_base -= 11;
341 sg[0].iov_len += 11;
344 #endif
346 void pprint_pdu(V9fsPDU *pdu)
348 size_t offset = 7;
350 if (llogfile == NULL) {
351 llogfile = fopen("/tmp/pdu.log", "w");
354 BUG_ON(!llogfile);
356 switch (pdu->id) {
357 case P9_TREADDIR:
358 fprintf(llogfile, "TREADDIR: (");
359 pprint_int32(pdu, 0, &offset, "fid");
360 pprint_int64(pdu, 0, &offset, ", initial offset");
361 pprint_int32(pdu, 0, &offset, ", max count");
362 break;
363 case P9_RREADDIR:
364 fprintf(llogfile, "RREADDIR: (");
365 pprint_int32(pdu, 1, &offset, "count");
366 #ifdef DEBUG_DATA
367 pprint_data(pdu, 1, &offset, ", data");
368 #endif
369 break;
370 case P9_TMKDIR:
371 fprintf(llogfile, "TMKDIR: (");
372 pprint_int32(pdu, 0, &offset, "fid");
373 pprint_str(pdu, 0, &offset, "name");
374 pprint_int32(pdu, 0, &offset, "mode");
375 pprint_int32(pdu, 0, &offset, "gid");
376 break;
377 case P9_RMKDIR:
378 fprintf(llogfile, "RMKDIR: (");
379 pprint_qid(pdu, 0, &offset, "qid");
380 break;
381 case P9_TVERSION:
382 fprintf(llogfile, "TVERSION: (");
383 pprint_int32(pdu, 0, &offset, "msize");
384 pprint_str(pdu, 0, &offset, ", version");
385 break;
386 case P9_RVERSION:
387 fprintf(llogfile, "RVERSION: (");
388 pprint_int32(pdu, 1, &offset, "msize");
389 pprint_str(pdu, 1, &offset, ", version");
390 break;
391 case P9_TGETATTR:
392 fprintf(llogfile, "TGETATTR: (");
393 pprint_int32(pdu, 0, &offset, "fid");
394 break;
395 case P9_RGETATTR:
396 fprintf(llogfile, "RGETATTR: (");
397 pprint_stat_dotl(pdu, 1, &offset, "getattr");
398 break;
399 case P9_TAUTH:
400 fprintf(llogfile, "TAUTH: (");
401 pprint_int32(pdu, 0, &offset, "afid");
402 pprint_str(pdu, 0, &offset, ", uname");
403 pprint_str(pdu, 0, &offset, ", aname");
404 if (dotu) {
405 pprint_int32(pdu, 0, &offset, ", n_uname");
407 break;
408 case P9_RAUTH:
409 fprintf(llogfile, "RAUTH: (");
410 pprint_qid(pdu, 1, &offset, "qid");
411 break;
412 case P9_TATTACH:
413 fprintf(llogfile, "TATTACH: (");
414 pprint_int32(pdu, 0, &offset, "fid");
415 pprint_int32(pdu, 0, &offset, ", afid");
416 pprint_str(pdu, 0, &offset, ", uname");
417 pprint_str(pdu, 0, &offset, ", aname");
418 if (dotu) {
419 pprint_int32(pdu, 0, &offset, ", n_uname");
421 break;
422 case P9_RATTACH:
423 fprintf(llogfile, "RATTACH: (");
424 pprint_qid(pdu, 1, &offset, "qid");
425 break;
426 case P9_TERROR:
427 fprintf(llogfile, "TERROR: (");
428 break;
429 case P9_RERROR:
430 fprintf(llogfile, "RERROR: (");
431 pprint_str(pdu, 1, &offset, "ename");
432 if (dotu) {
433 pprint_int32(pdu, 1, &offset, ", ecode");
435 break;
436 case P9_TFLUSH:
437 fprintf(llogfile, "TFLUSH: (");
438 pprint_int16(pdu, 0, &offset, "oldtag");
439 break;
440 case P9_RFLUSH:
441 fprintf(llogfile, "RFLUSH: (");
442 break;
443 case P9_TWALK:
444 fprintf(llogfile, "TWALK: (");
445 pprint_int32(pdu, 0, &offset, "fid");
446 pprint_int32(pdu, 0, &offset, ", newfid");
447 pprint_strs(pdu, 0, &offset, ", wnames");
448 break;
449 case P9_RWALK:
450 fprintf(llogfile, "RWALK: (");
451 pprint_qids(pdu, 1, &offset, "wqids");
452 break;
453 case P9_TOPEN:
454 fprintf(llogfile, "TOPEN: (");
455 pprint_int32(pdu, 0, &offset, "fid");
456 pprint_int8(pdu, 0, &offset, ", mode");
457 break;
458 case P9_ROPEN:
459 fprintf(llogfile, "ROPEN: (");
460 pprint_qid(pdu, 1, &offset, "qid");
461 pprint_int32(pdu, 1, &offset, ", iounit");
462 break;
463 case P9_TCREATE:
464 fprintf(llogfile, "TCREATE: (");
465 pprint_int32(pdu, 0, &offset, "fid");
466 pprint_str(pdu, 0, &offset, ", name");
467 pprint_int32(pdu, 0, &offset, ", perm");
468 pprint_int8(pdu, 0, &offset, ", mode");
469 if (dotu) {
470 pprint_str(pdu, 0, &offset, ", extension");
472 break;
473 case P9_RCREATE:
474 fprintf(llogfile, "RCREATE: (");
475 pprint_qid(pdu, 1, &offset, "qid");
476 pprint_int32(pdu, 1, &offset, ", iounit");
477 break;
478 case P9_TSYMLINK:
479 fprintf(llogfile, "TSYMLINK: (");
480 pprint_int32(pdu, 0, &offset, "fid");
481 pprint_str(pdu, 0, &offset, ", name");
482 pprint_str(pdu, 0, &offset, ", symname");
483 pprint_int32(pdu, 0, &offset, ", gid");
484 break;
485 case P9_RSYMLINK:
486 fprintf(llogfile, "RSYMLINK: (");
487 pprint_qid(pdu, 1, &offset, "qid");
488 break;
489 case P9_TLCREATE:
490 fprintf(llogfile, "TLCREATE: (");
491 pprint_int32(pdu, 0, &offset, "dfid");
492 pprint_str(pdu, 0, &offset, ", name");
493 pprint_int32(pdu, 0, &offset, ", flags");
494 pprint_int32(pdu, 0, &offset, ", mode");
495 pprint_int32(pdu, 0, &offset, ", gid");
496 break;
497 case P9_RLCREATE:
498 fprintf(llogfile, "RLCREATE: (");
499 pprint_qid(pdu, 1, &offset, "qid");
500 pprint_int32(pdu, 1, &offset, ", iounit");
501 break;
502 case P9_TMKNOD:
503 fprintf(llogfile, "TMKNOD: (");
504 pprint_int32(pdu, 0, &offset, "fid");
505 pprint_str(pdu, 0, &offset, "name");
506 pprint_int32(pdu, 0, &offset, "mode");
507 pprint_int32(pdu, 0, &offset, "major");
508 pprint_int32(pdu, 0, &offset, "minor");
509 pprint_int32(pdu, 0, &offset, "gid");
510 break;
511 case P9_RMKNOD:
512 fprintf(llogfile, "RMKNOD: )");
513 pprint_qid(pdu, 0, &offset, "qid");
514 break;
515 case P9_TREAD:
516 fprintf(llogfile, "TREAD: (");
517 pprint_int32(pdu, 0, &offset, "fid");
518 pprint_int64(pdu, 0, &offset, ", offset");
519 pprint_int32(pdu, 0, &offset, ", count");
520 pprint_sg(pdu, 0, &offset, ", sg");
521 break;
522 case P9_RREAD:
523 fprintf(llogfile, "RREAD: (");
524 pprint_int32(pdu, 1, &offset, "count");
525 pprint_sg(pdu, 1, &offset, ", sg");
526 offset = 7;
527 #ifdef DEBUG_DATA
528 pprint_data(pdu, 1, &offset, ", data");
529 #endif
530 break;
531 case P9_TWRITE:
532 fprintf(llogfile, "TWRITE: (");
533 pprint_int32(pdu, 0, &offset, "fid");
534 pprint_int64(pdu, 0, &offset, ", offset");
535 pprint_int32(pdu, 0, &offset, ", count");
536 break;
537 case P9_RWRITE:
538 fprintf(llogfile, "RWRITE: (");
539 pprint_int32(pdu, 1, &offset, "count");
540 break;
541 case P9_TCLUNK:
542 fprintf(llogfile, "TCLUNK: (");
543 pprint_int32(pdu, 0, &offset, "fid");
544 break;
545 case P9_RCLUNK:
546 fprintf(llogfile, "RCLUNK: (");
547 break;
548 case P9_TLINK:
549 fprintf(llogfile, "TLINK: (");
550 pprint_int32(pdu, 0, &offset, "fid");
551 pprint_str(pdu, 0, &offset, ", oldpath");
552 pprint_str(pdu, 0, &offset, ", newpath");
553 break;
554 case P9_RLINK:
555 fprintf(llogfile, "RLINK: (");
556 break;
557 case P9_TREMOVE:
558 fprintf(llogfile, "TREMOVE: (");
559 pprint_int32(pdu, 0, &offset, "fid");
560 break;
561 case P9_RREMOVE:
562 fprintf(llogfile, "RREMOVE: (");
563 break;
564 case P9_TSTAT:
565 fprintf(llogfile, "TSTAT: (");
566 pprint_int32(pdu, 0, &offset, "fid");
567 break;
568 case P9_RSTAT:
569 fprintf(llogfile, "RSTAT: (");
570 offset += 2; /* ignored */
571 pprint_stat(pdu, 1, &offset, "stat");
572 break;
573 case P9_TWSTAT:
574 fprintf(llogfile, "TWSTAT: (");
575 pprint_int32(pdu, 0, &offset, "fid");
576 offset += 2; /* ignored */
577 pprint_stat(pdu, 0, &offset, ", stat");
578 break;
579 case P9_RWSTAT:
580 fprintf(llogfile, "RWSTAT: (");
581 break;
582 case P9_TXATTRWALK:
583 fprintf(llogfile, "TXATTRWALK: (");
584 pprint_int32(pdu, 0, &offset, "fid");
585 pprint_int32(pdu, 0, &offset, ", newfid");
586 pprint_str(pdu, 0, &offset, ", xattr name");
587 break;
588 case P9_RXATTRWALK:
589 fprintf(llogfile, "RXATTRWALK: (");
590 pprint_int64(pdu, 1, &offset, "xattrsize");
591 case P9_TXATTRCREATE:
592 fprintf(llogfile, "TXATTRCREATE: (");
593 pprint_int32(pdu, 0, &offset, "fid");
594 pprint_str(pdu, 0, &offset, ", name");
595 pprint_int64(pdu, 0, &offset, ", xattrsize");
596 pprint_int32(pdu, 0, &offset, ", flags");
597 break;
598 case P9_RXATTRCREATE:
599 fprintf(llogfile, "RXATTRCREATE: (");
600 break;
601 default:
602 fprintf(llogfile, "unknown(%d): (", pdu->id);
603 break;
606 fprintf(llogfile, ")\n");
607 /* Flush the log message out */
608 fflush(llogfile);