LCOV - code coverage report
Current view: top level - source4/torture/nbench - nbench.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 6 159 3.8 %
Date: 2024-04-21 15:09:00 Functions: 1 4 25.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB torture tester - NBENCH test
       4             :    Copyright (C) Andrew Tridgell 1997-2004
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "libcli/libcli.h"
      22             : #include "torture/util.h"
      23             : #include "torture/smbtorture.h"
      24             : #include "system/filesys.h"
      25             : #include "system/locale.h"
      26             : #include "lib/util/smb_strtox.h"
      27             : 
      28             : #include "torture/nbench/proto.h"
      29             : 
      30             : int nbench_line_count = 0;
      31             : static int timelimit = 600;
      32             : static int warmup;
      33             : static const char *loadfile;
      34             : static int read_only;
      35             : 
      36             : #define ival(s) strtoll(s, NULL, 0)
      37             : 
      38             : static unsigned long nb_max_retries;
      39             : 
      40             : #define NB_RETRY(op) \
      41             :         for (n=0;n<=nb_max_retries && !op;n++) do_reconnect(&cli, tctx, client)
      42             : 
      43           0 : static void do_reconnect(struct smbcli_state **cli, struct torture_context *tctx, int client)
      44             : {
      45           0 :         int n;
      46           0 :         printf("[%d] Reconnecting client %d\n", nbench_line_count, client);
      47           0 :         for (n=0;n<nb_max_retries;n++) {
      48           0 :                 if (nb_reconnect(cli, tctx, client)) {
      49           0 :                         printf("[%d] Reconnected client %d\n", nbench_line_count, client);
      50           0 :                         return;
      51             :                 }
      52             :         }
      53           0 :         printf("[%d] Failed to reconnect client %d\n", nbench_line_count, client);
      54           0 :         nb_exit(1);
      55             : }
      56             : 
      57             : /* run a test that simulates an approximate netbench client load */
      58           0 : static bool run_netbench(struct torture_context *tctx, struct smbcli_state *cli, int client)
      59             : {
      60           0 :         int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
      61           0 :         int i;
      62           0 :         char line[1024];
      63           0 :         char *cname;
      64           0 :         FILE *f;
      65           0 :         bool correct = true;
      66           0 :         double target_rate = torture_setting_double(tctx, "targetrate", 0);
      67           0 :         int n = 0;
      68           0 :         int ret;
      69             : 
      70           0 :         if (target_rate != 0 && client == 0) {
      71           0 :                 printf("Targeting %.4f MByte/sec\n", target_rate);
      72             :         }
      73             : 
      74           0 :         nb_setup(cli, client);
      75             : 
      76           0 :         if (torture_nprocs == 1) {
      77           0 :                 if (!read_only) {
      78           0 :                         NB_RETRY(torture_setup_dir(cli, "\\clients"));
      79             :                 }
      80             :         }
      81             : 
      82           0 :         ret = asprintf(&cname, "client%d", client+1);
      83           0 :         if (ret == -1) {
      84           0 :                 return false;
      85             :         }
      86             : 
      87           0 :         f = fopen(loadfile, "r");
      88             : 
      89           0 :         if (!f) {
      90           0 :                 perror(loadfile);
      91           0 :                 return false;
      92             :         }
      93             : 
      94           0 : again:
      95           0 :         nbio_time_reset();
      96             : 
      97           0 :         while (fgets(line, sizeof(line)-1, f)) {
      98           0 :                 NTSTATUS status;
      99           0 :                 const char **params0, **params;
     100           0 :                 unsigned long int tmp;
     101           0 :                 int error = 0;
     102             : 
     103           0 :                 nbench_line_count++;
     104             : 
     105           0 :                 if ((strlen(line) > 0) && line[strlen(line)-1] == '\n') {
     106           0 :                         line[strlen(line)-1] = 0;
     107             :                 }
     108             : 
     109           0 :                 all_string_sub(line, "client1", cname, sizeof(line));
     110             : 
     111           0 :                 params = params0 = const_str_list(
     112             :                                         str_list_make_shell(NULL, line, " "));
     113           0 :                 i = str_list_length(params);
     114             : 
     115           0 :                 if (i > 0 && isdigit(params[0][0])) {
     116           0 :                         double targett = strtod(params[0], NULL);
     117           0 :                         if (target_rate != 0) {
     118           0 :                                 nbio_target_rate(target_rate);
     119             :                         } else {
     120           0 :                                 nbio_time_delay(targett);
     121             :                         }
     122           0 :                         params++;
     123           0 :                         i--;
     124           0 :                 } else if (target_rate != 0) {
     125           0 :                         nbio_target_rate(target_rate);
     126             :                 }
     127             : 
     128           0 :                 if (i < 2 || params[0][0] == '#') continue;
     129             : 
     130           0 :                 if (!strncmp(params[0],"SMB", 3)) {
     131           0 :                         printf("ERROR: You are using a dbench 1 load file\n");
     132           0 :                         nb_exit(1);
     133             :                 }
     134             : 
     135           0 :                 if (strncmp(params[i-1], "NT_STATUS_", 10) != 0 &&
     136           0 :                     strncmp(params[i-1], "0x", 2) != 0) {
     137           0 :                         printf("Badly formed status at line %d\n", nbench_line_count);
     138           0 :                         talloc_free(params);
     139           0 :                         continue;
     140             :                 }
     141             : 
     142             :                 /* accept numeric or string status codes */
     143           0 :                 if (strncmp(params[i-1], "0x", 2) == 0) {
     144           0 :                         tmp = smb_strtoul(params[i-1],
     145             :                                           NULL,
     146             :                                           16,
     147             :                                           &error,
     148             :                                           SMB_STR_STANDARD);
     149           0 :                         if (error != 0) {
     150           0 :                                 tmp = error;
     151             :                         }
     152           0 :                         status = NT_STATUS(tmp);
     153             :                 } else {
     154           0 :                         status = nt_status_string_to_code(params[i-1]);
     155             :                 }
     156             : 
     157           0 :                 DEBUG(9,("run_netbench(%d): %s %s\n", client, params[0], params[1]));
     158             : 
     159           0 :                 if (!strcmp(params[0],"NTCreateX")) {
     160           0 :                         NB_RETRY(nb_createx(params[1], ival(params[2]), ival(params[3]),
     161             :                                             ival(params[4]), status));
     162           0 :                 } else if (!strcmp(params[0],"Close")) {
     163           0 :                         NB_RETRY(nb_close(ival(params[1]), status));
     164           0 :                 } else if (!read_only && !strcmp(params[0],"Rename")) {
     165           0 :                         NB_RETRY(nb_rename(params[1], params[2], status, n>0));
     166           0 :                 } else if (!read_only && !strcmp(params[0],"Unlink")) {
     167           0 :                         NB_RETRY(nb_unlink(params[1], ival(params[2]), status, n>0));
     168           0 :                 } else if (!read_only && !strcmp(params[0],"Deltree")) {
     169           0 :                         NB_RETRY(nb_deltree(params[1], n>0));
     170           0 :                 } else if (!read_only && !strcmp(params[0],"Rmdir")) {
     171           0 :                         NB_RETRY(nb_rmdir(params[1], status, n>0));
     172           0 :                 } else if (!read_only && !strcmp(params[0],"Mkdir")) {
     173           0 :                         NB_RETRY(nb_mkdir(params[1], status, n>0));
     174           0 :                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
     175           0 :                         NB_RETRY(nb_qpathinfo(params[1], ival(params[2]), status));
     176           0 :                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
     177           0 :                         NB_RETRY(nb_qfileinfo(ival(params[1]), ival(params[2]), status));
     178           0 :                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
     179           0 :                         NB_RETRY(nb_qfsinfo(ival(params[1]), status));
     180           0 :                 } else if (!read_only && !strcmp(params[0],"SET_FILE_INFORMATION")) {
     181           0 :                         NB_RETRY(nb_sfileinfo(ival(params[1]), ival(params[2]), status));
     182           0 :                 } else if (!strcmp(params[0],"FIND_FIRST")) {
     183           0 :                         NB_RETRY(nb_findfirst(params[1], ival(params[2]),
     184             :                                               ival(params[3]), ival(params[4]), status));
     185           0 :                 } else if (!read_only && !strcmp(params[0],"WriteX")) {
     186           0 :                         NB_RETRY(nb_writex(ival(params[1]),
     187             :                                            ival(params[2]), ival(params[3]), ival(params[4]),
     188             :                                            status));
     189           0 :                 } else if (!read_only && !strcmp(params[0],"Write")) {
     190           0 :                         NB_RETRY(nb_write(ival(params[1]),
     191             :                                           ival(params[2]), ival(params[3]), ival(params[4]),
     192             :                                           status));
     193           0 :                 } else if (!strcmp(params[0],"LockX")) {
     194           0 :                         NB_RETRY(nb_lockx(ival(params[1]),
     195             :                                           ival(params[2]), ival(params[3]), status));
     196           0 :                 } else if (!strcmp(params[0],"UnlockX")) {
     197           0 :                         NB_RETRY(nb_unlockx(ival(params[1]),
     198             :                                             ival(params[2]), ival(params[3]), status));
     199           0 :                 } else if (!strcmp(params[0],"ReadX")) {
     200           0 :                         NB_RETRY(nb_readx(ival(params[1]),
     201             :                                           ival(params[2]), ival(params[3]), ival(params[4]),
     202             :                                           status));
     203           0 :                 } else if (!strcmp(params[0],"Flush")) {
     204           0 :                         NB_RETRY(nb_flush(ival(params[1]), status));
     205           0 :                 } else if (!strcmp(params[0],"Sleep")) {
     206           0 :                         nb_sleep(ival(params[1]), status);
     207             :                 } else {
     208           0 :                         printf("[%d] Unknown operation %s\n", nbench_line_count, params[0]);
     209             :                 }
     210             : 
     211           0 :                 if (n > nb_max_retries) {
     212           0 :                         printf("Maximum reconnect retries reached for op '%s'\n", params[0]);
     213           0 :                         nb_exit(1);
     214             :                 }
     215             : 
     216           0 :                 talloc_free(params0);
     217             : 
     218           0 :                 if (nb_tick()) goto done;
     219             :         }
     220             : 
     221           0 :         rewind(f);
     222           0 :         goto again;
     223             : 
     224           0 : done:
     225           0 :         fclose(f);
     226             : 
     227           0 :         if (!read_only && torture_nprocs == 1) {
     228           0 :                 smbcli_deltree(cli->tree, "\\clients");
     229             :         }
     230           0 :         if (!torture_close_connection(cli)) {
     231           0 :                 correct = false;
     232             :         }
     233             : 
     234           0 :         return correct;
     235             : }
     236             : 
     237             : 
     238             : /* run a test that simulates an approximate netbench client load */
     239           0 : bool torture_nbench(struct torture_context *torture)
     240             : {
     241           0 :         bool correct = true;
     242           0 :         int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
     243           0 :         struct smbcli_state *cli;
     244           0 :         const char *p;
     245             : 
     246           0 :         read_only = torture_setting_bool(torture, "readonly", false);
     247             : 
     248           0 :         nb_max_retries = torture_setting_int(torture, "nretries", 1);
     249             : 
     250           0 :         p = torture_setting_string(torture, "timelimit", NULL);
     251           0 :         if (p && *p) {
     252           0 :                 timelimit = atoi(p);
     253             :         }
     254             : 
     255           0 :         warmup = timelimit / 20;
     256             : 
     257           0 :         loadfile = torture_setting_string(torture, "loadfile", NULL);
     258           0 :         if (!loadfile || !*loadfile) {
     259           0 :                 loadfile = "client.txt";
     260             :         }
     261             : 
     262           0 :         if (torture_nprocs > 1) {
     263           0 :                 if (!torture_open_connection(&cli, torture, 0)) {
     264           0 :                         return false;
     265             :                 }
     266             : 
     267           0 :                 if (!read_only && !torture_setup_dir(cli, "\\clients")) {
     268           0 :                         return false;
     269             :                 }
     270             :         }
     271             : 
     272           0 :         nbio_shmem(torture_nprocs, timelimit, warmup);
     273             : 
     274           0 :         printf("Running for %d seconds with load '%s' and warmup %d secs\n",
     275             :                timelimit, loadfile, warmup);
     276             : 
     277             :         /* we need to reset SIGCHLD here as the name resolution
     278             :            library may have changed it. We rely on correct signals
     279             :            from children in the main torture code which reaps
     280             :            children. This is why smbtorture BENCH-NBENCH was sometimes
     281             :            failing */
     282           0 :         signal(SIGCHLD, SIG_DFL);
     283             : 
     284             : 
     285           0 :         signal(SIGALRM, nb_alarm);
     286           0 :         alarm(1);
     287           0 :         torture_create_procs(torture, run_netbench, &correct);
     288           0 :         alarm(0);
     289             : 
     290           0 :         if (!read_only && torture_nprocs > 1) {
     291           0 :                 smbcli_deltree(cli->tree, "\\clients");
     292             :         }
     293             : 
     294           0 :         printf("\nThroughput %g MB/sec\n", nbio_result());
     295           0 :         return correct;
     296             : }
     297             : 
     298        2354 : NTSTATUS torture_nbench_init(TALLOC_CTX *ctx)
     299             : {
     300        2354 :         struct torture_suite *suite = torture_suite_create(
     301             :                                                    ctx, "bench");
     302             : 
     303        2354 :         torture_suite_add_simple_test(suite, "nbench", torture_nbench);
     304             : 
     305        2354 :         suite->description = talloc_strdup(suite, "Benchmarks");
     306             : 
     307        2354 :         torture_register_suite(ctx, suite);
     308        2354 :         return NT_STATUS_OK;
     309             : }

Generated by: LCOV version 1.14