opdump.c revision 1.32 1 /* $NetBSD: opdump.c,v 1.32 2010/05/21 08:46:14 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.32 2010/05/21 08:46:14 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_STATVFS",
59 "PUFFS_VFS_SYNC",
60 "PUFFS_VFS_VGET",
61 "PUFFS_VFS_FHTOVP",
62 "PUFFS_VFS_VPTOFH",
63 "PUFFS_VFS_INIT",
64 "PUFFS_VFS_DONE",
65 "PUFFS_VFS_SNAPSHOT",
66 "PUFFS_VFS_EXTATTRCTL",
67 "PUFFS_VFS_SUSPEND"
68 };
69 /* XXX! */
70 const char *vnop_revmap[] = {
71 "PUFFS_VN_LOOKUP",
72 "PUFFS_VN_CREATE",
73 "PUFFS_VN_MKNOD",
74 "PUFFS_VN_OPEN",
75 "PUFFS_VN_CLOSE",
76 "PUFFS_VN_ACCESS",
77 "PUFFS_VN_GETATTR",
78 "PUFFS_VN_SETATTR",
79 "PUFFS_VN_READ",
80 "PUFFS_VN_WRITE",
81 "PUFFS_VN_IOCTL",
82 "PUFFS_VN_FCNTL",
83 "PUFFS_VN_POLL",
84 "PUFFS_VN_KQFILTER",
85 "PUFFS_VN_REVOKE",
86 "PUFFS_VN_MMAP",
87 "PUFFS_VN_FSYNC",
88 "PUFFS_VN_SEEK",
89 "PUFFS_VN_REMOVE",
90 "PUFFS_VN_LINK",
91 "PUFFS_VN_RENAME",
92 "PUFFS_VN_MKDIR",
93 "PUFFS_VN_RMDIR",
94 "PUFFS_VN_SYMLINK",
95 "PUFFS_VN_READDIR",
96 "PUFFS_VN_READLINK",
97 "PUFFS_VN_ABORTOP",
98 "PUFFS_VN_INACTIVE",
99 "PUFFS_VN_RECLAIM",
100 "PUFFS_VN_LOCK",
101 "PUFFS_VN_UNLOCK",
102 "PUFFS_VN_BMAP",
103 "PUFFS_VN_STRATEGY",
104 "PUFFS_VN_PRINT",
105 "PUFFS_VN_ISLOCKED",
106 "PUFFS_VN_PATHCONF",
107 "PUFFS_VN_ADVLOCK",
108 "PUFFS_VN_LEASE",
109 "PUFFS_VN_WHITEOUT",
110 "PUFFS_VN_GETPAGES",
111 "PUFFS_VN_PUTPAGES",
112 "PUFFS_VN_GETEXTATTR",
113 "PUFFS_VN_LISTEXTATTR",
114 "PUFFS_VN_OPENEXTATTR",
115 "PUFFS_VN_DELETEEXTATTR",
116 "PUFFS_VN_SETEXTATTR",
117 };
118 /* XXX! */
119 const char *cacheop_revmap[] = {
120 "PUFFS_CACHE_WRITE"
121 };
122 /* XXX! */
123 const char *errnot_revmap[] = {
124 "PUFFS_ERR_MAKENODE",
125 "PUFFS_ERR_LOOKUP",
126 "PUFFS_ERR_READDIR",
127 "PUFFS_ERR_READLINK",
128 "PUFFS_ERR_READ",
129 "PUFFS_ERR_WRITE",
130 "PUFFS_ERR_VPTOFH"
131 };
132 /* XXX! */
133 const char *flush_revmap[] = {
134 "PUFFS_INVAL_NAMECACHE_NODE",
135 "PUFFS_INVAL_NAMECACHE_DIR",
136 "PUFFS_INVAL_NAMECACHE_ALL",
137 "PUFFS_INVAL_PAGECACHE_NODE_RANGE",
138 "PUFFS_FLUSH_PAGECACHE_NODE_RANGE",
139 };
140
141 void
142 puffsdump_req(struct puffs_req *preq)
143 {
144 char buf[128];
145 static struct timeval tv_prev;
146 struct timeval tv_now, tv;
147 const char **map;
148 const char *optype;
149 size_t maxhandle;
150 int opclass, isvn = 0;
151
152 printf("reqid: %" PRIu64 ", ", preq->preq_id);
153 opclass = PUFFSOP_OPCLASS(preq->preq_opclass);
154 switch (opclass) {
155 case PUFFSOP_VFS:
156 map = vfsop_revmap;
157 maxhandle = __arraycount(vfsop_revmap);
158 break;
159 case PUFFSOP_VN:
160 map = vnop_revmap;
161 maxhandle = __arraycount(vnop_revmap);
162 isvn = 1;
163 break;
164 case PUFFSOP_CACHE:
165 map = cacheop_revmap;
166 maxhandle = __arraycount(cacheop_revmap);
167 break;
168 case PUFFSOP_ERROR:
169 map = errnot_revmap;
170 maxhandle = __arraycount(errnot_revmap);
171 break;
172 case PUFFSOP_FLUSH:
173 map = flush_revmap;
174 maxhandle = __arraycount(flush_revmap);
175 break;
176 default:
177 printf("unhandled opclass %d\n", opclass);
178 return;
179 }
180
181 if (preq->preq_optype < maxhandle) {
182 optype = map[preq->preq_optype];
183 } else {
184 snprintf(buf, sizeof(buf), "UNKNOWN (%d)", preq->preq_optype);
185 optype = buf;
186 }
187
188 printf("opclass %d%s, optype: %s, "
189 "cookie: %p,\n" DINT "aux: %p, auxlen: %zu, pid: %d, lwpid: %d\n",
190 opclass, PUFFSOP_WANTREPLY(preq->preq_opclass) ? "" : " (FAF)",
191 optype, preq->preq_cookie,
192 preq->preq_buf, preq->preq_buflen,
193 preq->preq_pid, preq->preq_lid);
194
195 if (isvn) {
196 switch (preq->preq_optype) {
197 case PUFFS_VN_LOOKUP:
198 puffsdump_lookup(preq);
199 break;
200 case PUFFS_VN_READ:
201 case PUFFS_VN_WRITE:
202 puffsdump_readwrite(preq);
203 break;
204 case PUFFS_VN_OPEN:
205 puffsdump_open(preq);
206 break;
207 case PUFFS_VN_REMOVE:
208 case PUFFS_VN_RMDIR:
209 case PUFFS_VN_LINK:
210 puffsdump_targ(preq);
211 break;
212 case PUFFS_VN_READDIR:
213 puffsdump_readdir(preq);
214 break;
215 case PUFFS_VN_CREATE:
216 case PUFFS_VN_MKDIR:
217 case PUFFS_VN_MKNOD:
218 case PUFFS_VN_SYMLINK:
219 puffsdump_create(preq);
220 break;
221 case PUFFS_VN_SETATTR:
222 puffsdump_attr(preq);
223 break;
224 default:
225 break;
226 }
227 }
228
229 PU_LOCK();
230 gettimeofday(&tv_now, NULL);
231 timersub(&tv_now, &tv_prev, &tv);
232 printf(DINT "since previous call: %lld.%06ld\n",
233 (long long)tv.tv_sec, (long)tv.tv_usec);
234 gettimeofday(&tv_prev, NULL);
235 PU_UNLOCK();
236 }
237
238 void
239 puffsdump_rv(struct puffs_req *preq)
240 {
241
242 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
243 switch (preq->preq_optype) {
244 case PUFFS_VN_LOOKUP:
245 puffsdump_lookup_rv(preq);
246 break;
247 case PUFFS_VN_CREATE:
248 case PUFFS_VN_MKDIR:
249 case PUFFS_VN_MKNOD:
250 case PUFFS_VN_SYMLINK:
251 puffsdump_create_rv(preq);
252 break;
253 case PUFFS_VN_READ:
254 case PUFFS_VN_WRITE:
255 puffsdump_readwrite_rv(preq);
256 break;
257 case PUFFS_VN_READDIR:
258 puffsdump_readdir_rv(preq);
259 break;
260 case PUFFS_VN_GETATTR:
261 puffsdump_attr(preq);
262 break;
263 default:
264 break;
265 }
266 }
267
268 printf("RV reqid: %" PRIu64 ", result: %d %s\n",
269 preq->preq_id, preq->preq_rv,
270 preq->preq_rv ? strerror(preq->preq_rv) : "");
271 }
272
273 /*
274 * Slightly tedious print-routine so that we get a nice NOVAL instead
275 * of some tedious output representations for -1, especially (uint64_t)-1
276 *
277 * We use typecasting to make this work beyond time_t/dev_t size changes.
278 */
279 static void
280 dumpattr(struct vattr *vap)
281 {
282 const char * const vtypes[] = { VNODE_TYPES };
283 char buf[128];
284
285 /* XXX: better readability. and this is debug, so no cycle-sweat */
286 #define DEFAULTBUF() snprintf(buf, sizeof(buf), "NOVAL")
287
288 printf(DINT "vattr:\n");
289 printf(DINT DINT "type: %s, ", vtypes[vap->va_type]);
290
291 DEFAULTBUF();
292 if (vap->va_mode != (mode_t)PUFFS_VNOVAL)
293 snprintf(buf, sizeof(buf), "0%o", vap->va_mode);
294 printf("mode: %s, ", buf);
295
296 DEFAULTBUF();
297 if (vap->va_nlink != (nlink_t)PUFFS_VNOVAL)
298 snprintf(buf, sizeof(buf), "%d", vap->va_nlink);
299 printf("nlink: %s, ", buf);
300
301 DEFAULTBUF();
302 if (vap->va_uid != (uid_t)PUFFS_VNOVAL)
303 snprintf(buf, sizeof(buf), "%d", vap->va_uid);
304 printf("uid: %s, ", buf);
305
306 DEFAULTBUF();
307 if (vap->va_gid != (gid_t)PUFFS_VNOVAL)
308 snprintf(buf, sizeof(buf), "%d", vap->va_gid);
309 printf("gid: %s\n", buf);
310
311 DEFAULTBUF();
312 if ((unsigned long long)vap->va_fsid!=(unsigned long long)PUFFS_VNOVAL)
313 snprintf(buf, sizeof(buf), "0x%llx",
314 (unsigned long long)vap->va_fsid);
315 printf(DINT DINT "fsid: %s, ", buf);
316
317 DEFAULTBUF();
318 if (vap->va_fileid != (ino_t)PUFFS_VNOVAL)
319 snprintf(buf, sizeof(buf), "%" PRIu64, vap->va_fileid);
320 printf("ino: %s, ", buf);
321
322 DEFAULTBUF();
323 if (vap->va_size != (u_quad_t)PUFFS_VNOVAL)
324 snprintf(buf, sizeof(buf), "%" PRIu64, vap->va_size);
325 printf("size: %s, ", buf);
326
327 DEFAULTBUF();
328 if (vap->va_blocksize != (long)PUFFS_VNOVAL)
329 snprintf(buf, sizeof(buf), "%ld", vap->va_blocksize);
330 printf("bsize: %s\n", buf);
331
332 DEFAULTBUF();
333 if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL)
334 snprintf(buf, sizeof(buf), "%lld",
335 (long long)vap->va_atime.tv_sec);
336 printf(DINT DINT "a.s: %s, ", buf);
337
338 DEFAULTBUF();
339 if (vap->va_atime.tv_nsec != (long)PUFFS_VNOVAL)
340 snprintf(buf, sizeof(buf), "%ld", vap->va_atime.tv_nsec);
341 printf("a.ns: %s, ", buf);
342
343 DEFAULTBUF();
344 if (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)
345 snprintf(buf, sizeof(buf), "%lld",
346 (long long)vap->va_mtime.tv_sec);
347 printf("m.s: %s, ", buf);
348
349 DEFAULTBUF();
350 if (vap->va_mtime.tv_nsec != (long)PUFFS_VNOVAL)
351 snprintf(buf, sizeof(buf), "%ld", vap->va_mtime.tv_nsec);
352 printf("m.ns: %s\n", buf);
353
354 DEFAULTBUF();
355 if (vap->va_ctime.tv_sec != (time_t)PUFFS_VNOVAL)
356 snprintf(buf, sizeof(buf), "%lld",
357 (long long)vap->va_ctime.tv_sec);
358 printf(DINT DINT "c.s: %s, ", buf);
359
360 DEFAULTBUF();
361 if (vap->va_ctime.tv_nsec != (long)PUFFS_VNOVAL)
362 snprintf(buf, sizeof(buf), "%ld", vap->va_ctime.tv_nsec);
363 printf("c.ns: %s, ", buf);
364
365 DEFAULTBUF();
366 if (vap->va_birthtime.tv_sec != (time_t)PUFFS_VNOVAL)
367 snprintf(buf, sizeof(buf), "%lld",
368 (long long)vap->va_birthtime.tv_sec);
369 printf("b.s: %s, ", buf);
370
371 DEFAULTBUF();
372 if (vap->va_birthtime.tv_nsec != (long)PUFFS_VNOVAL)
373 snprintf(buf, sizeof(buf), "%ld", vap->va_birthtime.tv_nsec);
374 printf("b.ns: %s\n", buf);
375
376 DEFAULTBUF();
377 if (vap->va_gen != (u_long)PUFFS_VNOVAL)
378 snprintf(buf, sizeof(buf), "%lu", vap->va_gen);
379 printf(DINT DINT "gen: %s, ", buf);
380
381 DEFAULTBUF();
382 if (vap->va_flags != (u_long)PUFFS_VNOVAL)
383 snprintf(buf, sizeof(buf), "0x%lx", vap->va_flags);
384 printf("flags: %s, ", buf);
385
386 DEFAULTBUF();
387 if (vap->va_rdev != (dev_t)PUFFS_VNOVAL)
388 snprintf(buf, sizeof(buf), "0x%llx",
389 (unsigned long long)vap->va_rdev);
390 printf("rdev: %s\n", buf);
391
392 DEFAULTBUF();
393 if (vap->va_bytes != (u_quad_t)PUFFS_VNOVAL)
394 snprintf(buf, sizeof(buf), "%" PRIu64, vap->va_bytes);
395 printf(DINT DINT "bytes: %s, ", buf);
396
397 snprintf(buf, sizeof(buf), "%" PRIu64, vap->va_filerev);
398 printf("filerev: %s, ", buf);
399
400 snprintf(buf, sizeof(buf), "0x%x", vap->va_vaflags);
401 printf("vaflags: %s\n", buf);
402 }
403
404 void
405 puffsdump_cookie(puffs_cookie_t c, const char *cookiename)
406 {
407
408 printf("%scookie: at %p\n", cookiename, c);
409 }
410
411 static const char *cn_opnames[] = {
412 "LOOKUP",
413 "CREATE",
414 "DELETE",
415 "RENAME"
416 };
417
418 void
419 puffsdump_cn(struct puffs_kcn *pkcn)
420 {
421
422 printf(DINT "puffs_cn: \"%s\", len %zu op %s (flags 0x%x)\n",
423 pkcn->pkcn_name, pkcn->pkcn_namelen,
424 cn_opnames[pkcn->pkcn_nameiop & NAMEI_OPMASK],
425 pkcn->pkcn_flags);
426 }
427
428 void
429 puffsdump_lookup(struct puffs_req *preq)
430 {
431 struct puffs_vnmsg_lookup *lookup_msg = (void *)preq;
432
433 puffsdump_cn(&lookup_msg->pvnr_cn);
434 }
435
436 void
437 puffsdump_lookup_rv(struct puffs_req *preq)
438 {
439 struct puffs_vnmsg_lookup *lookup_msg = (void *)preq;
440
441 printf(DINT "new %p, type 0x%x, size 0x%"PRIu64", dev 0x%llx\n",
442 lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype,
443 lookup_msg->pvnr_size, (unsigned long long)lookup_msg->pvnr_rdev);
444 }
445
446 void
447 puffsdump_create(struct puffs_req *preq)
448 {
449 /* XXX: wrong type, but we know it fits the slot */
450 struct puffs_vnmsg_create *create_msg = (void *)preq;
451
452 dumpattr(&create_msg->pvnr_va);
453 }
454
455 void
456 puffsdump_create_rv(struct puffs_req *preq)
457 {
458 /* XXX: wrong type, but we know it fits the slot */
459 struct puffs_vnmsg_create *create_msg = (void *)preq;
460
461 printf(DINT "new %p\n", create_msg->pvnr_newnode);
462 }
463
464 void
465 puffsdump_readwrite(struct puffs_req *preq)
466 {
467 struct puffs_vnmsg_rw *rw_msg = (void *)preq;
468
469 printf(DINT "offset: %" PRId64 ", resid %zu, ioflag 0x%x\n",
470 rw_msg->pvnr_offset, rw_msg->pvnr_resid, rw_msg->pvnr_ioflag);
471 }
472
473 void
474 puffsdump_readwrite_rv(struct puffs_req *preq)
475 {
476 struct puffs_vnmsg_rw *rw_msg = (void *)preq;
477
478 printf(DINT "resid after op: %zu\n", rw_msg->pvnr_resid);
479 }
480
481 void
482 puffsdump_readdir_rv(struct puffs_req *preq)
483 {
484 struct puffs_vnmsg_readdir *readdir_msg = (void *)preq;
485
486 printf(DINT "resid after op: %zu, eofflag %d\n",
487 readdir_msg->pvnr_resid, readdir_msg->pvnr_eofflag);
488 }
489
490 void
491 puffsdump_open(struct puffs_req *preq)
492 {
493 struct puffs_vnmsg_open *open_msg = (void *)preq;
494
495 printf(DINT "mode: 0x%x\n", open_msg->pvnr_mode);
496 }
497
498 void
499 puffsdump_targ(struct puffs_req *preq)
500 {
501 struct puffs_vnmsg_remove *remove_msg = (void *)preq; /* XXX! */
502
503 printf(DINT "target cookie: %p\n", remove_msg->pvnr_cookie_targ);
504 }
505
506 void
507 puffsdump_readdir(struct puffs_req *preq)
508 {
509 struct puffs_vnmsg_readdir *readdir_msg = (void *)preq;
510
511 printf(DINT "read offset: %" PRId64 "\n", readdir_msg->pvnr_offset);
512 }
513
514 void
515 puffsdump_attr(struct puffs_req *preq)
516 {
517 struct puffs_vnmsg_setgetattr *attr_msg = (void *)preq;
518
519 dumpattr(&attr_msg->pvnr_va);
520 }
521