Home | History | Annotate | Line # | Download | only in libpuffs
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