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