1*39f030b8SPatrick Mooney /* 2*39f030b8SPatrick Mooney * This file and its contents are supplied under the terms of the 3*39f030b8SPatrick Mooney * Common Development and Distribution License ("CDDL"), version 1.0. 4*39f030b8SPatrick Mooney * You may only use this file in accordance with the terms of version 5*39f030b8SPatrick Mooney * 1.0 of the CDDL. 6*39f030b8SPatrick Mooney * 7*39f030b8SPatrick Mooney * A full copy of the text of the CDDL should have accompanied this 8*39f030b8SPatrick Mooney * source. A copy of the CDDL is also available via the Internet at 9*39f030b8SPatrick Mooney * http://www.illumos.org/license/CDDL. 10*39f030b8SPatrick Mooney */ 11*39f030b8SPatrick Mooney 12*39f030b8SPatrick Mooney /* 13*39f030b8SPatrick Mooney * Copyright 2016 Joyent, Inc. 14*39f030b8SPatrick Mooney */ 15*39f030b8SPatrick Mooney 16*39f030b8SPatrick Mooney #include "dnlc.h" 17*39f030b8SPatrick Mooney 18*39f030b8SPatrick Mooney #include <mdb/mdb_modapi.h> 19*39f030b8SPatrick Mooney #include <sys/dnlc.h> 20*39f030b8SPatrick Mooney 21*39f030b8SPatrick Mooney typedef struct dnlc_walk { 22*39f030b8SPatrick Mooney int dw_hashsz; 23*39f030b8SPatrick Mooney int dw_index; 24*39f030b8SPatrick Mooney uintptr_t dw_hash; 25*39f030b8SPatrick Mooney uintptr_t dw_head; 26*39f030b8SPatrick Mooney } dnlc_walk_t; 27*39f030b8SPatrick Mooney 28*39f030b8SPatrick Mooney 29*39f030b8SPatrick Mooney int 30*39f030b8SPatrick Mooney dnlc_walk_init(mdb_walk_state_t *wsp) 31*39f030b8SPatrick Mooney { 32*39f030b8SPatrick Mooney dnlc_walk_t *dwp; 33*39f030b8SPatrick Mooney 34*39f030b8SPatrick Mooney if (wsp->walk_addr != NULL) { 35*39f030b8SPatrick Mooney mdb_warn("dnlc walk doesn't support global walks\n"); 36*39f030b8SPatrick Mooney return (WALK_ERR); 37*39f030b8SPatrick Mooney } 38*39f030b8SPatrick Mooney 39*39f030b8SPatrick Mooney dwp = mdb_zalloc(sizeof (dnlc_walk_t), UM_SLEEP); 40*39f030b8SPatrick Mooney if (mdb_readvar(&dwp->dw_hashsz, "nc_hashsz") == -1 || 41*39f030b8SPatrick Mooney dwp->dw_hashsz <= 0) { 42*39f030b8SPatrick Mooney mdb_warn("failed to read 'nc_hashsz'\n"); 43*39f030b8SPatrick Mooney mdb_free(dwp, sizeof (dnlc_walk_t)); 44*39f030b8SPatrick Mooney return (WALK_ERR); 45*39f030b8SPatrick Mooney } 46*39f030b8SPatrick Mooney if (dwp->dw_hashsz <= 0) { 47*39f030b8SPatrick Mooney mdb_warn("invalid 'nc_hashsz' value\n"); 48*39f030b8SPatrick Mooney mdb_free(dwp, sizeof (dnlc_walk_t)); 49*39f030b8SPatrick Mooney return (WALK_ERR); 50*39f030b8SPatrick Mooney } 51*39f030b8SPatrick Mooney if (mdb_readvar(&dwp->dw_hash, "nc_hash") == -1) { 52*39f030b8SPatrick Mooney mdb_warn("failed to read 'nc_hash'\n"); 53*39f030b8SPatrick Mooney mdb_free(dwp, sizeof (dnlc_walk_t)); 54*39f030b8SPatrick Mooney return (WALK_ERR); 55*39f030b8SPatrick Mooney } 56*39f030b8SPatrick Mooney 57*39f030b8SPatrick Mooney wsp->walk_data = dwp; 58*39f030b8SPatrick Mooney return (WALK_NEXT); 59*39f030b8SPatrick Mooney } 60*39f030b8SPatrick Mooney 61*39f030b8SPatrick Mooney int 62*39f030b8SPatrick Mooney dnlc_walk_step(mdb_walk_state_t *wsp) 63*39f030b8SPatrick Mooney { 64*39f030b8SPatrick Mooney dnlc_walk_t *dwp = wsp->walk_data; 65*39f030b8SPatrick Mooney nc_hash_t hash; 66*39f030b8SPatrick Mooney uintptr_t result, addr = wsp->walk_addr; 67*39f030b8SPatrick Mooney 68*39f030b8SPatrick Mooney next: 69*39f030b8SPatrick Mooney while (addr == dwp->dw_head || addr == NULL) { 70*39f030b8SPatrick Mooney if (dwp->dw_index >= dwp->dw_hashsz) { 71*39f030b8SPatrick Mooney return (WALK_DONE); 72*39f030b8SPatrick Mooney } 73*39f030b8SPatrick Mooney dwp->dw_head = dwp->dw_hash + 74*39f030b8SPatrick Mooney (sizeof (nc_hash_t) * dwp->dw_index); 75*39f030b8SPatrick Mooney if (mdb_vread(&hash, sizeof (hash), dwp->dw_head) == -1) { 76*39f030b8SPatrick Mooney mdb_warn("failed to read nc_hash_t at %#lx", 77*39f030b8SPatrick Mooney dwp->dw_hash); 78*39f030b8SPatrick Mooney return (WALK_ERR); 79*39f030b8SPatrick Mooney } 80*39f030b8SPatrick Mooney dwp->dw_index++; 81*39f030b8SPatrick Mooney addr = (uintptr_t)hash.hash_next; 82*39f030b8SPatrick Mooney } 83*39f030b8SPatrick Mooney 84*39f030b8SPatrick Mooney result = addr; 85*39f030b8SPatrick Mooney if (mdb_vread(&addr, sizeof (uintptr_t), addr) == -1) { 86*39f030b8SPatrick Mooney /* 87*39f030b8SPatrick Mooney * This entry may have become bogus since acquiring the address 88*39f030b8SPatrick Mooney * from its neighbor. Continue on if that is the case. 89*39f030b8SPatrick Mooney */ 90*39f030b8SPatrick Mooney addr = NULL; 91*39f030b8SPatrick Mooney goto next; 92*39f030b8SPatrick Mooney } 93*39f030b8SPatrick Mooney wsp->walk_addr = addr; 94*39f030b8SPatrick Mooney 95*39f030b8SPatrick Mooney return (wsp->walk_callback(result, &result, wsp->walk_cbdata)); 96*39f030b8SPatrick Mooney } 97*39f030b8SPatrick Mooney 98*39f030b8SPatrick Mooney void 99*39f030b8SPatrick Mooney dnlc_walk_fini(mdb_walk_state_t *wsp) 100*39f030b8SPatrick Mooney { 101*39f030b8SPatrick Mooney dnlc_walk_t *dwp = wsp->walk_data; 102*39f030b8SPatrick Mooney 103*39f030b8SPatrick Mooney mdb_free(dwp, sizeof (dnlc_walk_t)); 104*39f030b8SPatrick Mooney } 105