4 * Copyright IBM, Corp. 2010
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 "hw/virtio.h"
16 #include "virtio-9p.h"
17 #include "virtio-9p-debug.h"
19 #define BUG_ON(cond) assert(!(cond))
21 static FILE *llogfile
;
23 static struct iovec
*get_sg(V9fsPDU
*pdu
, int rx
)
26 return pdu
->elem
.in_sg
;
28 return pdu
->elem
.out_sg
;
31 static int get_sg_count(V9fsPDU
*pdu
, int rx
)
34 return pdu
->elem
.in_num
;
36 return pdu
->elem
.out_num
;
40 static void pprint_int8(V9fsPDU
*pdu
, int rx
, size_t *offsetp
,
44 int count
= get_sg_count(pdu
, rx
);
45 size_t offset
= *offsetp
;
46 struct iovec
*sg
= get_sg(pdu
, rx
);
49 copied
= do_pdu_unpack(&value
, sg
, count
, offset
, sizeof(value
));
51 BUG_ON(copied
!= sizeof(value
));
52 offset
+= sizeof(value
);
53 fprintf(llogfile
, "%s=0x%x", name
, value
);
57 static void pprint_int16(V9fsPDU
*pdu
, int rx
, size_t *offsetp
,
61 int count
= get_sg_count(pdu
, rx
);
62 struct iovec
*sg
= get_sg(pdu
, rx
);
63 size_t offset
= *offsetp
;
67 copied
= do_pdu_unpack(&value
, sg
, count
, offset
, sizeof(value
));
69 BUG_ON(copied
!= sizeof(value
));
70 offset
+= sizeof(value
);
71 fprintf(llogfile
, "%s=0x%x", name
, value
);
75 static void pprint_int32(V9fsPDU
*pdu
, int rx
, size_t *offsetp
,
79 int count
= get_sg_count(pdu
, rx
);
80 struct iovec
*sg
= get_sg(pdu
, rx
);
81 size_t offset
= *offsetp
;
85 copied
= do_pdu_unpack(&value
, sg
, count
, offset
, sizeof(value
));
87 BUG_ON(copied
!= sizeof(value
));
88 offset
+= sizeof(value
);
89 fprintf(llogfile
, "%s=0x%x", name
, value
);
93 static void pprint_int64(V9fsPDU
*pdu
, int rx
, size_t *offsetp
,
97 int count
= get_sg_count(pdu
, rx
);
98 struct iovec
*sg
= get_sg(pdu
, rx
);
99 size_t offset
= *offsetp
;
103 copied
= do_pdu_unpack(&value
, sg
, count
, offset
, sizeof(value
));
105 BUG_ON(copied
!= sizeof(value
));
106 offset
+= sizeof(value
);
107 fprintf(llogfile
, "%s=0x%" PRIx64
, name
, value
);
111 static void pprint_str(V9fsPDU
*pdu
, int rx
, size_t *offsetp
, const char *name
)
113 int sg_count
= get_sg_count(pdu
, rx
);
114 struct iovec
*sg
= get_sg(pdu
, rx
);
115 size_t offset
= *offsetp
;
116 uint16_t tmp_size
, size
;
122 copied
= do_pdu_unpack(&tmp_size
, sg
, sg_count
, offset
, sizeof(tmp_size
));
123 BUG_ON(copied
!= sizeof(tmp_size
));
124 size
= le16_to_cpupu(&tmp_size
);
127 fprintf(llogfile
, "%s=", name
);
128 for (i
= 0; size
&& i
< sg_count
; i
++) {
130 if (offset
>= sg
[i
].iov_len
) {
132 offset
-= sg
[i
].iov_len
;
135 len
= MIN(sg
[i
].iov_len
- offset
, size
);
136 result
= fwrite(sg
[i
].iov_base
+ offset
, 1, len
, llogfile
);
137 BUG_ON(result
!= len
);
149 static void pprint_qid(V9fsPDU
*pdu
, int rx
, size_t *offsetp
, const char *name
)
151 fprintf(llogfile
, "%s={", name
);
152 pprint_int8(pdu
, rx
, offsetp
, "type");
153 pprint_int32(pdu
, rx
, offsetp
, ", version");
154 pprint_int64(pdu
, rx
, offsetp
, ", path");
155 fprintf(llogfile
, "}");
158 static void pprint_stat(V9fsPDU
*pdu
, int rx
, size_t *offsetp
, const char *name
)
160 fprintf(llogfile
, "%s={", name
);
161 pprint_int16(pdu
, rx
, offsetp
, "size");
162 pprint_int16(pdu
, rx
, offsetp
, ", type");
163 pprint_int32(pdu
, rx
, offsetp
, ", dev");
164 pprint_qid(pdu
, rx
, offsetp
, ", qid");
165 pprint_int32(pdu
, rx
, offsetp
, ", mode");
166 pprint_int32(pdu
, rx
, offsetp
, ", atime");
167 pprint_int32(pdu
, rx
, offsetp
, ", mtime");
168 pprint_int64(pdu
, rx
, offsetp
, ", length");
169 pprint_str(pdu
, rx
, offsetp
, ", name");
170 pprint_str(pdu
, rx
, offsetp
, ", uid");
171 pprint_str(pdu
, rx
, offsetp
, ", gid");
172 pprint_str(pdu
, rx
, offsetp
, ", muid");
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 fprintf(llogfile
, "}");
180 static void pprint_stat_dotl(V9fsPDU
*pdu
, int rx
, size_t *offsetp
,
183 fprintf(llogfile
, "%s={", name
);
184 pprint_qid(pdu
, rx
, offsetp
, "qid");
185 pprint_int32(pdu
, rx
, offsetp
, ", st_mode");
186 pprint_int64(pdu
, rx
, offsetp
, ", st_nlink");
187 pprint_int32(pdu
, rx
, offsetp
, ", st_uid");
188 pprint_int32(pdu
, rx
, offsetp
, ", st_gid");
189 pprint_int64(pdu
, rx
, offsetp
, ", st_rdev");
190 pprint_int64(pdu
, rx
, offsetp
, ", st_size");
191 pprint_int64(pdu
, rx
, offsetp
, ", st_blksize");
192 pprint_int64(pdu
, rx
, offsetp
, ", st_blocks");
193 pprint_int64(pdu
, rx
, offsetp
, ", atime");
194 pprint_int64(pdu
, rx
, offsetp
, ", atime_nsec");
195 pprint_int64(pdu
, rx
, offsetp
, ", mtime");
196 pprint_int64(pdu
, rx
, offsetp
, ", mtime_nsec");
197 pprint_int64(pdu
, rx
, offsetp
, ", ctime");
198 pprint_int64(pdu
, rx
, offsetp
, ", ctime_nsec");
199 fprintf(llogfile
, "}");
204 static void pprint_strs(V9fsPDU
*pdu
, int rx
, size_t *offsetp
, const char *name
)
206 int sg_count
= get_sg_count(pdu
, rx
);
207 struct iovec
*sg
= get_sg(pdu
, rx
);
208 size_t offset
= *offsetp
;
209 uint16_t tmp_count
, count
, i
;
212 fprintf(llogfile
, "%s={", name
);
215 copied
= do_pdu_unpack(&tmp_count
, sg
, sg_count
, offset
, sizeof(tmp_count
));
216 BUG_ON(copied
!= sizeof(tmp_count
));
217 count
= le16_to_cpupu(&tmp_count
);
220 for (i
= 0; i
< count
; i
++) {
223 fprintf(llogfile
, ", ");
225 snprintf(str
, sizeof(str
), "[%d]", i
);
226 pprint_str(pdu
, rx
, &offset
, str
);
229 fprintf(llogfile
, "}");
234 static void pprint_qids(V9fsPDU
*pdu
, int rx
, size_t *offsetp
, const char *name
)
236 int sg_count
= get_sg_count(pdu
, rx
);
237 struct iovec
*sg
= get_sg(pdu
, rx
);
238 size_t offset
= *offsetp
;
239 uint16_t tmp_count
, count
, i
;
242 fprintf(llogfile
, "%s={", name
);
244 copied
= do_pdu_unpack(&tmp_count
, sg
, sg_count
, offset
, sizeof(tmp_count
));
245 BUG_ON(copied
!= sizeof(tmp_count
));
246 count
= le16_to_cpupu(&tmp_count
);
249 for (i
= 0; i
< count
; i
++) {
252 fprintf(llogfile
, ", ");
254 snprintf(str
, sizeof(str
), "[%d]", i
);
255 pprint_qid(pdu
, rx
, &offset
, str
);
258 fprintf(llogfile
, "}");
263 static void pprint_sg(V9fsPDU
*pdu
, int rx
, size_t *offsetp
, const char *name
)
265 struct iovec
*sg
= get_sg(pdu
, rx
);
270 count
= pdu
->elem
.in_num
;
272 count
= pdu
->elem
.out_num
;
275 fprintf(llogfile
, "%s={", name
);
276 for (i
= 0; i
< count
; i
++) {
278 fprintf(llogfile
, ", ");
280 fprintf(llogfile
, "(%p, 0x%zx)", sg
[i
].iov_base
, sg
[i
].iov_len
);
282 fprintf(llogfile
, "}");
285 /* FIXME: read from a directory fid returns serialized stat_t's */
287 static void pprint_data(V9fsPDU
*pdu
, int rx
, size_t *offsetp
, const char *name
)
289 struct iovec
*sg
= get_sg(pdu
, rx
);
290 size_t offset
= *offsetp
;
297 count
= pdu
->elem
.in_num
;
299 count
= pdu
->elem
.out_num
;
302 BUG_ON((offset
+ sizeof(size
)) > sg
[0].iov_len
);
304 memcpy(&size
, sg
[0].iov_base
+ offset
, sizeof(size
));
305 offset
+= sizeof(size
);
307 fprintf(llogfile
, "size: %x\n", size
);
309 sg
[0].iov_base
+= 11; /* skip header */
313 for (i
= 0; i
< count
; i
++) {
314 total
+= sg
[i
].iov_len
;
316 /* trim sg list so writev does the right thing */
317 sg
[i
].iov_len
-= (total
- size
);
323 fprintf(llogfile
, "%s={\"", name
);
325 for (j
= 0; j
< i
; j
++) {
327 fprintf(llogfile
, "\", \"");
332 len
= writev(fileno(llogfile
), &sg
[j
], 1);
333 } while (len
== -1 && errno
== EINTR
);
334 fprintf(llogfile
, "len == %ld: %m\n", len
);
335 BUG_ON(len
!= sg
[j
].iov_len
);
337 fprintf(llogfile
, "\"}");
339 sg
[0].iov_base
-= 11;
345 void pprint_pdu(V9fsPDU
*pdu
)
349 if (llogfile
== NULL
) {
350 llogfile
= fopen("/tmp/pdu.log", "w");
357 fprintf(llogfile
, "TREADDIR: (");
358 pprint_int32(pdu
, 0, &offset
, "fid");
359 pprint_int64(pdu
, 0, &offset
, ", initial offset");
360 pprint_int32(pdu
, 0, &offset
, ", max count");
363 fprintf(llogfile
, "RREADDIR: (");
364 pprint_int32(pdu
, 1, &offset
, "count");
366 pprint_data(pdu
, 1, &offset
, ", data");
370 fprintf(llogfile
, "TMKDIR: (");
371 pprint_int32(pdu
, 0, &offset
, "fid");
372 pprint_str(pdu
, 0, &offset
, "name");
373 pprint_int32(pdu
, 0, &offset
, "mode");
374 pprint_int32(pdu
, 0, &offset
, "gid");
377 fprintf(llogfile
, "RMKDIR: (");
378 pprint_qid(pdu
, 0, &offset
, "qid");
381 fprintf(llogfile
, "TVERSION: (");
382 pprint_int32(pdu
, 0, &offset
, "msize");
383 pprint_str(pdu
, 0, &offset
, ", version");
386 fprintf(llogfile
, "RVERSION: (");
387 pprint_int32(pdu
, 1, &offset
, "msize");
388 pprint_str(pdu
, 1, &offset
, ", version");
391 fprintf(llogfile
, "TGETATTR: (");
392 pprint_int32(pdu
, 0, &offset
, "fid");
395 fprintf(llogfile
, "RGETATTR: (");
396 pprint_stat_dotl(pdu
, 1, &offset
, "getattr");
399 fprintf(llogfile
, "TAUTH: (");
400 pprint_int32(pdu
, 0, &offset
, "afid");
401 pprint_str(pdu
, 0, &offset
, ", uname");
402 pprint_str(pdu
, 0, &offset
, ", aname");
403 pprint_int32(pdu
, 0, &offset
, ", n_uname");
406 fprintf(llogfile
, "RAUTH: (");
407 pprint_qid(pdu
, 1, &offset
, "qid");
410 fprintf(llogfile
, "TATTACH: (");
411 pprint_int32(pdu
, 0, &offset
, "fid");
412 pprint_int32(pdu
, 0, &offset
, ", afid");
413 pprint_str(pdu
, 0, &offset
, ", uname");
414 pprint_str(pdu
, 0, &offset
, ", aname");
415 pprint_int32(pdu
, 0, &offset
, ", n_uname");
418 fprintf(llogfile
, "RATTACH: (");
419 pprint_qid(pdu
, 1, &offset
, "qid");
422 fprintf(llogfile
, "TERROR: (");
425 fprintf(llogfile
, "RERROR: (");
426 pprint_str(pdu
, 1, &offset
, "ename");
427 pprint_int32(pdu
, 1, &offset
, ", ecode");
430 fprintf(llogfile
, "TFLUSH: (");
431 pprint_int16(pdu
, 0, &offset
, "oldtag");
434 fprintf(llogfile
, "RFLUSH: (");
437 fprintf(llogfile
, "TWALK: (");
438 pprint_int32(pdu
, 0, &offset
, "fid");
439 pprint_int32(pdu
, 0, &offset
, ", newfid");
440 pprint_strs(pdu
, 0, &offset
, ", wnames");
443 fprintf(llogfile
, "RWALK: (");
444 pprint_qids(pdu
, 1, &offset
, "wqids");
447 fprintf(llogfile
, "TOPEN: (");
448 pprint_int32(pdu
, 0, &offset
, "fid");
449 pprint_int8(pdu
, 0, &offset
, ", mode");
452 fprintf(llogfile
, "ROPEN: (");
453 pprint_qid(pdu
, 1, &offset
, "qid");
454 pprint_int32(pdu
, 1, &offset
, ", iounit");
457 fprintf(llogfile
, "TCREATE: (");
458 pprint_int32(pdu
, 0, &offset
, "fid");
459 pprint_str(pdu
, 0, &offset
, ", name");
460 pprint_int32(pdu
, 0, &offset
, ", perm");
461 pprint_int8(pdu
, 0, &offset
, ", mode");
462 pprint_str(pdu
, 0, &offset
, ", extension");
465 fprintf(llogfile
, "RCREATE: (");
466 pprint_qid(pdu
, 1, &offset
, "qid");
467 pprint_int32(pdu
, 1, &offset
, ", iounit");
470 fprintf(llogfile
, "TSYMLINK: (");
471 pprint_int32(pdu
, 0, &offset
, "fid");
472 pprint_str(pdu
, 0, &offset
, ", name");
473 pprint_str(pdu
, 0, &offset
, ", symname");
474 pprint_int32(pdu
, 0, &offset
, ", gid");
477 fprintf(llogfile
, "RSYMLINK: (");
478 pprint_qid(pdu
, 1, &offset
, "qid");
481 fprintf(llogfile
, "TLCREATE: (");
482 pprint_int32(pdu
, 0, &offset
, "dfid");
483 pprint_str(pdu
, 0, &offset
, ", name");
484 pprint_int32(pdu
, 0, &offset
, ", flags");
485 pprint_int32(pdu
, 0, &offset
, ", mode");
486 pprint_int32(pdu
, 0, &offset
, ", gid");
489 fprintf(llogfile
, "RLCREATE: (");
490 pprint_qid(pdu
, 1, &offset
, "qid");
491 pprint_int32(pdu
, 1, &offset
, ", iounit");
494 fprintf(llogfile
, "TMKNOD: (");
495 pprint_int32(pdu
, 0, &offset
, "fid");
496 pprint_str(pdu
, 0, &offset
, "name");
497 pprint_int32(pdu
, 0, &offset
, "mode");
498 pprint_int32(pdu
, 0, &offset
, "major");
499 pprint_int32(pdu
, 0, &offset
, "minor");
500 pprint_int32(pdu
, 0, &offset
, "gid");
503 fprintf(llogfile
, "RMKNOD: )");
504 pprint_qid(pdu
, 0, &offset
, "qid");
507 fprintf(llogfile
, "TREADLINK: (");
508 pprint_int32(pdu
, 0, &offset
, "fid");
511 fprintf(llogfile
, "RREADLINK: (");
512 pprint_str(pdu
, 0, &offset
, "target");
515 fprintf(llogfile
, "TREAD: (");
516 pprint_int32(pdu
, 0, &offset
, "fid");
517 pprint_int64(pdu
, 0, &offset
, ", offset");
518 pprint_int32(pdu
, 0, &offset
, ", count");
519 pprint_sg(pdu
, 0, &offset
, ", sg");
522 fprintf(llogfile
, "RREAD: (");
523 pprint_int32(pdu
, 1, &offset
, "count");
524 pprint_sg(pdu
, 1, &offset
, ", sg");
527 pprint_data(pdu
, 1, &offset
, ", data");
531 fprintf(llogfile
, "TWRITE: (");
532 pprint_int32(pdu
, 0, &offset
, "fid");
533 pprint_int64(pdu
, 0, &offset
, ", offset");
534 pprint_int32(pdu
, 0, &offset
, ", count");
537 fprintf(llogfile
, "RWRITE: (");
538 pprint_int32(pdu
, 1, &offset
, "count");
541 fprintf(llogfile
, "TCLUNK: (");
542 pprint_int32(pdu
, 0, &offset
, "fid");
545 fprintf(llogfile
, "RCLUNK: (");
548 fprintf(llogfile
, "TFSYNC: (");
549 pprint_int32(pdu
, 0, &offset
, "fid");
552 fprintf(llogfile
, "RFSYNC: (");
555 fprintf(llogfile
, "TLINK: (");
556 pprint_int32(pdu
, 0, &offset
, "dfid");
557 pprint_int32(pdu
, 0, &offset
, ", fid");
558 pprint_str(pdu
, 0, &offset
, ", newpath");
561 fprintf(llogfile
, "RLINK: (");
564 fprintf(llogfile
, "TREMOVE: (");
565 pprint_int32(pdu
, 0, &offset
, "fid");
568 fprintf(llogfile
, "RREMOVE: (");
571 fprintf(llogfile
, "TSTAT: (");
572 pprint_int32(pdu
, 0, &offset
, "fid");
575 fprintf(llogfile
, "RSTAT: (");
576 offset
+= 2; /* ignored */
577 pprint_stat(pdu
, 1, &offset
, "stat");
580 fprintf(llogfile
, "TWSTAT: (");
581 pprint_int32(pdu
, 0, &offset
, "fid");
582 offset
+= 2; /* ignored */
583 pprint_stat(pdu
, 0, &offset
, ", stat");
586 fprintf(llogfile
, "RWSTAT: (");
589 fprintf(llogfile
, "TXATTRWALK: (");
590 pprint_int32(pdu
, 0, &offset
, "fid");
591 pprint_int32(pdu
, 0, &offset
, ", newfid");
592 pprint_str(pdu
, 0, &offset
, ", xattr name");
595 fprintf(llogfile
, "RXATTRWALK: (");
596 pprint_int64(pdu
, 1, &offset
, "xattrsize");
597 case P9_TXATTRCREATE
:
598 fprintf(llogfile
, "TXATTRCREATE: (");
599 pprint_int32(pdu
, 0, &offset
, "fid");
600 pprint_str(pdu
, 0, &offset
, ", name");
601 pprint_int64(pdu
, 0, &offset
, ", xattrsize");
602 pprint_int32(pdu
, 0, &offset
, ", flags");
604 case P9_RXATTRCREATE
:
605 fprintf(llogfile
, "RXATTRCREATE: (");
608 fprintf(llogfile
, "TLOCK: (");
609 pprint_int32(pdu
, 0, &offset
, "fid");
610 pprint_int8(pdu
, 0, &offset
, ", type");
611 pprint_int32(pdu
, 0, &offset
, ", flags");
612 pprint_int64(pdu
, 0, &offset
, ", start");
613 pprint_int64(pdu
, 0, &offset
, ", length");
614 pprint_int32(pdu
, 0, &offset
, ", proc_id");
615 pprint_str(pdu
, 0, &offset
, ", client_id");
618 fprintf(llogfile
, "RLOCK: (");
619 pprint_int8(pdu
, 0, &offset
, "status");
622 fprintf(llogfile
, "TGETLOCK: (");
623 pprint_int32(pdu
, 0, &offset
, "fid");
624 pprint_int8(pdu
, 0, &offset
, ", type");
625 pprint_int64(pdu
, 0, &offset
, ", start");
626 pprint_int64(pdu
, 0, &offset
, ", length");
627 pprint_int32(pdu
, 0, &offset
, ", proc_id");
628 pprint_str(pdu
, 0, &offset
, ", client_id");
631 fprintf(llogfile
, "RGETLOCK: (");
632 pprint_int8(pdu
, 0, &offset
, "type");
633 pprint_int64(pdu
, 0, &offset
, ", start");
634 pprint_int64(pdu
, 0, &offset
, ", length");
635 pprint_int32(pdu
, 0, &offset
, ", proc_id");
636 pprint_str(pdu
, 0, &offset
, ", client_id");
639 fprintf(llogfile
, "unknown(%d): (", pdu
->id
);
643 fprintf(llogfile
, ")\n");
644 /* Flush the log message out */