root/source3/modules/perfcount_test.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. perfcount_test_add_counters
  2. perfcount_test_dump_id
  3. smb_subop_name
  4. perfcount_test_dump_counter
  5. perfcount_test_dump_counters
  6. perfcount_test_start
  7. perfcount_test_add
  8. perfcount_test_set_op
  9. perfcount_test_set_subop
  10. perfcount_test_set_ioctl
  11. perfcount_test_set_msglen_in
  12. perfcount_test_set_msglen_out
  13. perfcount_test_copy_context
  14. perfcount_test_defer_op
  15. perfcount_test_set_client
  16. perfcount_test_end
  17. perfcount_test_init

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

/* [<][>][^][v][top][bottom][index][help] */