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