Wed May 25 10:02:27 2022 UTC ()
lsof: don't need to keep track of the parent vnode kva, save some RAM


(tnn)
diff -r1.3 -r1.4 pkgsrc/sysutils/lsof/files/rnmt.c

cvs diff -r1.3 -r1.4 pkgsrc/sysutils/lsof/files/rnmt.c (switch to unified diff)

--- pkgsrc/sysutils/lsof/files/rnmt.c 2022/05/25 09:48:58 1.3
+++ pkgsrc/sysutils/lsof/files/rnmt.c 2022/05/25 10:02:27 1.4
@@ -1,229 +1,227 @@ @@ -1,229 +1,227 @@
1/* 1/*
2 * Copyright (C) 2022 Tobias Nygren <tnn@NetBSD.org> 2 * Copyright (C) 2022 Tobias Nygren <tnn@NetBSD.org>
3 * 3 *
4 * Permission to use, copy, modify, and/or distribute this software for any 4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted. 5 * purpose with or without fee is hereby granted.
6 * 6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14*/ 14*/
15 15
16#include "../machine.h" 16#include "../machine.h"
17 17
18#if defined(HASNCACHE) && defined(USE_LIB_RNMT) 18#if defined(HASNCACHE) && defined(USE_LIB_RNMT)
19#include <sys/rbtree.h> 19#include <sys/rbtree.h>
20#include <sys/vnode_impl.h> 20#include <sys/vnode_impl.h>
21#include <err.h> 21#include <err.h>
22 22
23#include "../lsof.h" 23#include "../lsof.h"
24 24
25/* 25/*
26 * rnmt.c - read NetBSD=>10-style red-black tree kernel name cache 26 * rnmt.c - read NetBSD=>10-style red-black tree kernel name cache
27 */ 27 */
28 28
29static int lnc_compare_nodes(void *, const void *, const void *); 29static int lnc_compare_nodes(void *, const void *, const void *);
30static int lnc_compare_key(void *, const void *, const void *); 30static int lnc_compare_key(void *, const void *, const void *);
31 31
32static rb_tree_t lnc_rbtree; 32static rb_tree_t lnc_rbtree;
33 33
34/* local name cache entry */ 34/* local name cache entry */
35struct lnc { 35struct lnc {
36 struct rb_node lnc_tree; /* red-black tree */ 36 struct rb_node lnc_tree; /* red-black tree */
37 KA_T lnc_vp; /* vnode address */ 37 KA_T lnc_vp; /* vnode address */
38 KA_T lnc_pvp; /* parent vnode address */ 
39 const struct lnc *lnc_plnc; /* parent lnc address */ 38 const struct lnc *lnc_plnc; /* parent lnc address */
40 int lnc_nlen; /* name length */ 39 int lnc_nlen; /* name length */
41 char lnc_name[NCHNAMLEN + 1]; /* name */ 40 char lnc_name[NCHNAMLEN + 1]; /* name */
42}; 41};
43 42
44static const rb_tree_ops_t lnc_rbtree_ops = { 43static const rb_tree_ops_t lnc_rbtree_ops = {
45 .rbto_compare_nodes = lnc_compare_nodes, 44 .rbto_compare_nodes = lnc_compare_nodes,
46 .rbto_compare_key = lnc_compare_key, 45 .rbto_compare_key = lnc_compare_key,
47 .rbto_node_offset = offsetof(struct lnc, lnc_tree), 46 .rbto_node_offset = offsetof(struct lnc, lnc_tree),
48 .rbto_context = NULL 47 .rbto_context = NULL
49}; 48};
50 49
51static int 50static int
52lnc_compare_nodes(void *context, const void *node1, const void *node2) 51lnc_compare_nodes(void *context, const void *node1, const void *node2)
53{ 52{
54 const struct lnc *lnc1 = node1; 53 const struct lnc *lnc1 = node1;
55 const struct lnc *lnc2 = node2; 54 const struct lnc *lnc2 = node2;
56 55
57 if (lnc1->lnc_vp < lnc2->lnc_vp) { 56 if (lnc1->lnc_vp < lnc2->lnc_vp) {
58 return -1; 57 return -1;
59 } 58 }
60 if (lnc1->lnc_vp > lnc2->lnc_vp) { 59 if (lnc1->lnc_vp > lnc2->lnc_vp) {
61 return 1; 60 return 1;
62 } 61 }
63 62
64 return 0; 63 return 0;
65} 64}
66 65
67static int 66static int
68lnc_compare_key(void *context, const void *node, const void *key) 67lnc_compare_key(void *context, const void *node, const void *key)
69{ 68{
70 const struct lnc *lnc = node; 69 const struct lnc *lnc = node;
71 const KA_T vp = (KA_T)key; 70 const KA_T vp = (KA_T)key;
72 71
73 if (lnc->lnc_vp < vp) { 72 if (lnc->lnc_vp < vp) {
74 return -1; 73 return -1;
75 } 74 }
76 if (lnc->lnc_vp > vp) { 75 if (lnc->lnc_vp > vp) {
77 return 1; 76 return 1;
78 } 77 }
79 78
80 return 0; 79 return 0;
81} 80}
82 81
83static struct lnc * 82static struct lnc *
84ncache_enter_local(KA_T vp, KA_T pvp, const struct lnc *plnc, const struct namecache *nc) 83ncache_enter_local(KA_T vp, const struct lnc *plnc, const struct namecache *nc)
85{ 84{
86 struct lnc *lnc; 85 struct lnc *lnc;
87 86
88 lnc = malloc(sizeof(*lnc)); 87 lnc = malloc(sizeof(*lnc));
89 if (!lnc) { 88 if (!lnc) {
90 errx(1, "can't allocate local name cache entry\n"); 89 errx(1, "can't allocate local name cache entry\n");
91 } 90 }
92 lnc->lnc_vp = vp; 91 lnc->lnc_vp = vp;
93 lnc->lnc_pvp = pvp; 
94 lnc->lnc_plnc = plnc; 92 lnc->lnc_plnc = plnc;
95 lnc->lnc_nlen = nc->nc_nlen; 93 lnc->lnc_nlen = nc->nc_nlen;
96 memcpy(lnc->lnc_name, nc->nc_name, lnc->lnc_nlen); 94 memcpy(lnc->lnc_name, nc->nc_name, lnc->lnc_nlen);
97 lnc->lnc_name[lnc->lnc_nlen] = 0; 95 lnc->lnc_name[lnc->lnc_nlen] = 0;
98 96
99 rb_tree_insert_node(&lnc_rbtree, lnc); 97 rb_tree_insert_node(&lnc_rbtree, lnc);
100 98
101 return lnc; 99 return lnc;
102} 100}
103 101
104static int 102static int
105sanity_check_vnode_impl(const struct vnode_impl *vi) 103sanity_check_vnode_impl(const struct vnode_impl *vi)
106{ 104{
107 if (vi->vi_vnode.v_type >= VBAD) 105 if (vi->vi_vnode.v_type >= VBAD)
108 return -1; 106 return -1;
109 107
110 return 0; 108 return 0;
111} 109}
112 110
113static int 111static int
114sanity_check_namecache(const struct namecache *nc) 112sanity_check_namecache(const struct namecache *nc)
115{ 113{
116 if (nc->nc_vp == NULL) 114 if (nc->nc_vp == NULL)
117 return -1; 115 return -1;
118 116
119 if (nc->nc_nlen > NCHNAMLEN) 117 if (nc->nc_nlen > NCHNAMLEN)
120 return -1; 118 return -1;
121 119
122 if (nc->nc_nlen == 1 && nc->nc_name[0] == '.') 120 if (nc->nc_nlen == 1 && nc->nc_name[0] == '.')
123 return -1; 121 return -1;
124 122
125 if (nc->nc_nlen == 2 && nc->nc_name[0] == '.' && nc->nc_name[1] == '.') 123 if (nc->nc_nlen == 2 && nc->nc_name[0] == '.' && nc->nc_name[1] == '.')
126 return -1; 124 return -1;
127 125
128 return 0; 126 return 0;
129} 127}
130 128
131static void 129static void
132ncache_walk(KA_T ncp, KA_T pvp, const struct lnc *plnc) 130ncache_walk(KA_T ncp, const struct lnc *plnc)
133{ 131{
134 struct l_nch *lc; 132 struct l_nch *lc;
135 static struct vnode_impl vi; 133 static struct vnode_impl vi;
136 static struct namecache nc; 134 static struct namecache nc;
137 struct lnc *lnc; 135 struct lnc *lnc;
138 KA_T vp; 136 KA_T vp;
139 KA_T left, right; 137 KA_T left, right;
140 138
141 if (kread(ncp, (char *)&nc, sizeof(nc))) { 139 if (kread(ncp, (char *)&nc, sizeof(nc))) {
142 return; 140 return;
143 } 141 }
144 vp = (KA_T)nc.nc_vp; 142 vp = (KA_T)nc.nc_vp;
145 if (kread(vp, (char *)&vi, sizeof(vi))) { 143 if (kread(vp, (char *)&vi, sizeof(vi))) {
146 vi.vi_vnode.v_type = VBAD; 144 vi.vi_vnode.v_type = VBAD;
147 } 145 }
148 left = (KA_T)nc.nc_tree.rb_nodes[0]; 146 left = (KA_T)nc.nc_tree.rb_nodes[0];
149 right = (KA_T)nc.nc_tree.rb_nodes[1]; 147 right = (KA_T)nc.nc_tree.rb_nodes[1];
150 if (sanity_check_vnode_impl(&vi) == 0 && sanity_check_namecache(&nc) == 0) { 148 if (sanity_check_vnode_impl(&vi) == 0 && sanity_check_namecache(&nc) == 0) {
151 lnc = ncache_enter_local(vp, pvp, plnc, &nc); 149 lnc = ncache_enter_local(vp, plnc, &nc);
152 if (vi.vi_vnode.v_type == VDIR && vi.vi_nc_tree.rbt_root != NULL) { 150 if (vi.vi_vnode.v_type == VDIR && vi.vi_nc_tree.rbt_root != NULL) {
153 ncache_walk((KA_T)vi.vi_nc_tree.rbt_root, ncp, lnc); 151 ncache_walk((KA_T)vi.vi_nc_tree.rbt_root, lnc);
154 } 152 }
155 } 153 }
156 if (left) 154 if (left)
157 ncache_walk(left, pvp, plnc); 155 ncache_walk(left, plnc);
158 if (right) 156 if (right)
159 ncache_walk(right, pvp, plnc); 157 ncache_walk(right, plnc);
160} 158}
161 159
162void 160void
163ncache_load() 161ncache_load()
164{ 162{
165 KA_T rootvnode_addr; 163 KA_T rootvnode_addr;
166 struct vnode_impl vi; 164 struct vnode_impl vi;
167 165
168 rootvnode_addr = (KA_T)0; 166 rootvnode_addr = (KA_T)0;
169 if (get_Nl_value("rootvnode", (struct drive_Nl *)NULL, &rootvnode_addr) < 0 167 if (get_Nl_value("rootvnode", (struct drive_Nl *)NULL, &rootvnode_addr) < 0
170 || !rootvnode_addr 168 || !rootvnode_addr
171 || kread((KA_T)rootvnode_addr, (char *)&rootvnode_addr, sizeof(rootvnode_addr)) 169 || kread((KA_T)rootvnode_addr, (char *)&rootvnode_addr, sizeof(rootvnode_addr))
172 || kread((KA_T)rootvnode_addr, (char *)&vi, sizeof(vi))) { 170 || kread((KA_T)rootvnode_addr, (char *)&vi, sizeof(vi))) {
173 errx(1, "can't read rootvnode\n"); 171 errx(1, "can't read rootvnode\n");
174 } 172 }
175 173
176 rb_tree_init(&lnc_rbtree, &lnc_rbtree_ops); 174 rb_tree_init(&lnc_rbtree, &lnc_rbtree_ops);
177 ncache_walk((KA_T)vi.vi_nc_tree.rbt_root, 0, 0); 175 ncache_walk((KA_T)vi.vi_nc_tree.rbt_root, 0);
178} 176}
179 177
180static void 178static void
181build_path(char **buf, size_t *remaining, const struct lnc *lnc) 179build_path(char **buf, size_t *remaining, const struct lnc *lnc)
182{ 180{
183 size_t len; 181 size_t len;
184 182
185 if (lnc == NULL) 183 if (lnc == NULL)
186 return; 184 return;
187 185
188 build_path(buf, remaining, lnc->lnc_plnc); 186 build_path(buf, remaining, lnc->lnc_plnc);
189 if (remaining == 0) { 187 if (remaining == 0) {
190 return; 188 return;
191 } 189 }
192 if (lnc->lnc_plnc != NULL) { 190 if (lnc->lnc_plnc != NULL) {
193 **buf = '/'; 191 **buf = '/';
194 (*buf)++; 192 (*buf)++;
195 remaining--; 193 remaining--;
196 } 194 }
197 len = lnc->lnc_nlen; 195 len = lnc->lnc_nlen;
198 if (*remaining < len) 196 if (*remaining < len)
199 len = *remaining; 197 len = *remaining;
200 memcpy(*buf, lnc->lnc_name, len); 198 memcpy(*buf, lnc->lnc_name, len);
201 *remaining -= len; 199 *remaining -= len;
202 *buf += len; 200 *buf += len;
203} 201}
204 202
205char * 203char *
206ncache_lookup(char *buf, int blen, int *fp) 204ncache_lookup(char *buf, int blen, int *fp)
207{ 205{
208 const struct lnc *lnc; 206 const struct lnc *lnc;
209 char *p; 207 char *p;
210 size_t remaining; 208 size_t remaining;
211 209
212 *fp = 0; 210 *fp = 0;
213 lnc = rb_tree_find_node(&lnc_rbtree, (void*)Lf->na); 211 lnc = rb_tree_find_node(&lnc_rbtree, (void*)Lf->na);
214 if (lnc != NULL) { 212 if (lnc != NULL) {
215 p = buf; 213 p = buf;
216 remaining = blen; 214 remaining = blen;
217 build_path(&p, &remaining, lnc); 215 build_path(&p, &remaining, lnc);
218 if (remaining == 0) { 216 if (remaining == 0) {
219 buf[blen - 1] = 0; 217 buf[blen - 1] = 0;
220 } else { 218 } else {
221 *p = 0; 219 *p = 0;
222 } 220 }
223 *fp = 1; 221 *fp = 1;
224 return buf; 222 return buf;
225 } 223 }
226 224
227 return NULL; 225 return NULL;
228} 226}
229#endif 227#endif