source: vendor/current/source3/modules/perfcount_test.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 9.0 KB
Line 
1/*
2 * Unix SMB/CIFS implementation.
3 * Test module for perfcounters
4 *
5 * Copyright (C) Todd Stecher 2008
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "includes.h"
22#include "smbd/smbd.h"
23
24#define PARM_PC_TEST_TYPE "pc_test"
25#define PARM_DUMPON_COUNT "count"
26#define PARM_DUMPON_COUNT_DEFAULT 50
27
28struct perfcount_test_identity {
29 uid_t uid;
30 char *user;
31 char *domain;
32};
33
34struct perfcount_test_counter {
35 int op;
36 int sub_op;
37 int ioctl;
38 uint64_t bytes_in;
39 uint64_t bytes_out;
40 int count;
41
42 struct perfcount_test_counter *next;
43 struct perfcount_test_counter *prev;
44};
45
46struct perfcount_test_context {
47
48 /* wip: identity */
49 struct perfcount_test_identity *id;
50 struct perfcount_test_counter *ops;
51};
52
53#define MAX_OP 256
54struct perfcount_test_counter *g_list[MAX_OP];
55
56int count;
57
58/* determine frequency of dumping results */
59int count_mod = 1;
60
61static void perfcount_test_add_counters(struct perfcount_test_context *ctxt)
62{
63 struct perfcount_test_counter *head;
64 struct perfcount_test_counter *ptc;
65 struct perfcount_test_counter *tmp;
66 bool found;
67
68 for (ptc = ctxt->ops; ptc != NULL; ) {
69
70 found = false;
71
72 if (ptc->op >= MAX_OP)
73 continue;
74
75 for (head = g_list[ptc->op]; head != NULL; head = head->next) {
76 if ((ptc->sub_op == head->sub_op) &&
77 (ptc->ioctl == head->ioctl)) {
78 head->bytes_in += ptc->bytes_in;
79 head->bytes_out += ptc->bytes_out;
80 head->count++;
81 tmp = ptc->next;
82 DLIST_REMOVE(ctxt->ops, ptc);
83 SAFE_FREE(ptc);
84 ptc = tmp;
85 found = true;
86 break;
87 }
88 }
89
90 /* not in global tracking list - add it */
91 if (!found) {
92 tmp = ptc->next;
93 DLIST_REMOVE(ctxt->ops, ptc);
94 ptc->count = 1;
95 DLIST_ADD(g_list[ptc->op], ptc);
96 ptc = tmp;
97 }
98 }
99
100}
101
102#if 0
103
104static void perfcount_test_dump_id(struct perfcount_test_identity *id, int lvl)
105{
106 if (!id)
107 return;
108
109 DEBUG(lvl,("uid - %d\n", id->uid));
110 DEBUG(lvl,("user - %s\n", id->user));
111 DEBUG(lvl,("domain - %s\n", id->domain));
112}
113
114#endif
115
116static const char *trans_subop_table[] = {
117 "unknown", "trans:create", "trans:ioctl", "trans:set sd",
118 "trans:change notify", "trans: rename", "trans:get sd",
119 "trans:get quota", "trans:set quota"
120};
121
122static const char *trans2_subop_table[] = {
123 "trans2:open", "trans2:find first", "trans2:find next",
124 "trans2:q fsinfo", "trans2:set fsinfo", "trans2:q path info",
125 "trans2:set pathinfo", "trans2:fs ctl", "trans2: io ctl",
126 "trans2:find notify first", "trans2:find notify next",
127 "trans2:mkdir", "trans2:sess setup", "trans2:get dfs referral",
128 "trans2:report dfs inconsistent"
129};
130
131static const char *smb_subop_name(int op, int subop)
132{
133 /* trans */
134 if (op == 0x25) {
135 if (subop >= sizeof(trans_subop_table) /
136 sizeof(trans_subop_table[0])) {
137 return "unknown";
138 }
139 return trans_subop_table[subop];
140 } else if (op == 0x32) {
141 if (subop >= sizeof(trans2_subop_table) /
142 sizeof(trans2_subop_table[0])) {
143 return "unknown";
144 }
145 return trans2_subop_table[subop];
146 }
147
148 return "unknown";
149}
150
151static void perfcount_test_dump_counter(struct perfcount_test_counter *ptc,
152 int lvl)
153{
154 DEBUG(lvl, ("OP: %s\n", smb_fn_name(ptc->op)));
155 if (ptc->sub_op > 0) {
156 DEBUG(lvl, ("SUBOP: %s\n",
157 smb_subop_name(ptc->op, ptc->sub_op)));
158 }
159
160 if (ptc->ioctl > 0) {
161 DEBUG(lvl, ("IOCTL: %d\n", ptc->ioctl));
162 }
163
164 DEBUG(lvl, ("Count: %d\n\n", ptc->count));
165}
166
167static void perfcount_test_dump_counters(void)
168{
169 int i;
170 struct perfcount_test_counter *head;
171
172 count_mod = lp_parm_int(0, PARM_PC_TEST_TYPE, PARM_DUMPON_COUNT,
173 PARM_DUMPON_COUNT_DEFAULT);
174
175 if (count_mod == 0) {
176 return;
177 }
178
179 if ((count++ % count_mod) != 0)
180 return;
181
182 DEBUG(0,("##### Dumping Performance Counters #####\n"));
183
184 for (i=0; i < MAX_OP; i++) {
185 struct perfcount_test_counter *next;
186 for (head = g_list[i]; head != NULL; head = next) {
187 next = head->next;
188 perfcount_test_dump_counter(head, 0);
189 SAFE_FREE(head);
190 }
191 g_list[i] = NULL;
192 }
193}
194
195/* operations */
196static void perfcount_test_start(struct smb_perfcount_data *pcd)
197{
198 struct perfcount_test_context *ctxt;
199 struct perfcount_test_counter *ctr;
200 /*
201 * there shouldn't already be a context here - if so,
202 * there's an unbalanced call to start / end.
203 */
204 if (pcd->context) {
205 DEBUG(0,("perfcount_test_start - starting "
206 "initialized context - %p\n", pcd));
207 return;
208 }
209
210 ctxt = SMB_MALLOC_P(struct perfcount_test_context);
211 if (!ctxt)
212 return;
213
214 ZERO_STRUCTP(ctxt);
215
216 /* create 'default' context */
217 ctr = SMB_MALLOC_P(struct perfcount_test_counter);
218 if (!ctr) {
219 SAFE_FREE(ctxt);
220 return;
221 }
222
223 ZERO_STRUCTP(ctr);
224 ctr->op = ctr->sub_op = ctr->ioctl = -1;
225 DLIST_ADD(ctxt->ops, ctr);
226
227 pcd->context = (void*)ctxt;
228}
229
230static void perfcount_test_add(struct smb_perfcount_data *pcd)
231{
232 struct perfcount_test_context *ctxt =
233 (struct perfcount_test_context *)pcd->context;
234 struct perfcount_test_counter *ctr;
235
236 if (pcd->context == NULL)
237 return;
238
239 ctr = SMB_MALLOC_P(struct perfcount_test_counter);
240 if (!ctr) {
241 return;
242 }
243
244 DLIST_ADD(ctxt->ops, ctr);
245
246}
247
248static void perfcount_test_set_op(struct smb_perfcount_data *pcd, int op)
249{
250 struct perfcount_test_context *ctxt =
251 (struct perfcount_test_context *)pcd->context;
252
253 if (pcd->context == NULL)
254 return;
255
256 ctxt->ops->op = op;
257}
258
259static void perfcount_test_set_subop(struct smb_perfcount_data *pcd, int sub_op)
260{
261 struct perfcount_test_context *ctxt =
262 (struct perfcount_test_context *)pcd->context;
263
264 if (pcd->context == NULL)
265 return;
266
267 ctxt->ops->sub_op = sub_op;
268}
269
270static void perfcount_test_set_ioctl(struct smb_perfcount_data *pcd, int io_ctl)
271{
272 struct perfcount_test_context *ctxt =
273 (struct perfcount_test_context *)pcd->context;
274 if (pcd->context == NULL)
275 return;
276
277 ctxt->ops->ioctl = io_ctl;
278}
279
280static void perfcount_test_set_msglen_in(struct smb_perfcount_data *pcd,
281 uint64_t bytes_in)
282{
283 struct perfcount_test_context *ctxt =
284 (struct perfcount_test_context *)pcd->context;
285 if (pcd->context == NULL)
286 return;
287
288 ctxt->ops->bytes_in = bytes_in;
289}
290
291static void perfcount_test_set_msglen_out(struct smb_perfcount_data *pcd,
292 uint64_t bytes_out)
293{
294 struct perfcount_test_context *ctxt =
295 (struct perfcount_test_context *)pcd->context;
296
297 if (pcd->context == NULL)
298 return;
299
300 ctxt->ops->bytes_out = bytes_out;
301}
302
303static void perfcount_test_copy_context(struct smb_perfcount_data *pcd,
304 struct smb_perfcount_data *new_pcd)
305{
306 struct perfcount_test_context *ctxt =
307 (struct perfcount_test_context *)pcd->context;
308 struct perfcount_test_context *new_ctxt;
309
310 struct perfcount_test_counter *ctr;
311 struct perfcount_test_counter *new_ctr;
312
313 if (pcd->context == NULL)
314 return;
315
316 new_ctxt = SMB_MALLOC_P(struct perfcount_test_context);
317 if (!new_ctxt) {
318 return;
319 }
320
321 memcpy(new_ctxt, ctxt, sizeof(struct perfcount_test_context));
322
323 for (ctr = ctxt->ops; ctr != NULL; ctr = ctr->next) {
324 new_ctr = SMB_MALLOC_P(struct perfcount_test_counter);
325 if (!new_ctr) {
326 goto error;
327 }
328
329 memcpy(new_ctr, ctr, sizeof(struct perfcount_test_counter));
330 new_ctr->next = NULL;
331 new_ctr->prev = NULL;
332 DLIST_ADD(new_ctxt->ops, new_ctr);
333 }
334
335 new_pcd->context = new_ctxt;
336 return;
337
338error:
339
340 for (ctr = new_ctxt->ops; ctr != NULL; ) {
341 new_ctr = ctr->next;
342 SAFE_FREE(ctr);
343 ctr = new_ctr;
344 }
345
346 SAFE_FREE(new_ctxt);
347}
348
349/*
350 * For perf reasons, its best to use some global state
351 * when an operation is deferred, we need to alloc a copy.
352 */
353static void perfcount_test_defer_op(struct smb_perfcount_data *pcd,
354 struct smb_perfcount_data *def_pcd)
355{
356 /* we don't do anything special to deferred ops */
357 return;
358}
359
360static void perfcount_test_end(struct smb_perfcount_data *pcd)
361{
362 struct perfcount_test_context *ctxt =
363 (struct perfcount_test_context *)pcd->context;
364 if (pcd->context == NULL)
365 return;
366
367 /* @bug - we don't store outbytes right for chained cmds */
368 perfcount_test_add_counters(ctxt);
369 perfcount_test_dump_counters();
370 pcd->context = NULL;
371 SAFE_FREE(ctxt);
372}
373
374
375static struct smb_perfcount_handlers perfcount_test_handlers = {
376 perfcount_test_start,
377 perfcount_test_add,
378 perfcount_test_set_op,
379 perfcount_test_set_subop,
380 perfcount_test_set_ioctl,
381 perfcount_test_set_msglen_in,
382 perfcount_test_set_msglen_out,
383 perfcount_test_copy_context,
384 perfcount_test_defer_op,
385 perfcount_test_end
386};
387
388static_decl_perfcount;
389NTSTATUS perfcount_test_init(void)
390{
391 return smb_register_perfcounter(SMB_PERFCOUNTER_INTERFACE_VERSION,
392 "pc_test", &perfcount_test_handlers);
393}
Note: See TracBrowser for help on using the repository browser.