Statistics
| Branch: | Revision:

root / hw / virtio-9p-debug.c @ c18e2f94

History | View | Annotate | Download (13.5 kB)

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

    
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
    BUG_ON(!llogfile);
331

    
332
    switch (pdu->id) {
333
    case P9_TREADDIR:
334
        fprintf(llogfile, "TREADDIR: (");
335
        pprint_int32(pdu, 0, &offset, "fid");
336
        pprint_int64(pdu, 0, &offset, ", initial offset");
337
        pprint_int32(pdu, 0, &offset, ", max count");
338
        break;
339
    case P9_RREADDIR:
340
        fprintf(llogfile, "RREADDIR: (");
341
        pprint_int32(pdu, 1, &offset, "count");
342
#ifdef DEBUG_DATA
343
        pprint_data(pdu, 1, &offset, ", data");
344
#endif
345
        break;
346
    case P9_TVERSION:
347
        fprintf(llogfile, "TVERSION: (");
348
        pprint_int32(pdu, 0, &offset, "msize");
349
        pprint_str(pdu, 0, &offset, ", version");
350
        break;
351
    case P9_RVERSION:
352
        fprintf(llogfile, "RVERSION: (");
353
        pprint_int32(pdu, 1, &offset, "msize");
354
        pprint_str(pdu, 1, &offset, ", version");
355
        break;
356
    case P9_TAUTH:
357
        fprintf(llogfile, "TAUTH: (");
358
        pprint_int32(pdu, 0, &offset, "afid");
359
        pprint_str(pdu, 0, &offset, ", uname");
360
        pprint_str(pdu, 0, &offset, ", aname");
361
        if (dotu) {
362
            pprint_int32(pdu, 0, &offset, ", n_uname");
363
        }
364
        break;
365
    case P9_RAUTH:
366
        fprintf(llogfile, "RAUTH: (");
367
        pprint_qid(pdu, 1, &offset, "qid");
368
        break;
369
    case P9_TATTACH:
370
        fprintf(llogfile, "TATTACH: (");
371
        pprint_int32(pdu, 0, &offset, "fid");
372
        pprint_int32(pdu, 0, &offset, ", afid");
373
        pprint_str(pdu, 0, &offset, ", uname");
374
        pprint_str(pdu, 0, &offset, ", aname");
375
        if (dotu) {
376
            pprint_int32(pdu, 0, &offset, ", n_uname");
377
        }
378
        break;
379
    case P9_RATTACH:
380
        fprintf(llogfile, "RATTACH: (");
381
        pprint_qid(pdu, 1, &offset, "qid");
382
        break;
383
    case P9_TERROR:
384
        fprintf(llogfile, "TERROR: (");
385
        break;
386
    case P9_RERROR:
387
        fprintf(llogfile, "RERROR: (");
388
        pprint_str(pdu, 1, &offset, "ename");
389
        if (dotu) {
390
            pprint_int32(pdu, 1, &offset, ", ecode");
391
        }
392
        break;
393
    case P9_TFLUSH:
394
        fprintf(llogfile, "TFLUSH: (");
395
        pprint_int16(pdu, 0, &offset, "oldtag");
396
        break;
397
    case P9_RFLUSH:
398
        fprintf(llogfile, "RFLUSH: (");
399
        break;
400
    case P9_TWALK:
401
        fprintf(llogfile, "TWALK: (");
402
        pprint_int32(pdu, 0, &offset, "fid");
403
        pprint_int32(pdu, 0, &offset, ", newfid");
404
        pprint_strs(pdu, 0, &offset, ", wnames");
405
        break;
406
    case P9_RWALK:
407
        fprintf(llogfile, "RWALK: (");
408
        pprint_qids(pdu, 1, &offset, "wqids");
409
        break;
410
    case P9_TOPEN:
411
        fprintf(llogfile, "TOPEN: (");
412
        pprint_int32(pdu, 0, &offset, "fid");
413
        pprint_int8(pdu, 0, &offset, ", mode");
414
        break;
415
    case P9_ROPEN:
416
        fprintf(llogfile, "ROPEN: (");
417
        pprint_qid(pdu, 1, &offset, "qid");
418
        pprint_int32(pdu, 1, &offset, ", iounit");
419
        break;
420
    case P9_TCREATE:
421
        fprintf(llogfile, "TCREATE: (");
422
        pprint_int32(pdu, 0, &offset, "fid");
423
        pprint_str(pdu, 0, &offset, ", name");
424
        pprint_int32(pdu, 0, &offset, ", perm");
425
        pprint_int8(pdu, 0, &offset, ", mode");
426
        if (dotu) {
427
            pprint_str(pdu, 0, &offset, ", extension");
428
        }
429
        break;
430
    case P9_RCREATE:
431
        fprintf(llogfile, "RCREATE: (");
432
        pprint_qid(pdu, 1, &offset, "qid");
433
        pprint_int32(pdu, 1, &offset, ", iounit");
434
        break;
435
    case P9_TREAD:
436
        fprintf(llogfile, "TREAD: (");
437
        pprint_int32(pdu, 0, &offset, "fid");
438
        pprint_int64(pdu, 0, &offset, ", offset");
439
        pprint_int32(pdu, 0, &offset, ", count");
440
        pprint_sg(pdu, 0, &offset, ", sg");
441
        break;
442
    case P9_RREAD:
443
        fprintf(llogfile, "RREAD: (");
444
        pprint_int32(pdu, 1, &offset, "count");
445
        pprint_sg(pdu, 1, &offset, ", sg");
446
        offset = 7;
447
#ifdef DEBUG_DATA
448
        pprint_data(pdu, 1, &offset, ", data");
449
#endif
450
        break;
451
    case P9_TWRITE:
452
        fprintf(llogfile, "TWRITE: (");
453
        pprint_int32(pdu, 0, &offset, "fid");
454
        pprint_int64(pdu, 0, &offset, ", offset");
455
        pprint_int32(pdu, 0, &offset, ", count");
456
        break;
457
    case P9_RWRITE:
458
        fprintf(llogfile, "RWRITE: (");
459
        pprint_int32(pdu, 1, &offset, "count");
460
        break;
461
    case P9_TCLUNK:
462
        fprintf(llogfile, "TCLUNK: (");
463
        pprint_int32(pdu, 0, &offset, "fid");
464
        break;
465
    case P9_RCLUNK:
466
        fprintf(llogfile, "RCLUNK: (");
467
        break;
468
    case P9_TREMOVE:
469
        fprintf(llogfile, "TREMOVE: (");
470
        pprint_int32(pdu, 0, &offset, "fid");
471
        break;
472
    case P9_RREMOVE:
473
        fprintf(llogfile, "RREMOVE: (");
474
        break;
475
    case P9_TSTAT:
476
        fprintf(llogfile, "TSTAT: (");
477
        pprint_int32(pdu, 0, &offset, "fid");
478
        break;
479
    case P9_RSTAT:
480
        fprintf(llogfile, "RSTAT: (");
481
        offset += 2; /* ignored */
482
        pprint_stat(pdu, 1, &offset, "stat");
483
        break;
484
    case P9_TWSTAT:
485
        fprintf(llogfile, "TWSTAT: (");
486
        pprint_int32(pdu, 0, &offset, "fid");
487
        offset += 2; /* ignored */
488
        pprint_stat(pdu, 0, &offset, ", stat");
489
        break;
490
    case P9_RWSTAT:
491
        fprintf(llogfile, "RWSTAT: (");
492
        break;
493
    default:
494
        fprintf(llogfile, "unknown(%d): (", pdu->id);
495
        break;
496
    }
497

    
498
    fprintf(llogfile, ")\n");
499
    /* Flush the log message out */
500
    fflush(llogfile);
501
}