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