]> Git Repo - qemu.git/blob - hw/virtio-9p-debug.c
2fb2673d93c384ca91e9d7b0450456b1104bb417
[qemu.git] / hw / virtio-9p-debug.c
1 /*
2  * Virtio 9p PDU debug
3  *
4  * Copyright IBM, Corp. 2010
5  *
6  * Authors:
7  *  Anthony Liguori   <[email protected]>
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
20 static FILE *llogfile;
21
22 static 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
30 static 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
39 static 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
56 static 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
74 static 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
92 static 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
110 static 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
148 static 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
157 static 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
181 static 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
211 static 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
240 static 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
264 static 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
322 void 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 }
This page took 0.04226 seconds and 2 git commands to generate.