opdump.c revision 1.33 1 /* $NetBSD: opdump.c,v 1.33 2010/05/21 10:43:07 pooka Exp $ */
2
3 /*
4 * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
5 *
6 * Development of this software was supported by the
7 * Google Summer of Code program and the Ulla Tuominen Foundation.
8 * The Google SoC project was mentored by Bill Studenmund.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /* Pretty-printing helper routines for VFS/VOP request contents */
33
34 /* yes, this is pretty much a mess */
35
36 #include <sys/cdefs.h>
37 #if !defined(lint)
38 __RCSID("$NetBSD: opdump.c,v 1.33 2010/05/21 10:43:07 pooka Exp $");
39 #endif /* !lint */
40
41 #include <sys/types.h>
42 #include <sys/time.h>
43
44 #include <puffs.h>
45 #include <puffsdump.h>
46 #include <stdio.h>
47
48 #include "puffs_priv.h"
49
50 #define DINT " "
51
52 /* XXX! */
53 const char *vfsop_revmap[] = {
54 "PUFFS_VFS_MOUNT",
55 "PUFFS_VFS_START",
56 "PUFFS_VFS_UNMOUNT",
57 "PUFFS_VFS_ROOT",
58 "PUFFS_VFS_QUOTACTL",
59 "PUFFS_VFS_STATVFS",
60 "PUFFS_VFS_SYNC",
61 "PUFFS_VFS_VGET",
62 "PUFFS_VFS_FHTOVP",
63 "PUFFS_VFS_VPTOFH",
64 "PUFFS_VFS_INIT",
65 "PUFFS_VFS_DONE",
66 "PUFFS_VFS_SNAPSHOT",
67 "PUFFS_VFS_EXTATTRCTL",
68 "PUFFS_VFS_SUSPEND"
69 };
70 /* XXX! */
71 const char *vnop_revmap[] = {
72 "PUFFS_VN_LOOKUP",
73 "PUFFS_VN_CREATE",
74 "PUFFS_VN_MKNOD",
75 "PUFFS_VN_OPEN",
76 "PUFFS_VN_CLOSE",
77 "PUFFS_VN_ACCESS",
78 "PUFFS_VN_GETATTR",
79 "PUFFS_VN_SETATTR",
80 "PUFFS_VN_READ",
81 "PUFFS_VN_WRITE",
82 "PUFFS_VN_IOCTL",
83 "PUFFS_VN_FCNTL",
84 "PUFFS_VN_POLL",
85 "PUFFS_VN_KQFILTER",
86 "PUFFS_VN_REVOKE",
87 "PUFFS_VN_MMAP",
88 "PUFFS_VN_FSYNC",
89 "PUFFS_VN_SEEK",
90 "PUFFS_VN_REMOVE",
91 "PUFFS_VN_LINK",
92 "PUFFS_VN_RENAME",
93 "PUFFS_VN_MKDIR",
94 "PUFFS_VN_RMDIR",
95 "PUFFS_VN_SYMLINK",
96 "PUFFS_VN_READDIR",
97 "PUFFS_VN_READLINK",
98 "PUFFS_VN_ABORTOP",
99 "PUFFS_VN_INACTIVE",
100 "PUFFS_VN_RECLAIM",
101 "PUFFS_VN_LOCK",
102 "PUFFS_VN_UNLOCK",
103 "PUFFS_VN_BMAP",
104 "PUFFS_VN_STRATEGY",
105 "PUFFS_VN_PRINT",
106 "PUFFS_VN_ISLOCKED",
107 "PUFFS_VN_PATHCONF",
108 "PUFFS_VN_ADVLOCK",
109 "PUFFS_VN_LEASE",
110 "PUFFS_VN_WHITEOUT",
111 "PUFFS_VN_GETPAGES",
112 "PUFFS_VN_PUTPAGES",
113 "PUFFS_VN_GETEXTATTR",
114 "PUFFS_VN_LISTEXTATTR",
115 "PUFFS_VN_OPENEXTATTR",
116 "PUFFS_VN_DELETEEXTATTR",
117 "PUFFS_VN_SETEXTATTR",
118 "PUFFS_VN_CLOSEEXTATTR",
119 };
120 /* XXX! */
121 const char *cacheop_revmap[] = {
122 "PUFFS_CACHE_WRITE"
123 };
124 /* XXX! */
125 const char *errnot_revmap[] = {
126 "PUFFS_ERR_ERROR",
127 "PUFFS_ERR_MAKENODE",
128 "PUFFS_ERR_LOOKUP",
129 "PUFFS_ERR_READDIR",
130 "PUFFS_ERR_READLINK",
131 "PUFFS_ERR_READ",
132 "PUFFS_ERR_WRITE",
133 "PUFFS_ERR_VPTOFH",
134 "PUFFS_ERR_GETEXTATTR",
135 "PUFFS_ERR_LISTEXTATTR",
136 };
137 /* XXX! */
138 const char *flush_revmap[] = {
139 "PUFFS_INVAL_NAMECACHE_NODE",
140 "PUFFS_INVAL_NAMECACHE_DIR",
141 "PUFFS_INVAL_NAMECACHE_ALL",
142 "PUFFS_INVAL_PAGECACHE_NODE_RANGE",
143 "PUFFS_FLUSH_PAGECACHE_NODE_RANGE",
144 };
145
146 void
147 puffsdump_req(struct puffs_req *preq)
148 {
149 char buf[128];
150 static struct timeval tv_prev;
151 struct timeval tv_now, tv;
152 const char **map;
153 const char *optype;
154 size_t maxhandle;
155 int opclass, isvn = 0;
156
157 printf("reqid: %" PRIu64 ", ", preq->preq_id);
158 opclass = PUFFSOP_OPCLASS(preq->preq_opclass);
159 switch (opclass) {
160 case PUFFSOP_VFS:
161 map = vfsop_revmap;
162 maxhandle = __arraycount(vfsop_revmap);
163 break;
164 case PUFFSOP_VN:
165 map = vnop_revmap;
166 maxhandle = __arraycount(vnop_revmap);
167 isvn = 1;
168 break;
169 case PUFFSOP_CACHE:
170 map = cacheop_revmap;
171 maxhandle = __arraycount(cacheop_revmap);
172 break;
173 case PUFFSOP_ERROR:
174 map = errnot_revmap;
175 maxhandle = __arraycount(errnot_revmap);
176 break;
177 case PUFFSOP_FLUSH:
178 map = flush_revmap;
179 maxhandle = __arraycount(flush_revmap);
180 break;
181 default:
182 printf("unhandled opclass %d\n", opclass);
183 return;
184 }
185
186 if (preq->preq_optype < maxhandle) {
187 optype = map[preq->preq_optype];
188 } else {
189 snprintf(buf, sizeof(buf), "UNKNOWN (%d)", preq->preq_optype);
190 optype = buf;
191 }
192
193 printf("opclass %d%s, optype: %s, "
194 "cookie: %p,\n" DINT "aux: %p, auxlen: %zu, pid: %d, lwpid: %d\n",
195 opclass, PUFFSOP_WANTREPLY(preq->preq_opclass) ? "" : " (FAF)",
196 optype, preq->preq_cookie,
197 preq->preq_buf, preq->preq_buflen,
198 preq->preq_pid, preq->preq_lid);
199
200 if (isvn) {
201 switch (preq->preq_optype) {
202 case PUFFS_VN_LOOKUP:
203 puffsdump_lookup(preq);
204 break;
205 case PUFFS_VN_READ:
206 case PUFFS_VN_WRITE:
207 puffsdump_readwrite(preq);
208 break;
209 case PUFFS_VN_OPEN:
210 puffsdump_open(preq);
211 break;
212 case PUFFS_VN_REMOVE:
213 case PUFFS_VN_RMDIR:
214 case PUFFS_VN_LINK:
215 puffsdump_targ(preq);
216 break;
217 case PUFFS_VN_READDIR:
218 puffsdump_readdir(preq);
219 break;
220 case PUFFS_VN_CREATE:
221 case PUFFS_VN_MKDIR:
222 case PUFFS_VN_MKNOD:
223 case PUFFS_VN_SYMLINK:
224 puffsdump_create(preq);
225 break;
226 case PUFFS_VN_SETATTR:
227 puffsdump_attr(preq);
228 break;
229 default:
230 break;
231 }
232 }
233
234 PU_LOCK();
235 gettimeofday(&tv_now, NULL);
236 timersub(&tv_now, &tv_prev, &tv);
237 printf(DINT "since previous call: %lld.%06ld\n",
238 (long long)tv.tv_sec, (long)tv.tv_usec);
239 gettimeofday(&tv_prev, NULL);
240 PU_UNLOCK();
241 }
242
243 void
244 puffsdump_rv(struct puffs_req *preq)
245 {
246
247 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
248 switch (preq->preq_optype) {
249 case PUFFS_VN_LOOKUP:
250 puffsdump_lookup_rv(preq);
251 break;
252 case PUFFS_VN_CREATE:
253 case PUFFS_VN_MKDIR:
254 case PUFFS_VN_MKNOD:
255 case PUFFS_VN_SYMLINK:
256 puffsdump_create_rv(preq);
257 break;
258 case PUFFS_VN_READ:
259 case PUFFS_VN_WRITE:
260 puffsdump_readwrite_rv(preq);
261 break;
262 case PUFFS_VN_READDIR:
263 puffsdump_readdir_rv(preq);
264 break;
265 case PUFFS_VN_GETATTR:
266 puffsdump_attr(preq);
267 break;
268 default:
269 break;
270 }
271 }
272
273 printf("RV reqid: %" PRIu64 ", result: %d %s\n",
274 preq->preq_id, preq->preq_rv,
275 preq->preq_rv ? strerror(preq->preq_rv) : "");
276 }
277
278 /*
279 * Slightly tedious print-routine so that we get a nice NOVAL instead
280 * of some tedious output representations for -1, especially (uint64_t)-1
281 *
282 * We use typecasting to make this work beyond time_t/dev_t size changes.
283 */
284 static void
285 dumpattr(struct vattr *vap)
286 {
287 const char * const vtypes[] = { VNODE_TYPES };
288 char buf[128];
289
290 /* XXX: better readability. and this is debug, so no cycle-sweat */
291 #define DEFAULTBUF() snprintf(buf, sizeof(buf), "NOVAL")
292
293 printf(DINT "vattr:\n");
294 printf(DINT DINT "type: %s, ", vtypes[vap->va_type]);
295
296 DEFAULTBUF();
297 if (vap->va_mode != (mode_t)PUFFS_VNOVAL)
298 snprintf(buf, sizeof(buf), "0%o", vap->va_mode);
299 printf("mode: %s, ", buf);
300
301 DEFAULTBUF();
302 if (vap->va_nlink != (nlink_t)PUFFS_VNOVAL)
303 snprintf(buf, sizeof(buf), "%d", vap->va_nlink);
304 printf("nlink: %s, ", buf);
305
306 DEFAULTBUF();
307 if (vap->va_uid != (uid_t)PUFFS_VNOVAL)
308 snprintf(buf, sizeof(buf), "%d", vap->va_uid);
309 printf("uid: %s, ", buf);
310
311 DEFAULTBUF();
312 if (vap->va_gid != (gid_t)PUFFS_VNOVAL)
313 snprintf(buf, sizeof(buf), "%d", vap->va_gid);
314 printf("gid: %s\n", buf);
315
316 DEFAULTBUF();
317 if ((unsigned long long)vap->va_fsid!=(unsigned long long)PUFFS_VNOVAL)
318 snprintf(buf, sizeof(buf), "0x%llx",
319 (unsigned long long)vap->va_fsid);
320 printf(DINT DINT "fsid: %s, ", buf);
321
322 DEFAULTBUF();
323 if (vap->va_fileid != (ino_t)PUFFS_VNOVAL)
324 snprintf(buf, sizeof(buf), "%" PRIu64, vap->va_fileid);
325 printf("ino: %s, ", buf);
326
327 DEFAULTBUF();
328 if (vap->va_size != (u_quad_t)PUFFS_VNOVAL)
329 snprintf(buf, sizeof(buf), "%" PRIu64, vap->va_size);
330 printf("size: %s, ", buf);
331
332 DEFAULTBUF();
333 if (vap->va_blocksize != (long)PUFFS_VNOVAL)
334 snprintf(buf, sizeof(buf), "%ld", vap->va_blocksize);
335 printf("bsize: %s\n", buf);
336
337 DEFAULTBUF();
338 if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL)
339 snprintf(buf, sizeof(buf), "%lld",
340 (long long)vap->va_atime.tv_sec);
341 printf(DINT DINT "a.s: %s, ", buf);
342
343 DEFAULTBUF();
344 if (vap->va_atime.tv_nsec != (long)PUFFS_VNOVAL)
345 snprintf(buf, sizeof(buf), "%ld", vap->va_atime.tv_nsec);
346 printf("a.ns: %s, ", buf);
347
348 DEFAULTBUF();
349 if (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)
350 snprintf(buf, sizeof(buf), "%lld",
351 (long long)vap->va_mtime.tv_sec);
352 printf("m.s: %s, ", buf);
353
354 DEFAULTBUF();
355 if (vap->va_mtime.tv_nsec != (long)PUFFS_VNOVAL)
356 snprintf(buf, sizeof(buf), "%ld", vap->va_mtime.tv_nsec);
357 printf("m.ns: %s\n", buf);
358
359 DEFAULTBUF();
360 if (vap->va_ctime.tv_sec != (time_t)PUFFS_VNOVAL)
361 snprintf(buf, sizeof(buf), "%lld",
362 (long long)vap->va_ctime.tv_sec);
363 printf(DINT DINT "c.s: %s, ", buf);
364
365 DEFAULTBUF();
366 if (vap->va_ctime.tv_nsec != (long)PUFFS_VNOVAL)
367 snprintf(buf, sizeof(buf), "%ld", vap->va_ctime.tv_nsec);
368 printf("c.ns: %s, ", buf);
369
370 DEFAULTBUF();
371 if (vap->va_birthtime.tv_sec != (time_t)PUFFS_VNOVAL)
372 snprintf(buf, sizeof(buf), "%lld",
373 (long long)vap->va_birthtime.tv_sec);
374 printf("b.s: %s, ", buf);
375
376 DEFAULTBUF();
377 if (vap->va_birthtime.tv_nsec != (long)PUFFS_VNOVAL)
378 snprintf(buf, sizeof(buf), "%ld", vap->va_birthtime.tv_nsec);
379 printf("b.ns: %s\n", buf);
380
381 DEFAULTBUF();
382 if (vap->va_gen != (u_long)PUFFS_VNOVAL)
383 snprintf(buf, sizeof(buf), "%lu", vap->va_gen);
384 printf(DINT DINT "gen: %s, ", buf);
385
386 DEFAULTBUF();
387 if (vap->va_flags != (u_long)PUFFS_VNOVAL)
388 snprintf(buf, sizeof(buf), "0x%lx", vap->va_flags);
389 printf("flags: %s, ", buf);
390
391 DEFAULTBUF();
392 if (vap->va_rdev != (dev_t)PUFFS_VNOVAL)
393 snprintf(buf, sizeof(buf), "0x%llx",
394 (unsigned long long)vap->va_rdev);
395 printf("rdev: %s\n", buf);
396
397 DEFAULTBUF();
398 if (vap->va_bytes != (u_quad_t)PUFFS_VNOVAL)
399 snprintf(buf, sizeof(buf), "%" PRIu64, vap->va_bytes);
400 printf(DINT DINT "bytes: %s, ", buf);
401
402 snprintf(buf, sizeof(buf), "%" PRIu64, vap->va_filerev);
403 printf("filerev: %s, ", buf);
404
405 snprintf(buf, sizeof(buf), "0x%x", vap->va_vaflags);
406 printf("vaflags: %s\n", buf);
407 }
408
409 void
410 puffsdump_cookie(puffs_cookie_t c, const char *cookiename)
411 {
412
413 printf("%scookie: at %p\n", cookiename, c);
414 }
415
416 static const char *cn_opnames[] = {
417 "LOOKUP",
418 "CREATE",
419 "DELETE",
420 "RENAME"
421 };
422
423 void
424 puffsdump_cn(struct puffs_kcn *pkcn)
425 {
426
427 printf(DINT "puffs_cn: \"%s\", len %zu op %s (flags 0x%x)\n",
428 pkcn->pkcn_name, pkcn->pkcn_namelen,
429 cn_opnames[pkcn->pkcn_nameiop & NAMEI_OPMASK],
430 pkcn->pkcn_flags);
431 }
432
433 void
434 puffsdump_lookup(struct puffs_req *preq)
435 {
436 struct puffs_vnmsg_lookup *lookup_msg = (void *)preq;
437
438 puffsdump_cn(&lookup_msg->pvnr_cn);
439 }
440
441 void
442 puffsdump_lookup_rv(struct puffs_req *preq)
443 {
444 struct puffs_vnmsg_lookup *lookup_msg = (void *)preq;
445
446 printf(DINT "new %p, type 0x%x, size 0x%"PRIu64", dev 0x%llx\n",
447 lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype,
448 lookup_msg->pvnr_size, (unsigned long long)lookup_msg->pvnr_rdev);
449 }
450
451 void
452 puffsdump_create(struct puffs_req *preq)
453 {
454 /* XXX: wrong type, but we know it fits the slot */
455 struct puffs_vnmsg_create *create_msg = (void *)preq;
456
457 dumpattr(&create_msg->pvnr_va);
458 }
459
460 void
461 puffsdump_create_rv(struct puffs_req *preq)
462 {
463 /* XXX: wrong type, but we know it fits the slot */
464 struct puffs_vnmsg_create *create_msg = (void *)preq;
465
466 printf(DINT "new %p\n", create_msg->pvnr_newnode);
467 }
468
469 void
470 puffsdump_readwrite(struct puffs_req *preq)
471 {
472 struct puffs_vnmsg_rw *rw_msg = (void *)preq;
473
474 printf(DINT "offset: %" PRId64 ", resid %zu, ioflag 0x%x\n",
475 rw_msg->pvnr_offset, rw_msg->pvnr_resid, rw_msg->pvnr_ioflag);
476 }
477
478 void
479 puffsdump_readwrite_rv(struct puffs_req *preq)
480 {
481 struct puffs_vnmsg_rw *rw_msg = (void *)preq;
482
483 printf(DINT "resid after op: %zu\n", rw_msg->pvnr_resid);
484 }
485
486 void
487 puffsdump_readdir_rv(struct puffs_req *preq)
488 {
489 struct puffs_vnmsg_readdir *readdir_msg = (void *)preq;
490
491 printf(DINT "resid after op: %zu, eofflag %d\n",
492 readdir_msg->pvnr_resid, readdir_msg->pvnr_eofflag);
493 }
494
495 void
496 puffsdump_open(struct puffs_req *preq)
497 {
498 struct puffs_vnmsg_open *open_msg = (void *)preq;
499
500 printf(DINT "mode: 0x%x\n", open_msg->pvnr_mode);
501 }
502
503 void
504 puffsdump_targ(struct puffs_req *preq)
505 {
506 struct puffs_vnmsg_remove *remove_msg = (void *)preq; /* XXX! */
507
508 printf(DINT "target cookie: %p\n", remove_msg->pvnr_cookie_targ);
509 }
510
511 void
512 puffsdump_readdir(struct puffs_req *preq)
513 {
514 struct puffs_vnmsg_readdir *readdir_msg = (void *)preq;
515
516 printf(DINT "read offset: %" PRId64 "\n", readdir_msg->pvnr_offset);
517 }
518
519 void
520 puffsdump_attr(struct puffs_req *preq)
521 {
522 struct puffs_vnmsg_setgetattr *attr_msg = (void *)preq;
523
524 dumpattr(&attr_msg->pvnr_va);
525 }
526