Statistics
| Branch: | Revision:

root / hw / virtio-9p-debug.c @ 10b468bd

History | View | Annotate | Download (17.4 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_stat_dotl(V9fsPDU *pdu, int rx, size_t *offsetp,
182
                                                  const char *name)
183
{
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, "}");
201
}
202

    
203

    
204

    
205
static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
206
{
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;
212

    
213
    fprintf(llogfile, "%s={", name);
214

    
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;
220

    
221
    for (i = 0; i < count; i++) {
222
        char str[512];
223
        if (i) {
224
            fprintf(llogfile, ", ");
225
        }
226
        snprintf(str, sizeof(str), "[%d]", i);
227
        pprint_str(pdu, rx, &offset, str);
228
    }
229

    
230
    fprintf(llogfile, "}");
231

    
232
    *offsetp = offset;
233
}
234

    
235
static void pprint_qids(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
236
{
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;
242

    
243
    fprintf(llogfile, "%s={", name);
244

    
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;
249

    
250
    for (i = 0; i < count; i++) {
251
        char str[512];
252
        if (i) {
253
            fprintf(llogfile, ", ");
254
        }
255
        snprintf(str, sizeof(str), "[%d]", i);
256
        pprint_qid(pdu, rx, &offset, str);
257
    }
258

    
259
    fprintf(llogfile, "}");
260

    
261
    *offsetp = offset;
262
}
263

    
264
static void pprint_sg(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
265
{
266
    struct iovec *sg = get_sg(pdu, rx);
267
    unsigned int count;
268
    int i;
269

    
270
    if (rx) {
271
        count = pdu->elem.in_num;
272
    } else {
273
        count = pdu->elem.out_num;
274
    }
275

    
276
    fprintf(llogfile, "%s={", name);
277
    for (i = 0; i < count; i++) {
278
        if (i) {
279
            fprintf(llogfile, ", ");
280
        }
281
        fprintf(llogfile, "(%p, 0x%zx)", sg[i].iov_base, sg[i].iov_len);
282
    }
283
    fprintf(llogfile, "}");
284
}
285

    
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)
289
{
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;
296

    
297
    if (rx) {
298
        count = pdu->elem.in_num;
299
    } else
300
        count = pdu->elem.out_num;
301
    }
302

    
303
    BUG_ON((offset + sizeof(size)) > sg[0].iov_len);
304

    
305
    memcpy(&size, sg[0].iov_base + offset, sizeof(size));
306
    offset += sizeof(size);
307

    
308
    fprintf(llogfile, "size: %x\n", size);
309

    
310
    sg[0].iov_base += 11; /* skip header */
311
    sg[0].iov_len -= 11;
312

    
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;
321
        }
322
    }
323

    
324
    fprintf(llogfile, "%s={\"", name);
325
    fflush(llogfile);
326
    for (j = 0; j < i; j++) {
327
        if (j) {
328
            fprintf(llogfile, "\", \"");
329
            fflush(llogfile);
330
        }
331

    
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);
337
    }
338
    fprintf(llogfile, "\"}");
339

    
340
    sg[0].iov_base -= 11;
341
    sg[0].iov_len += 11;
342

    
343
}
344
#endif
345

    
346
void pprint_pdu(V9fsPDU *pdu)
347
{
348
    size_t offset = 7;
349

    
350
    if (llogfile == NULL) {
351
        llogfile = fopen("/tmp/pdu.log", "w");
352
    }
353

    
354
    BUG_ON(!llogfile);
355

    
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");
406
        }
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");
420
        }
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");
434
        }
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");
471
        }
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;
604
    }
605

    
606
    fprintf(llogfile, ")\n");
607
    /* Flush the log message out */
608
    fflush(llogfile);
609
}