17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
287c478bd9Sstevel@tonic-gate #include <sys/buf.h>
297c478bd9Sstevel@tonic-gate #include <sys/var.h>
307c478bd9Sstevel@tonic-gate #include <vm/page.h>
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #include "bio.h"
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate typedef struct buf_walk {
357c478bd9Sstevel@tonic-gate uintptr_t bw_hbufbase; /* Base address of hbuf buckets */
367c478bd9Sstevel@tonic-gate struct hbuf *bw_hbufs; /* Snapshot of hbuf buckets */
377c478bd9Sstevel@tonic-gate size_t bw_nhbufs; /* Number of hbuf buckets */
387c478bd9Sstevel@tonic-gate size_t bw_hbufi; /* Current hbuf index */
397c478bd9Sstevel@tonic-gate buf_t *bw_bufp; /* Current buffer */
407c478bd9Sstevel@tonic-gate } buf_walk_t;
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate int
buf_walk_init(mdb_walk_state_t * wsp)437c478bd9Sstevel@tonic-gate buf_walk_init(mdb_walk_state_t *wsp)
447c478bd9Sstevel@tonic-gate {
457c478bd9Sstevel@tonic-gate struct hbuf *hbufs;
467c478bd9Sstevel@tonic-gate struct var v;
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate uintptr_t hbuf_addr;
497c478bd9Sstevel@tonic-gate size_t nbytes;
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate buf_walk_t *bwp;
527c478bd9Sstevel@tonic-gate
53*892ad162SToomas Soome if (wsp->walk_addr != 0) {
547c478bd9Sstevel@tonic-gate mdb_warn("only global buf walk supported\n");
557c478bd9Sstevel@tonic-gate return (WALK_ERR);
567c478bd9Sstevel@tonic-gate }
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate if (mdb_readvar(&v, "v") == -1) {
597c478bd9Sstevel@tonic-gate mdb_warn("failed to read var struct");
607c478bd9Sstevel@tonic-gate return (WALK_ERR);
617c478bd9Sstevel@tonic-gate }
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate if (mdb_readvar(&hbuf_addr, "hbuf") == -1) {
647c478bd9Sstevel@tonic-gate mdb_warn("failed to read hbuf pointer");
657c478bd9Sstevel@tonic-gate return (WALK_ERR);
667c478bd9Sstevel@tonic-gate }
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate nbytes = sizeof (struct hbuf) * v.v_hbuf;
697c478bd9Sstevel@tonic-gate hbufs = mdb_alloc(nbytes, UM_SLEEP);
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate if (mdb_vread(hbufs, nbytes, hbuf_addr) != nbytes) {
727c478bd9Sstevel@tonic-gate mdb_warn("failed to read hbufs");
737c478bd9Sstevel@tonic-gate mdb_free(hbufs, nbytes);
747c478bd9Sstevel@tonic-gate return (WALK_ERR);
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate bwp = mdb_alloc(sizeof (buf_walk_t), UM_SLEEP);
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate bwp->bw_hbufbase = hbuf_addr;
807c478bd9Sstevel@tonic-gate bwp->bw_hbufs = hbufs;
817c478bd9Sstevel@tonic-gate bwp->bw_nhbufs = v.v_hbuf;
827c478bd9Sstevel@tonic-gate bwp->bw_hbufi = 0;
837c478bd9Sstevel@tonic-gate bwp->bw_bufp = mdb_alloc(sizeof (buf_t), UM_SLEEP);
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)hbufs[0].b_forw;
867c478bd9Sstevel@tonic-gate wsp->walk_data = bwp;
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate return (WALK_NEXT);
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate int
buf_walk_step(mdb_walk_state_t * wsp)927c478bd9Sstevel@tonic-gate buf_walk_step(mdb_walk_state_t *wsp)
937c478bd9Sstevel@tonic-gate {
947c478bd9Sstevel@tonic-gate buf_walk_t *bwp = wsp->walk_data;
957c478bd9Sstevel@tonic-gate uintptr_t addr;
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate * If the next buf_t address we want is NULL or points back at the
997c478bd9Sstevel@tonic-gate * hbuf itself, advance to the next hash bucket. When we reach
1007c478bd9Sstevel@tonic-gate * bw_nhbufs, we're done.
1017c478bd9Sstevel@tonic-gate */
102*892ad162SToomas Soome while (wsp->walk_addr == 0 || wsp->walk_addr == (bwp->bw_hbufbase +
1037c478bd9Sstevel@tonic-gate bwp->bw_hbufi * sizeof (struct hbuf))) {
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate if (++bwp->bw_hbufi == bwp->bw_nhbufs)
1067c478bd9Sstevel@tonic-gate return (WALK_DONE);
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)
1097c478bd9Sstevel@tonic-gate bwp->bw_hbufs[bwp->bw_hbufi].b_forw;
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate * When we have a buf_t address, read the buffer and invoke our
1147c478bd9Sstevel@tonic-gate * walk callback. We keep the next buf_t address in wsp->walk_addr.
1157c478bd9Sstevel@tonic-gate */
1167c478bd9Sstevel@tonic-gate addr = wsp->walk_addr;
1177c478bd9Sstevel@tonic-gate (void) mdb_vread(bwp->bw_bufp, sizeof (buf_t), addr);
1187c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)bwp->bw_bufp->b_forw;
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate return (wsp->walk_callback(addr, bwp->bw_bufp, wsp->walk_cbdata));
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate void
buf_walk_fini(mdb_walk_state_t * wsp)1247c478bd9Sstevel@tonic-gate buf_walk_fini(mdb_walk_state_t *wsp)
1257c478bd9Sstevel@tonic-gate {
1267c478bd9Sstevel@tonic-gate buf_walk_t *bwp = wsp->walk_data;
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate mdb_free(bwp->bw_hbufs, sizeof (struct hbuf) * bwp->bw_nhbufs);
1297c478bd9Sstevel@tonic-gate mdb_free(bwp->bw_bufp, sizeof (buf_t));
1307c478bd9Sstevel@tonic-gate mdb_free(bwp, sizeof (buf_walk_t));
1317c478bd9Sstevel@tonic-gate }
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1347c478bd9Sstevel@tonic-gate int
bufpagefind(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1357c478bd9Sstevel@tonic-gate bufpagefind(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1367c478bd9Sstevel@tonic-gate {
1377c478bd9Sstevel@tonic-gate uintptr_t b_addr = addr;
1387c478bd9Sstevel@tonic-gate uintptr_t arg;
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate page_t p;
1417c478bd9Sstevel@tonic-gate buf_t b;
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate if (argc != 1)
1447c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate if (argv->a_type == MDB_TYPE_IMMEDIATE)
1477c478bd9Sstevel@tonic-gate arg = (uintptr_t)argv->a_un.a_val;
1487c478bd9Sstevel@tonic-gate else
1497c478bd9Sstevel@tonic-gate arg = (uintptr_t)mdb_strtoull(argv->a_un.a_str);
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate if (mdb_vread(&b, sizeof (buf_t), b_addr) == -1)
1527c478bd9Sstevel@tonic-gate return (DCMD_ERR);
1537c478bd9Sstevel@tonic-gate
154*892ad162SToomas Soome for (addr = (uintptr_t)b.b_pages; addr != 0;
1557c478bd9Sstevel@tonic-gate addr = (uintptr_t)p.p_next) {
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate if (addr == arg) {
1587c478bd9Sstevel@tonic-gate mdb_printf("buf %p has page %p on b_pages list\n",
1597c478bd9Sstevel@tonic-gate b_addr, addr);
1607c478bd9Sstevel@tonic-gate break;
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate if (mdb_vread(&p, sizeof (page_t), addr) == -1)
1647c478bd9Sstevel@tonic-gate return (DCMD_ERR);
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate return (DCMD_OK);
1687c478bd9Sstevel@tonic-gate }
169