1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11 /*
12 * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
13 */
14
15 #include <sys/mdb_modapi.h>
16 #include <sys/zone.h>
17 #include <nfs/nfs4_kprot.h>
18 #include <nfs/nfs4_idmap_impl.h>
19
20 #include "idmap.h"
21 #include "common.h"
22
23 /*
24 * nfs4_idmap dcmd implementation
25 */
26
27 int
nfs4_idmap_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)28 nfs4_idmap_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
29 {
30 nfsidmap_t idmap;
31 char *s;
32
33 if (argc > 0)
34 return (DCMD_USAGE);
35
36 if ((flags & DCMD_ADDRSPEC) == 0) {
37 mdb_printf("requires address of nfsidmap_t\n");
38 return (DCMD_USAGE);
39 }
40
41 if (mdb_vread(&idmap, sizeof (idmap), addr) == -1) {
42 mdb_warn("unable to read nfsidmap_t");
43 return (DCMD_ERR);
44 }
45
46 if (DCMD_HDRSPEC(flags))
47 mdb_printf("%<b>%<u>%-20s %10s %-20s%</u>%</b>\n", "TimeStamp",
48 "Number", "String");
49
50 s = mdb_alloc(idmap.id_str.utf8string_len + 1, UM_NOSLEEP | UM_GC);
51 if (s == NULL || mdb_readstr(s, idmap.id_str.utf8string_len + 1,
52 (uintptr_t)idmap.id_str.utf8string_val) == -1)
53 s = "??";
54
55 mdb_printf("%-20Y %10i %s\n", idmap.id_time, idmap.id_no, s);
56
57 return (DCMD_OK);
58 }
59
60 /*
61 * nfs4_idmap_info dcmd implementation
62 */
63
64 int
nfs4_idmap_info_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)65 nfs4_idmap_info_dcmd(uintptr_t addr, uint_t flags, int argc,
66 const mdb_arg_t *argv)
67 {
68 uint_t u2s, g2s, s2u, s2g;
69 int i;
70
71 if ((flags & DCMD_ADDRSPEC) == 0)
72 addr = 0;
73
74 u2s = g2s = s2u = s2g = argc == 0;
75
76 for (i = 0; i < argc; i++) {
77 const char *s;
78
79 if (argv[i].a_type != MDB_TYPE_STRING)
80 return (DCMD_USAGE);
81
82 s = argv[i].a_un.a_str;
83
84 if (strcmp(s, "u2s") == 0)
85 u2s = TRUE;
86 else if (strcmp(s, "g2s") == 0)
87 g2s = TRUE;
88 else if (strcmp(s, "s2u") == 0)
89 s2u = TRUE;
90 else if (strcmp(s, "s2g") == 0)
91 s2g = TRUE;
92 else
93 return (DCMD_USAGE);
94 }
95
96 if (u2s) {
97 mdb_printf("%<b>NFSv4 uid-to-string idmap cache:%</b>\n");
98 mdb_pwalk_dcmd("nfs4_u2s", "nfs4_idmap", 0, NULL, addr);
99 }
100
101 if (g2s) {
102 mdb_printf("%<b>NFSv4 gid-to-string idmap cache:%</b>\n");
103 mdb_pwalk_dcmd("nfs4_g2s", "nfs4_idmap", 0, NULL, addr);
104 }
105
106 if (s2u) {
107 mdb_printf("%<b>NFSv4 string-to-uid idmap cache:%</b>\n");
108 mdb_pwalk_dcmd("nfs4_s2u", "nfs4_idmap", 0, NULL, addr);
109 }
110
111 if (s2g) {
112 mdb_printf("%<b>NFSv4 string-to-gid idmap cache:%</b>\n");
113 mdb_pwalk_dcmd("nfs4_s2g", "nfs4_idmap", 0, NULL, addr);
114 }
115
116 return (DCMD_OK);
117 }
118
119 void
nfs4_idmap_info_help(void)120 nfs4_idmap_info_help(void)
121 {
122 mdb_printf(
123 "u2s display entries from NFSv4 uid-to-string idmap cache\n"
124 "g2s display entries from NFSv4 gid-to-string idmap cache\n"
125 "s2u display entries from NFSv4 string-to-uid idmap cache\n"
126 "s2g display entries from NFSv4 string-to-gid idmap cache\n"
127 "\nWithout arguments display entries from all caches.\n");
128 }
129
130 /*
131 * nfs4_u2s/nfs4_s2u/nfs4_g2s/nfs4_s2g walker implementation
132 */
133
134 int
nfs4_idmap_walk_init(mdb_walk_state_t * wsp)135 nfs4_idmap_walk_init(mdb_walk_state_t *wsp)
136 {
137 uintptr_t table;
138 hash_table_walk_arg_t *arg;
139 int status;
140
141 /* Use global zone by default */
142 if (wsp->walk_addr == 0) {
143 /* wsp->walk_addr = global_zone */
144 if (mdb_readvar(&wsp->walk_addr, "global_zone") == -1) {
145 mdb_warn("failed to locate global_zone");
146 return (WALK_ERR);
147 }
148 }
149
150 if (zoned_get_zsd(wsp->walk_addr, "nfsidmap_zone_key",
151 &wsp->walk_addr) != DCMD_OK) {
152 mdb_warn("failed to get zoned idmap");
153 return (WALK_ERR);
154 }
155
156 if (mdb_vread(&table, sizeof (table), wsp->walk_addr
157 + (uintptr_t)wsp->walk_arg + OFFSETOF(idmap_cache_info_t, table))
158 == -1) {
159 mdb_warn("unable to read table pointer");
160 return (WALK_ERR);
161 }
162
163 arg = mdb_alloc(sizeof (hash_table_walk_arg_t), UM_SLEEP);
164 arg->array_addr = table;
165 arg->array_len = NFSID_CACHE_ANCHORS;
166 arg->head_size = sizeof (nfsidhq_t);
167 arg->first_name = "hq_lru_forw";
168 arg->first_offset = OFFSETOF(nfsidhq_t, hq_lru_forw);
169 arg->member_type_name = "nfsidmap_t";
170 arg->member_size = sizeof (nfsidmap_t);
171 arg->next_offset = OFFSETOF(nfsidmap_t, id_forw);
172
173 wsp->walk_arg = arg;
174
175 status = hash_table_walk_init(wsp);
176 if (status != WALK_NEXT)
177 mdb_free(wsp->walk_arg, sizeof (hash_table_walk_arg_t));
178 return (status);
179 }
180
181 void
nfs4_idmap_walk_fini(mdb_walk_state_t * wsp)182 nfs4_idmap_walk_fini(mdb_walk_state_t *wsp)
183 {
184 hash_table_walk_fini(wsp);
185 mdb_free(wsp->walk_arg, sizeof (hash_table_walk_arg_t));
186 }
187