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