8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / mdb / common / modules / ufs / ufs.c
blobd288718b7e4f9faf5a742d7ea3fb04e99f3cb77b
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <mdb/mdb_modapi.h>
29 #include <mdb/mdb_ks.h>
30 #include <sys/types.h>
31 #include <sys/sysmacros.h>
32 #include <sys/fs/ufs_inode.h>
33 #include <sys/fs/ufs_acl.h>
34 #include <sys/fs/ufs_fs.h>
36 #include "ufs_cmds.h"
38 typedef struct inode_walk_data {
39 int iw_inohsz;
40 int iw_inohcnt;
41 uintptr_t iw_ihead;
42 inode_t iw_inode;
43 } inode_walk_data_t;
45 static int
46 inode_walk_init(mdb_walk_state_t *wsp)
48 int inohsz;
49 uintptr_t ihead;
50 union ihead ih;
51 inode_walk_data_t *iw;
53 if (wsp->walk_addr != NULL) {
54 mdb_warn("inode_cache only supports global walks\n");
55 return (WALK_ERR);
58 if (mdb_readvar(&inohsz, "inohsz") == -1) {
59 mdb_warn("failed to read 'inohsz'");
60 return (WALK_ERR);
63 if (inohsz == 0)
64 return (WALK_DONE);
66 if (mdb_readvar(&ihead, "ihead") == -1) {
67 mdb_warn("failed to read 'ihead'");
68 return (WALK_ERR);
71 if (mdb_vread(&ih, sizeof (union ihead), ihead) == -1) {
72 mdb_warn("failed to read ihead at %p", ihead);
73 return (WALK_DONE);
76 iw = mdb_alloc(sizeof (inode_walk_data_t), UM_SLEEP);
77 iw->iw_inohsz = inohsz;
78 iw->iw_inohcnt = 0;
79 iw->iw_ihead = ihead;
81 wsp->walk_addr = (uintptr_t)ih.ih_chain[0];
82 wsp->walk_data = iw;
84 return (WALK_NEXT);
87 static int
88 inode_walk_step(mdb_walk_state_t *wsp)
90 uintptr_t addr = wsp->walk_addr;
91 inode_walk_data_t *iw = wsp->walk_data;
92 union ihead ih;
94 while (addr == iw->iw_ihead) {
95 if (++iw->iw_inohcnt >= iw->iw_inohsz)
96 return (WALK_DONE);
98 iw->iw_ihead += sizeof (union ihead);
100 if (mdb_vread(&ih, sizeof (union ihead), iw->iw_ihead) == -1) {
101 mdb_warn("failed to read ihead at %p", iw->iw_ihead);
102 return (WALK_DONE);
104 addr = (uintptr_t)ih.ih_chain[0];
107 if (mdb_vread(&iw->iw_inode, sizeof (inode_t), addr) == -1) {
108 mdb_warn("failed to read inode at %p", addr);
109 return (WALK_DONE);
112 wsp->walk_addr = (uintptr_t)iw->iw_inode.i_forw;
114 return (wsp->walk_callback(addr, (void *)(uintptr_t)iw->iw_inohcnt,
115 wsp->walk_cbdata));
118 static void
119 inode_walk_fini(mdb_walk_state_t *wsp)
121 mdb_free(wsp->walk_data, sizeof (inode_walk_data_t));
124 typedef struct inode_cbdata {
125 ino_t id_inumber;
126 dev_t id_device;
127 uintptr_t id_addr;
128 uint_t id_flags;
129 } inode_cbdata_t;
131 static int
132 inode_cache_cb(uintptr_t addr, const int inohcnt, inode_cbdata_t *id)
134 inode_t inode;
135 int inohsz;
137 if (mdb_vread(&inode, sizeof (inode), addr) == -1) {
138 mdb_warn("failed to read inode_t at %p", addr);
139 return (WALK_ERR);
142 if (id->id_device != 0 && inode.i_dev != id->id_device)
143 return (WALK_NEXT);
145 if (id->id_inumber != 0 && inode.i_number != id->id_inumber)
146 return (WALK_NEXT);
148 if (id->id_flags & DCMD_ADDRSPEC && addr != id->id_addr)
149 return (WALK_NEXT);
151 if (id->id_flags & DCMD_PIPE_OUT) {
152 mdb_printf("%p\n", addr);
153 return (WALK_NEXT);
156 mdb_printf("%0?p %10lld %15lx",
157 addr, (u_longlong_t)inode.i_number, inode.i_dev);
160 * INOHASH needs inohsz.
162 if (mdb_readvar(&inohsz, "inohsz") == -1) {
163 mdb_warn("failed to read 'inohsz'");
164 return (WALK_ERR);
168 * Is the inode in the hash chain it should be?
170 if (inohcnt == INOHASH(inode.i_number)) {
171 mdb_printf(" %5d\n", inohcnt);
172 } else {
173 mdb_printf(" %<b>%5d/%5d ??</b>\n",
174 inohcnt, INOHASH(inode.i_number));
177 return (WALK_NEXT);
180 /*ARGSUSED*/
181 static int
182 inode_cache(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
184 inode_cbdata_t id;
186 id.id_inumber = 0;
187 id.id_device = 0;
188 id.id_addr = addr;
189 id.id_flags = flags;
191 if (mdb_getopts(argc, argv,
192 'i', MDB_OPT_UINT64, &id.id_inumber,
193 'd', MDB_OPT_UINTPTR, &id.id_device, NULL) != argc)
194 return (DCMD_USAGE);
196 if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) {
197 mdb_printf("%<u>%-?s %10s %15s %5s%</u>\n",
198 "ADDR", "INUMBER", "DEVICE", "CHAIN");
201 if (mdb_walk("inode_cache", (mdb_walk_cb_t)inode_cache_cb, &id) == -1) {
202 mdb_warn("can't walk inode cache");
203 return (DCMD_ERR);
206 return (DCMD_OK);
209 /*ARGSUSED*/
210 static int
211 inode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
213 uint_t verbose = FALSE;
214 inode_t inode;
215 char buf[64];
216 char path[MAXPATHLEN];
218 static const mdb_bitmask_t i_flag_masks[] = {
219 { "UPD", IUPD, IUPD },
220 { "ACC", IACC, IACC },
221 { "MOD", IMOD, IMOD },
222 { "CHG", ICHG, ICHG },
223 { "NOACC", INOACC, INOACC },
224 { "MODTIME", IMODTIME, IMODTIME },
225 { "REF", IREF, IREF },
226 { "SYNC", ISYNC, ISYNC },
227 { "FASTSYMLNK", IFASTSYMLNK, IFASTSYMLNK },
228 { "MODACC", IMODACC, IMODACC },
229 { "ATTCHG", IATTCHG, IATTCHG },
230 { "BDWRITE", IBDWRITE, IBDWRITE },
231 { "STALE", ISTALE, ISTALE },
232 { "DEL", IDEL, IDEL },
233 { "DIRECTIO", IDIRECTIO, IDIRECTIO },
234 { "JUNKIQ", IJUNKIQ, IJUNKIQ },
235 { NULL, 0, 0 }
238 static const mdb_bitmask_t i_modetype_masks[] = {
239 { "p", IFMT, IFIFO },
240 { "c", IFMT, IFCHR },
241 { "d", IFMT, IFDIR },
242 { "b", IFMT, IFBLK },
243 { "-", IFMT, IFREG },
244 { "l", IFMT, IFLNK },
245 { "S", IFMT, IFSHAD },
246 { "s", IFMT, IFSOCK },
247 { "A", IFMT, IFATTRDIR },
248 { NULL, 0, 0 }
251 if (!(flags & DCMD_ADDRSPEC))
252 return (DCMD_USAGE);
254 if (mdb_getopts(argc, argv,
255 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc)
256 return (DCMD_USAGE);
258 if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) {
259 mdb_printf("%<u>%-?s %10s %1s %5s %8s",
260 "ADDR", "INUMBER", "T", "MODE", "SIZE");
262 if (verbose)
263 mdb_printf(" %11s %-22s%</u>\n", "DEVICE", "FLAG");
264 else
265 mdb_printf(" %-12s %-21s%</u>\n", "MTIME", "NAME");
268 if (mdb_vread(&inode, sizeof (inode), addr) == -1) {
269 mdb_warn("failed to read inode_t at %p", addr);
270 return (DCMD_ERR);
273 mdb_printf("%0?p %10lld %b %5#o %8llx",
274 addr, (u_longlong_t)inode.i_number, inode.i_mode, i_modetype_masks,
275 inode.i_mode & ~IFMT, inode.i_size);
277 if (verbose) {
279 mdb_printf(" %11lx <%b>\n",
280 inode.i_dev, inode.i_flag, i_flag_masks);
282 mdb_inc_indent(2);
284 mdb_printf("%Y\n", inode.i_mtime.tv_sec);
286 if (mdb_vnode2path((uintptr_t)inode.i_vnode, path,
287 sizeof (path)) == 0 && *path != '\0')
288 mdb_printf("%s\n", path);
289 else
290 mdb_printf("??\n");
292 mdb_dec_indent(2);
294 return (DCMD_OK);
298 * Not verbose, everything must fit into one line.
300 mdb_snprintf(buf, sizeof (buf), "%Y", inode.i_mtime.tv_sec);
301 buf[17] = '\0'; /* drop seconds */
302 if (buf[0] == '1' || buf[0] == '2')
303 mdb_printf(" %12s", buf + 5); /* drop year */
304 else
305 mdb_printf(" %-12s", "?");
307 if (mdb_vnode2path((uintptr_t)inode.i_vnode, path,
308 sizeof (path)) == 0 && *path != '\0') {
309 if (strlen(path) <= 21)
310 mdb_printf(" %-21s\n", path);
311 else
312 mdb_printf(" ...%-18s\n", path + strlen(path) - 18);
313 } else {
314 mdb_printf(" ??\n");
317 return (DCMD_OK);
320 static struct {
321 int am_offset;
322 char *am_tag;
323 } acl_map[] = {
324 { offsetof(si_t, aowner), "USER_OBJ" },
325 { offsetof(si_t, agroup), "GROUP_OBJ" },
326 { offsetof(si_t, aother), "OTHER_OBJ" },
327 { offsetof(si_t, ausers), "USER" },
328 { offsetof(si_t, agroups), "GROUP" },
329 { offsetof(si_t, downer), "DEF_USER_OBJ" },
330 { offsetof(si_t, dgroup), "DEF_GROUP_OBJ" },
331 { offsetof(si_t, dother), "DEF_OTHER_OBJ" },
332 { offsetof(si_t, dusers), "DEF_USER" },
333 { offsetof(si_t, dgroups), "DEF_GROUP" },
334 { -1, NULL }
337 static int
338 acl_walk_init(mdb_walk_state_t *wsp)
340 uintptr_t addr = wsp->walk_addr;
341 inode_t inode;
342 si_t *si;
343 ufs_ic_acl_t **aclpp;
345 if (addr == NULL) {
346 mdb_warn("acl walk needs an inode address\n");
347 return (WALK_ERR);
350 if (mdb_vread(&inode, sizeof (inode), addr) == -1) {
351 mdb_warn("failed to read inode_t at %p", addr);
352 return (WALK_ERR);
355 if (inode.i_ufs_acl == NULL)
356 return (WALK_DONE);
358 si = mdb_alloc(sizeof (si_t), UM_SLEEP);
360 if (mdb_vread(si, sizeof (si_t), (uintptr_t)inode.i_ufs_acl) == -1) {
361 mdb_warn("failed to read si_t at %p", inode.i_ufs_acl);
362 mdb_free(si, sizeof (si_t));
363 return (WALK_ERR);
366 /* LINTED - alignment */
367 aclpp = (ufs_ic_acl_t **)((caddr_t)si + acl_map[0].am_offset);
369 wsp->walk_addr = (uintptr_t)*aclpp;
370 wsp->walk_data = si;
371 wsp->walk_arg = 0;
373 return (WALK_NEXT);
376 static int
377 acl_walk_step(mdb_walk_state_t *wsp)
379 uintptr_t addr = wsp->walk_addr;
380 si_t *si = wsp->walk_data;
381 uint_t i = (uintptr_t)wsp->walk_arg;
382 ufs_ic_acl_t **aclpp;
383 ufs_ic_acl_t acl;
385 while (addr == NULL) {
386 wsp->walk_arg = (void *)(uintptr_t)++i;
388 if (acl_map[i].am_offset == -1)
389 return (WALK_DONE);
391 /* LINTED - alignment */
392 aclpp = (ufs_ic_acl_t **)((caddr_t)si + acl_map[i].am_offset);
394 addr = (uintptr_t)*aclpp;
397 if (mdb_vread(&acl, sizeof (acl), addr) == -1) {
398 mdb_warn("failed to read acl at %p", addr);
399 return (WALK_DONE);
402 wsp->walk_addr = (uintptr_t)acl.acl_ic_next;
404 return (wsp->walk_callback(addr, &acl, acl_map[i].am_tag));
407 static void
408 acl_walk_fini(mdb_walk_state_t *wsp)
410 mdb_free(wsp->walk_data, sizeof (si_t));
413 static int
414 acl_cb(uintptr_t addr, const void *arg, void *data)
416 ufs_ic_acl_t *aclp = (ufs_ic_acl_t *)arg;
418 mdb_printf("%?p %-16s %7#o %10d\n",
419 addr, (char *)data, aclp->acl_ic_perm, aclp->acl_ic_who);
421 return (WALK_NEXT);
424 /*ARGSUSED*/
425 static int
426 acl_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
428 if (!(flags & DCMD_ADDRSPEC))
429 return (DCMD_USAGE);
431 if (argc != 0)
432 return (DCMD_USAGE);
434 if (DCMD_HDRSPEC(flags)) {
435 mdb_printf("%<u>%?s %-16s %7s %10s%</u>\n",
436 "ADDR", "TAG", "PERM", "WHO");
439 if (mdb_pwalk("acl", (mdb_walk_cb_t)acl_cb, NULL, addr) == -1) {
440 mdb_warn("can't walk acls of inode %p", addr);
441 return (DCMD_ERR);
444 return (DCMD_OK);
448 static int
449 cg_walk_init(mdb_walk_state_t *wsp)
451 if (mdb_layered_walk("buf", wsp) == -1) {
452 mdb_warn("couldn't walk bio buf hash");
453 return (WALK_ERR);
456 return (WALK_NEXT);
459 static int
460 cg_walk_step(mdb_walk_state_t *wsp)
462 uintptr_t addr = (uintptr_t)((const buf_t *)wsp->walk_layer)->b_un.b_cg;
463 struct cg cg;
465 if (mdb_vread(&cg, sizeof (cg), addr) == -1) {
466 mdb_warn("failed to read cg struct at %p", addr);
467 return (WALK_ERR);
470 if (cg.cg_magic != CG_MAGIC)
471 return (WALK_NEXT);
473 return (wsp->walk_callback(addr, &cg, wsp->walk_cbdata));
476 static void
477 pbits(const uchar_t *cp, const int max, const int linelen)
479 int i, j, len;
480 char entry[40];
481 int linecnt = -1;
483 for (i = 0; i < max; i++) {
484 if (isset(cp, i)) {
485 len = mdb_snprintf(entry, sizeof (entry), "%d", i);
486 j = i;
487 while ((i + 1) < max && isset(cp, i+1))
488 i++;
489 if (i != j)
490 len += mdb_snprintf(entry + len,
491 sizeof (entry) - len, "-%d", i);
493 if (linecnt == -1) {
494 /* first entry */
495 mdb_printf("%s", entry);
496 linecnt = linelen - len;
497 } else if (linecnt - (len + 3) > 0) {
498 /* subsequent entry on same line */
499 mdb_printf(", %s", entry);
500 linecnt -= len + 2;
501 } else {
502 /* subsequent enty on new line */
503 mdb_printf(",\n%s", entry);
504 linecnt = linelen - len;
508 mdb_printf("\n");
511 /*ARGSUSED*/
512 static int
513 cg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
515 uint_t verbose = FALSE;
516 struct cg cg;
517 struct cg *cgp = &cg;
518 size_t size;
519 int i, j, cnt, off;
520 int32_t *blktot;
521 short *blks;
523 if (!(flags & DCMD_ADDRSPEC)) {
524 if (mdb_walk_dcmd("cg", "cg", argc, argv) == -1) {
525 mdb_warn("can't walk cylinder group structs");
526 return (DCMD_ERR);
528 return (DCMD_OK);
531 if (mdb_getopts(argc, argv,
532 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc)
533 return (DCMD_USAGE);
535 if (mdb_vread(cgp, sizeof (cg), addr) == -1) {
536 mdb_warn("failed to read cg struct at %p", addr);
537 return (DCMD_ERR);
540 if (!verbose) {
541 if (DCMD_HDRSPEC(flags))
542 mdb_printf("%<u>%4s %?s %10s %10s %10s %10s%</u>\n",
543 "CGX", "CG", "NDIR", "NBFREE", "NIFREE", "NFFREE");
545 mdb_printf("%4d %?p %10d %10d %10d %10d\n", cgp->cg_cgx,
546 addr, cgp->cg_cs.cs_ndir, cgp->cg_cs.cs_nbfree,
547 cgp->cg_cs.cs_nifree, cgp->cg_cs.cs_nffree);
549 return (DCMD_OK);
553 * Verbose: produce output similiar to "fstyp -v".
555 if (cgp->cg_btotoff >= cgp->cg_nextfreeoff ||
556 cgp->cg_boff >= cgp->cg_nextfreeoff ||
557 cgp->cg_iusedoff >= cgp->cg_nextfreeoff ||
558 cgp->cg_freeoff >= cgp->cg_nextfreeoff) {
559 mdb_warn("struct cg at %p seems broken\n", addr);
560 return (DCMD_ERR);
563 size = cgp->cg_nextfreeoff;
564 cgp = mdb_alloc(size, UM_SLEEP);
566 if (mdb_vread(cgp, size, addr) == -1) {
567 mdb_warn("failed to read struct cg and maps at %p", addr);
568 mdb_free(cgp, size);
569 return (DCMD_ERR);
572 mdb_printf("%<b>cg %d (%0?p)%</b>\n", cgp->cg_cgx, addr);
574 mdb_inc_indent(4);
576 mdb_printf("time:\t%Y\n", cgp->cg_time);
577 mdb_printf("ndir:\t%d\n", cgp->cg_cs.cs_ndir);
578 mdb_printf("nbfree:\t%d\n", cgp->cg_cs.cs_nbfree);
579 mdb_printf("nifree:\t%d\n", cgp->cg_cs.cs_nifree);
580 mdb_printf("nffree:\t%d\n", cgp->cg_cs.cs_nffree);
582 mdb_printf("frsum:");
583 for (i = 1; i < MAXFRAG; i++)
584 mdb_printf("\t%d", cgp->cg_frsum[i]);
585 mdb_printf("\n");
587 off = cgp->cg_iusedoff;
588 mdb_printf("used inode map (%0?p):\n", (char *)addr + off);
589 mdb_inc_indent(4);
590 pbits((uchar_t *)cgp + off, cgp->cg_niblk / sizeof (char), 72);
591 mdb_dec_indent(4);
593 off = cgp->cg_freeoff;
594 mdb_printf("free block map (%0?p):\n", (char *)addr + off);
595 mdb_inc_indent(4);
596 pbits((uchar_t *)cgp + off, cgp->cg_ndblk / sizeof (char), 72);
597 mdb_dec_indent(4);
599 /* LINTED - alignment */
600 blktot = (int32_t *)((char *)cgp + cgp->cg_btotoff);
601 /* LINTED - alignment */
602 blks = (short *)((char *)cgp + cgp->cg_boff);
603 cnt = (cgp->cg_iusedoff - cgp->cg_boff) / cgp->cg_ncyl / sizeof (short);
604 mdb_printf("free block positions:\n");
605 mdb_inc_indent(4);
607 for (i = 0; i < cgp->cg_ncyl; i++) {
608 mdb_printf("c%d:\t(%d)\t", i, blktot[i]);
609 for (j = 0; j < cnt; j++)
610 mdb_printf(" %d", blks[i*cnt + j]);
611 mdb_printf("\n");
613 mdb_dec_indent(4);
615 mdb_printf("\n");
616 mdb_dec_indent(4);
618 mdb_free(cgp, size);
620 return (DCMD_OK);
623 void
624 inode_cache_help(void)
626 mdb_printf(
627 "Displays cached inode_t. If an address, an inode number and/or a\n"
628 "device is specified, searches inode cache for inodes which match\n"
629 "the specified criteria. Prints nothing but the address, if\n"
630 "output is a pipe.\n"
631 "\n"
632 "Options:\n"
633 " -d device Filter out inodes, which reside on the specified"
634 " device.\n"
635 " -i inumber Filter out inodes with the specified inode"
636 " number.\n");
640 * MDB module linkage
642 static const mdb_dcmd_t dcmds[] = {
643 { "inode_cache", "?[-d device] [-i inumber]",
644 "search/display inodes from inode cache",
645 inode_cache, inode_cache_help },
646 { "inode", ":[-v]", "display summarized inode_t", inode },
647 { "acl", ":", "given an inode, display its in core acl's", acl_dcmd },
648 { "cg", "?[-v]", "display a summarized cylinder group structure", cg },
649 { "mapentry", ":", "dumps ufslog mapentry", mapentry_dcmd },
650 { "mapstats", ":", "dumps ufslog stats", mapstats_dcmd },
651 { NULL }
654 static const mdb_walker_t walkers[] = {
655 { "inode_cache", "walk inode cache",
656 inode_walk_init, inode_walk_step, inode_walk_fini },
657 { "acl", "given an inode, walk chains of in core acl's",
658 acl_walk_init, acl_walk_step, acl_walk_fini },
659 { "cg", "walk cg's in bio buffer cache",
660 cg_walk_init, cg_walk_step, NULL },
661 { "ufslogmap", "walk map entries in a ufs_log mt_map",
662 ufslogmap_walk_init, ufslogmap_walk_step, NULL },
663 { NULL }
666 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
668 const mdb_modinfo_t *
669 _mdb_init(void)
671 return (&modinfo);