summaryrefslogtreecommitdiff
path: root/usr/src/cmd/mdb/common/modules/libmlsvc/smb_ht.c
blob: d6625ed58a1dc8f5d0472b9d108b50a1e07d610a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
 */

/*
 * walker for libsmb : smb_ht.c (hash tables)
 */

#include <mdb/mdb_modapi.h>
#include <mdb/mdb_ks.h>
#include <mdb/mdb_ctf.h>

#include <smbsrv/hash_table.h>

/* smb_ht_walk info */
struct hw_info {
	HT_HANDLE hw_handle;	/* struct ht_handle being walked */
	HT_TABLE_ENTRY hw_tblent;
	HT_ITEM hw_item;
	int hw_idx;
};

/*
 * Walker for libsmb/smb_ht.c code.  Calls the call-back function with
 * each HT_ITEM object.  Top-level is HT_HANDLE, passed to _walk_init.
 */
int
smb_ht_walk_init(mdb_walk_state_t *wsp)
{
	struct hw_info *hw;
	uintptr_t addr = wsp->walk_addr;
	HT_HANDLE *ht;

	if (addr == 0) {
		mdb_printf("require address of an HT_HANDLE\n");
		return (WALK_ERR);
	}

	/*
	 * allocate the AVL walk data
	 */
	wsp->walk_data = hw = mdb_zalloc(sizeof (*hw), UM_GC|UM_SLEEP);

	/*
	 * get an mdb copy of the HT_HANDLE being walked
	 */
	ht = &hw->hw_handle;
	if (mdb_vread(ht, sizeof (*ht), wsp->walk_addr) == -1) {
		mdb_warn("failed to read %s at %#lx",
		    "HT_HANDLE", wsp->walk_addr);
		return (WALK_ERR);
	}

	hw->hw_idx = -1;
	wsp->walk_addr = 0;
	wsp->walk_data = hw;

	return (WALK_NEXT);
}

int
smb_ht_walk_step(mdb_walk_state_t *wsp)
{
	struct hw_info *hw = wsp->walk_data;
	HT_TABLE_ENTRY *he = &hw->hw_tblent;
	HT_ITEM *hi = &hw->hw_item;
	uintptr_t he_addr;
	int rv;

	while (wsp->walk_addr == 0) {
		if (++hw->hw_idx >= hw->hw_handle.ht_table_size)
			return (WALK_DONE);
		he_addr = (uintptr_t)hw->hw_handle.ht_table +
		    (hw->hw_idx * sizeof (HT_TABLE_ENTRY));
		if (mdb_vread(he, sizeof (*he), he_addr) == -1) {
			mdb_warn("failed to read %s at %p",
			    "HT_TABLE_ENTRY", wsp->walk_addr);
			return (WALK_ERR);
		}
		wsp->walk_addr = (uintptr_t)he->he_head;
	}

	if (mdb_vread(hi, sizeof (*hi), wsp->walk_addr) == -1) {
		mdb_warn("failed to read %s at %p",
		    "HT_ITEM", wsp->walk_addr);
		return (WALK_ERR);
	}

	rv = wsp->walk_callback(wsp->walk_addr, hi,
	    wsp->walk_cbdata);

	wsp->walk_addr = (uintptr_t)hi->hi_next;

	return (rv);
}