LCOV - code coverage report
Current view: top level - source4/torture/basic - misc.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 0 553 0.0 %
Date: 2024-04-21 15:09:00 Functions: 0 18 0.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB torture tester
       4             :    Copyright (C) Andrew Tridgell 1997-2003
       5             :    Copyright (C) Jelmer Vernooij 2006
       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 "lib/util/util_file.h"
      23             : #include "libcli/raw/libcliraw.h"
      24             : #include "libcli/raw/raw_proto.h"
      25             : #include "system/time.h"
      26             : #include "system/wait.h"
      27             : #include "system/filesys.h"
      28             : #include "../libcli/smb/smb_constants.h"
      29             : #include "libcli/libcli.h"
      30             : #include "lib/events/events.h"
      31             : #include "libcli/resolve/resolve.h"
      32             : #include "torture/smbtorture.h"
      33             : #include "torture/util.h"
      34             : #include "libcli/smb_composite/smb_composite.h"
      35             : #include "libcli/composite/composite.h"
      36             : #include "param/param.h"
      37             : #include "torture/basic/proto.h"
      38             : #include "lib/cmdline/cmdline.h"
      39             : 
      40           0 : static bool wait_lock(struct smbcli_state *c, int fnum, uint32_t offset, uint32_t len)
      41             : {
      42           0 :         while (NT_STATUS_IS_ERR(smbcli_lock(c->tree, fnum, offset, len, -1, WRITE_LOCK))) {
      43           0 :                 if (!check_error(__location__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return false;
      44             :         }
      45           0 :         return true;
      46             : }
      47             : 
      48             : 
      49           0 : static bool rw_torture(struct torture_context *tctx, struct smbcli_state *c)
      50             : {
      51           0 :         const char *lockfname = "\\torture.lck";
      52           0 :         char *fname;
      53           0 :         int fnum;
      54           0 :         int fnum2;
      55           0 :         pid_t pid2, pid = getpid();
      56           0 :         int i, j;
      57           0 :         uint8_t buf[1024];
      58           0 :         bool correct = true;
      59             : 
      60           0 :         fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
      61             :                          DENY_NONE);
      62           0 :         if (fnum2 == -1)
      63           0 :                 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
      64           0 :         if (fnum2 == -1) {
      65           0 :                 torture_comment(tctx, "open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree));
      66           0 :                 return false;
      67             :         }
      68             : 
      69           0 :         generate_random_buffer(buf, sizeof(buf));
      70             : 
      71           0 :         for (i=0;i<torture_numops;i++) {
      72           0 :                 unsigned int n = (unsigned int)random()%10;
      73           0 :                 int ret;
      74             : 
      75           0 :                 if (i % 10 == 0) {
      76           0 :                         if (torture_setting_bool(tctx, "progress", true)) {
      77           0 :                                 torture_comment(tctx, "%d\r", i);
      78           0 :                                 fflush(stdout);
      79             :                         }
      80             :                 }
      81           0 :                 ret = asprintf(&fname, "\\torture.%u", n);
      82           0 :                 torture_assert(tctx, ret != -1, "asprintf failed");
      83             : 
      84           0 :                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
      85           0 :                         return false;
      86             :                 }
      87             : 
      88           0 :                 fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
      89           0 :                 if (fnum == -1) {
      90           0 :                         torture_comment(tctx, "open failed (%s)\n", smbcli_errstr(c->tree));
      91           0 :                         correct = false;
      92           0 :                         break;
      93             :                 }
      94             : 
      95           0 :                 if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) {
      96           0 :                         torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c->tree));
      97           0 :                         correct = false;
      98             :                 }
      99             : 
     100           0 :                 for (j=0;j<50;j++) {
     101           0 :                         if (smbcli_write(c->tree, fnum, 0, buf, 
     102           0 :                                       sizeof(pid)+(j*sizeof(buf)), 
     103             :                                       sizeof(buf)) != sizeof(buf)) {
     104           0 :                                 torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c->tree));
     105           0 :                                 correct = false;
     106             :                         }
     107             :                 }
     108             : 
     109           0 :                 pid2 = 0;
     110             : 
     111           0 :                 if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) {
     112           0 :                         torture_comment(tctx, "read failed (%s)\n", smbcli_errstr(c->tree));
     113           0 :                         correct = false;
     114             :                 }
     115             : 
     116           0 :                 if (pid2 != pid) {
     117           0 :                         torture_comment(tctx, "data corruption!\n");
     118           0 :                         correct = false;
     119             :                 }
     120             : 
     121           0 :                 if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
     122           0 :                         torture_comment(tctx, "close failed (%s)\n", smbcli_errstr(c->tree));
     123           0 :                         correct = false;
     124             :                 }
     125             : 
     126           0 :                 if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) {
     127           0 :                         torture_comment(tctx, "unlink failed (%s)\n", smbcli_errstr(c->tree));
     128           0 :                         correct = false;
     129             :                 }
     130             : 
     131           0 :                 if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
     132           0 :                         torture_comment(tctx, "unlock failed (%s)\n", smbcli_errstr(c->tree));
     133           0 :                         correct = false;
     134             :                 }
     135           0 :                 free(fname);
     136             :         }
     137             : 
     138           0 :         smbcli_close(c->tree, fnum2);
     139           0 :         smbcli_unlink(c->tree, lockfname);
     140             : 
     141           0 :         torture_comment(tctx, "%d\n", i);
     142             : 
     143           0 :         return correct;
     144             : }
     145             : 
     146           0 : bool run_torture(struct torture_context *tctx, struct smbcli_state *cli, int dummy)
     147             : {
     148           0 :         return rw_torture(tctx, cli);
     149             : }
     150             : 
     151             : 
     152             : /*
     153             :   see how many RPC pipes we can open at once
     154             : */
     155           0 : bool run_pipe_number(struct torture_context *tctx, 
     156             :                                          struct smbcli_state *cli1)
     157             : {
     158           0 :         const char *pipe_name = "\\WKSSVC";
     159           0 :         int fnum;
     160           0 :         int num_pipes = 0;
     161             : 
     162           0 :         while(1) {
     163           0 :                 fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
     164             :                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
     165             : 
     166           0 :                 if (fnum == -1) {
     167           0 :                         torture_comment(tctx, "Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
     168           0 :                         break;
     169             :                 }
     170           0 :                 num_pipes++;
     171           0 :                 if (torture_setting_bool(tctx, "progress", true)) {
     172           0 :                         torture_comment(tctx, "%d\r", num_pipes);
     173           0 :                         fflush(stdout);
     174             :                 }
     175             :         }
     176             : 
     177           0 :         torture_comment(tctx, "pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
     178           0 :         return true;
     179             : }
     180             : 
     181             : 
     182             : 
     183             : 
     184             : /*
     185             :   open N connections to the server and just hold them open
     186             :   used for testing performance when there are N idle users
     187             :   already connected
     188             :  */
     189           0 : bool torture_holdcon(struct torture_context *tctx)
     190             : {
     191           0 :         int i;
     192           0 :         struct smbcli_state **cli;
     193           0 :         int num_dead = 0;
     194             : 
     195           0 :         torture_comment(tctx, "Opening %d connections\n", torture_numops);
     196             :         
     197           0 :         cli = malloc_array_p(struct smbcli_state *, torture_numops);
     198             : 
     199           0 :         for (i=0;i<torture_numops;i++) {
     200           0 :                 if (!torture_open_connection(&cli[i], tctx, i)) {
     201           0 :                         return false;
     202             :                 }
     203           0 :                 if (torture_setting_bool(tctx, "progress", true)) {
     204           0 :                         torture_comment(tctx, "opened %d connections\r", i+1);
     205           0 :                         fflush(stdout);
     206             :                 }
     207             :         }
     208             : 
     209           0 :         torture_comment(tctx, "\nStarting pings\n");
     210             : 
     211           0 :         while (1) {
     212           0 :                 for (i=0;i<torture_numops;i++) {
     213           0 :                         NTSTATUS status;
     214           0 :                         if (cli[i]) {
     215           0 :                                 status = smbcli_chkpath(cli[i]->tree, "\\");
     216           0 :                                 if (!NT_STATUS_IS_OK(status)) {
     217           0 :                                         torture_comment(tctx, "Connection %d is dead\n", i);
     218           0 :                                         cli[i] = NULL;
     219           0 :                                         num_dead++;
     220             :                                 }
     221           0 :                                 usleep(100);
     222             :                         }
     223             :                 }
     224             : 
     225           0 :                 if (num_dead == torture_numops) {
     226           0 :                         torture_comment(tctx, "All connections dead - finishing\n");
     227           0 :                         break;
     228             :                 }
     229             : 
     230           0 :                 torture_comment(tctx, ".");
     231           0 :                 fflush(stdout);
     232             :         }
     233             : 
     234           0 :         return true;
     235             : }
     236             : 
     237             : /*
     238             :   open a file N times on the server and just hold them open
     239             :   used for testing performance when there are N file handles
     240             :   open
     241             :  */
     242           0 : bool torture_holdopen(struct torture_context *tctx,
     243             :                       struct smbcli_state *cli)
     244             : {
     245           0 :         int i, fnum;
     246           0 :         const char *fname = "\\holdopen.dat";
     247           0 :         NTSTATUS status;
     248             : 
     249           0 :         smbcli_unlink(cli->tree, fname);
     250             : 
     251           0 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
     252           0 :         if (fnum == -1) {
     253           0 :                 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
     254           0 :                 return false;
     255             :         }
     256             : 
     257           0 :         smbcli_close(cli->tree, fnum);
     258             : 
     259           0 :         for (i=0;i<torture_numops;i++) {
     260           0 :                 union smb_open op;
     261             : 
     262           0 :                 op.generic.level = RAW_OPEN_NTCREATEX;
     263           0 :                 op.ntcreatex.in.root_fid.fnum = 0;
     264           0 :                 op.ntcreatex.in.flags = 0;
     265           0 :                 op.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
     266           0 :                 op.ntcreatex.in.create_options = 0;
     267           0 :                 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
     268           0 :                 op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
     269           0 :                 op.ntcreatex.in.alloc_size = 0;
     270           0 :                 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
     271           0 :                 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
     272           0 :                 op.ntcreatex.in.security_flags = 0;
     273           0 :                 op.ntcreatex.in.fname = fname;
     274           0 :                 status = smb_raw_open(cli->tree, tctx, &op);
     275           0 :                 if (!NT_STATUS_IS_OK(status)) {
     276           0 :                         torture_warning(tctx, "open %d failed\n", i);
     277           0 :                         continue;
     278             :                 }
     279             : 
     280           0 :                 if (torture_setting_bool(tctx, "progress", true)) {
     281           0 :                         torture_comment(tctx, "opened %d file\r", i);
     282           0 :                         fflush(stdout);
     283             :                 }
     284             :         }
     285             : 
     286           0 :         torture_comment(tctx, "\nStarting pings\n");
     287             : 
     288           0 :         while (1) {
     289           0 :                 struct smb_echo ec;
     290           0 :                 ZERO_STRUCT(ec);
     291           0 :                 status = smb_raw_echo(cli->transport, &ec);
     292           0 :                 torture_comment(tctx, ".");
     293           0 :                 fflush(stdout);
     294           0 :                 sleep(15);
     295             :         }
     296             : }
     297             : 
     298             : /*
     299             : test how many open files this server supports on the one socket
     300             : */
     301           0 : bool torture_maxfid_test(struct torture_context *tctx, struct smbcli_state *cli)
     302             : {
     303             : #define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d"
     304           0 :         char *fname;
     305           0 :         int fnums[0x11000], i;
     306           0 :         int retries=4, maxfid;
     307           0 :         bool correct = true;
     308           0 :         int ret;
     309             : 
     310           0 :         if (retries <= 0) {
     311           0 :                 torture_comment(tctx, "failed to connect\n");
     312           0 :                 return false;
     313             :         }
     314             : 
     315           0 :         if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
     316           0 :                 torture_comment(tctx, "Failed to deltree \\maxfid - %s\n",
     317             :                        smbcli_errstr(cli->tree));
     318           0 :                 return false;
     319             :         }
     320           0 :         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) {
     321           0 :                 torture_comment(tctx, "Failed to mkdir \\maxfid, error=%s\n", 
     322             :                        smbcli_errstr(cli->tree));
     323           0 :                 return false;
     324             :         }
     325             : 
     326           0 :         torture_comment(tctx, "Testing maximum number of open files\n");
     327             : 
     328           0 :         for (i=0; i<0x11000; i++) {
     329           0 :                 if (i % 1000 == 0) {
     330           0 :                         ret = asprintf(&fname, "\\maxfid\\fid%d", i/1000);
     331           0 :                         torture_assert(tctx, ret != -1, "asprintf failed");
     332           0 :                         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) {
     333           0 :                                 torture_comment(tctx, "Failed to mkdir %s, error=%s\n", 
     334             :                                        fname, smbcli_errstr(cli->tree));
     335           0 :                                 return false;
     336             :                         }
     337           0 :                         free(fname);
     338             :                 }
     339           0 :                 ret = asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
     340           0 :                 torture_assert(tctx, ret != -1, "asprintf failed");
     341           0 :                 if ((fnums[i] = smbcli_open(cli->tree, fname, 
     342             :                                         O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
     343             :                     -1) {
     344           0 :                         torture_comment(tctx, "open of %s failed (%s)\n", 
     345             :                                fname, smbcli_errstr(cli->tree));
     346           0 :                         torture_comment(tctx, "maximum fnum is %d\n", i);
     347           0 :                         break;
     348             :                 }
     349           0 :                 free(fname);
     350           0 :                 if (torture_setting_bool(tctx, "progress", true)) {
     351           0 :                         torture_comment(tctx, "%6d\r", i);
     352           0 :                         fflush(stdout);
     353             :                 }
     354             :         }
     355           0 :         torture_comment(tctx, "%6d\n", i);
     356             : 
     357           0 :         maxfid = i;
     358             : 
     359           0 :         torture_comment(tctx, "cleaning up\n");
     360           0 :         for (i=0;i<maxfid;i++) {
     361           0 :                 ret = asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
     362           0 :                 torture_assert(tctx, ret != -1, "asprintf failed");
     363           0 :                 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) {
     364           0 :                         torture_comment(tctx, "Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree));
     365             :                 }
     366           0 :                 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
     367           0 :                         torture_comment(tctx, "unlink of %s failed (%s)\n", 
     368             :                                fname, smbcli_errstr(cli->tree));
     369           0 :                         correct = false;
     370             :                 }
     371           0 :                 free(fname);
     372             : 
     373           0 :                 if (torture_setting_bool(tctx, "progress", true)) {
     374           0 :                         torture_comment(tctx, "%6d\r", i);
     375           0 :                         fflush(stdout);
     376             :                 }
     377             :         }
     378           0 :         torture_comment(tctx, "%6d\n", 0);
     379             : 
     380           0 :         if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
     381           0 :                 torture_comment(tctx, "Failed to deltree \\maxfid - %s\n",
     382             :                        smbcli_errstr(cli->tree));
     383           0 :                 return false;
     384             :         }
     385             : 
     386           0 :         torture_comment(tctx, "maxfid test finished\n");
     387             : 
     388           0 :         return correct;
     389             : #undef MAXFID_TEMPLATE
     390             : }
     391             : 
     392             : 
     393             : 
     394             : /*
     395             :   sees what IOCTLs are supported
     396             :  */
     397           0 : bool torture_ioctl_test(struct torture_context *tctx, 
     398             :                                                 struct smbcli_state *cli)
     399             : {
     400           0 :         uint16_t device, function;
     401           0 :         int fnum;
     402           0 :         const char *fname = "\\ioctl.dat";
     403           0 :         NTSTATUS status;
     404           0 :         union smb_ioctl parms;
     405           0 :         TALLOC_CTX *mem_ctx;
     406             : 
     407           0 :         mem_ctx = talloc_named_const(tctx, 0, "ioctl_test");
     408             : 
     409           0 :         smbcli_unlink(cli->tree, fname);
     410             : 
     411           0 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
     412           0 :         if (fnum == -1) {
     413           0 :                 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
     414           0 :                 return false;
     415             :         }
     416             : 
     417           0 :         parms.ioctl.level = RAW_IOCTL_IOCTL;
     418           0 :         parms.ioctl.in.file.fnum = fnum;
     419           0 :         parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
     420           0 :         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
     421           0 :         torture_comment(tctx, "ioctl job info: %s\n", smbcli_errstr(cli->tree));
     422             : 
     423           0 :         for (device=0;device<0x100;device++) {
     424           0 :                 torture_comment(tctx, "Testing device=0x%x\n", device);
     425           0 :                 for (function=0;function<0x100;function++) {
     426           0 :                         parms.ioctl.in.request = (device << 16) | function;
     427           0 :                         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
     428             : 
     429           0 :                         if (NT_STATUS_IS_OK(status)) {
     430           0 :                                 torture_comment(tctx, "ioctl device=0x%x function=0x%x OK : %d bytes\n", 
     431           0 :                                         device, function, (int)parms.ioctl.out.blob.length);
     432             :                         }
     433             :                 }
     434             :         }
     435             : 
     436           0 :         return true;
     437             : }
     438             : 
     439             : static void benchrw_callback(struct smbcli_request *req);
     440             : enum benchrw_stage {
     441             :         START,
     442             :         OPEN_CONNECTION,
     443             :         CLEANUP_TESTDIR,
     444             :         MK_TESTDIR,
     445             :         OPEN_FILE,
     446             :         INITIAL_WRITE,
     447             :         READ_WRITE_DATA,
     448             :         MAX_OPS_REACHED,
     449             :         ERROR,
     450             :         CLOSE_FILE,
     451             :         CLEANUP,
     452             :         FINISHED
     453             : };
     454             : 
     455             : struct bench_params {
     456             :                 struct unclist{
     457             :                         const char *host;
     458             :                         const char *share;
     459             :                 } **unc;
     460             :                 const char *workgroup;
     461             :                 int retry;
     462             :                 unsigned int writeblocks;
     463             :                 unsigned int blocksize;
     464             :                 unsigned int writeratio;
     465             :                 int num_parallel_requests;
     466             : };
     467             : 
     468             : struct benchrw_state {
     469             :         struct torture_context *tctx;
     470             :         char *dname;
     471             :         char *fname;
     472             :         uint16_t fnum;
     473             :         int nr;
     474             :         struct smbcli_tree      *cli;           
     475             :         uint8_t *buffer;
     476             :         int writecnt;
     477             :         int readcnt;
     478             :         int completed;
     479             :         int num_parallel_requests;
     480             :         void *req_params;
     481             :         enum benchrw_stage mode;
     482             :         struct bench_params *lpcfg_params;
     483             : };
     484             : 
     485             : /* 
     486             :         init params using lpcfg_parm_xxx
     487             :         return number of unclist entries
     488             : */
     489           0 : static int init_benchrw_params(struct torture_context *tctx,
     490             :                                struct bench_params *lpar)
     491             : {
     492           0 :         char **unc_list = NULL;
     493           0 :         int num_unc_names = 0, conn_index=0, empty_lines=0;
     494           0 :         const char *p;
     495           0 :         lpar->retry = torture_setting_int(tctx, "retry",3);
     496           0 :         lpar->blocksize = torture_setting_int(tctx, "blocksize",65535);
     497           0 :         lpar->writeblocks = torture_setting_int(tctx, "writeblocks",15);
     498           0 :         lpar->writeratio = torture_setting_int(tctx, "writeratio",5);
     499           0 :         lpar->num_parallel_requests = torture_setting_int(
     500             :                 tctx, "parallel_requests", 5);
     501           0 :         lpar->workgroup = lpcfg_workgroup(tctx->lp_ctx);
     502             :         
     503           0 :         p = torture_setting_string(tctx, "unclist", NULL);
     504           0 :         if (p) {
     505           0 :                 char *h, *s;
     506           0 :                 unc_list = file_lines_load(p, &num_unc_names, 0, NULL);
     507           0 :                 if (!unc_list || num_unc_names <= 0) {
     508           0 :                         torture_comment(tctx, "Failed to load unc names list "
     509             :                                         "from '%s'\n", p);
     510           0 :                         exit(1);
     511             :                 }
     512             :                 
     513           0 :                 lpar->unc = talloc_array(tctx, struct unclist *,
     514             :                                          (num_unc_names-empty_lines));
     515           0 :                 for(conn_index = 0; conn_index < num_unc_names; conn_index++) {
     516             :                         /* ignore empty lines */
     517           0 :                         if(strlen(unc_list[conn_index % num_unc_names])==0){
     518           0 :                                 empty_lines++;
     519           0 :                                 continue;
     520             :                         }
     521           0 :                         if (!smbcli_parse_unc(
     522           0 :                                     unc_list[conn_index % num_unc_names],
     523             :                                     NULL, &h, &s)) {
     524           0 :                                 torture_comment(
     525             :                                         tctx, "Failed to parse UNC "
     526             :                                         "name %s\n",
     527           0 :                                         unc_list[conn_index % num_unc_names]);
     528           0 :                                 exit(1);
     529             :                         }
     530           0 :                         lpar->unc[conn_index-empty_lines] =
     531           0 :                                 talloc(tctx, struct unclist);
     532           0 :                         lpar->unc[conn_index-empty_lines]->host = h;
     533           0 :                         lpar->unc[conn_index-empty_lines]->share = s;     
     534             :                 }
     535           0 :                 return num_unc_names-empty_lines;
     536             :         }else{
     537           0 :                 lpar->unc = talloc_array(tctx, struct unclist *, 1);
     538           0 :                 lpar->unc[0] = talloc(tctx,struct unclist);
     539           0 :                 lpar->unc[0]->host  = torture_setting_string(tctx, "host",
     540             :                                                              NULL);
     541           0 :                 lpar->unc[0]->share = torture_setting_string(tctx, "share",
     542             :                                                              NULL);
     543           0 :                 return 1;
     544             :         }
     545             : }
     546             : 
     547             : /*
     548             :  Called when the reads & writes are finished. closes the file.
     549             : */
     550           0 : static NTSTATUS benchrw_close(struct torture_context *tctx,
     551             :                               struct smbcli_request *req,
     552             :                               struct benchrw_state *state)
     553             : {
     554           0 :         union smb_close close_parms;
     555             :         
     556           0 :         NT_STATUS_NOT_OK_RETURN(req->status);
     557             :         
     558           0 :         torture_comment(tctx, "Close file %d (%d)\n",state->nr,state->fnum);
     559           0 :         close_parms.close.level = RAW_CLOSE_CLOSE;
     560           0 :         close_parms.close.in.file.fnum = state->fnum ;
     561           0 :         close_parms.close.in.write_time = 0;
     562           0 :         state->mode=CLOSE_FILE;
     563             :         
     564           0 :         req = smb_raw_close_send(state->cli, &close_parms);
     565           0 :         NT_STATUS_HAVE_NO_MEMORY(req);
     566             :         /*register the callback function!*/
     567           0 :         req->async.fn = benchrw_callback;
     568           0 :         req->async.private_data = state;
     569             :         
     570           0 :         return NT_STATUS_OK;
     571             : }
     572             : 
     573             : static NTSTATUS benchrw_readwrite(struct torture_context *tctx,
     574             :                                   struct benchrw_state *state);
     575             : static void benchrw_callback(struct smbcli_request *req);
     576             : 
     577           0 : static void benchrw_rw_callback(struct smbcli_request *req)
     578             : {
     579           0 :         struct benchrw_state *state = req->async.private_data;
     580           0 :         struct torture_context *tctx = state->tctx;
     581             : 
     582           0 :         if (!NT_STATUS_IS_OK(req->status)) {
     583           0 :                 state->mode = ERROR;
     584           0 :                 return;
     585             :         }
     586             : 
     587           0 :         state->completed++;
     588           0 :         state->num_parallel_requests--;
     589             : 
     590           0 :         if ((state->completed >= torture_numops)
     591           0 :             && (state->num_parallel_requests == 0)) {
     592           0 :                 benchrw_callback(req);
     593           0 :                 talloc_free(req);
     594           0 :                 return;
     595             :         }
     596             : 
     597           0 :         talloc_free(req);
     598             : 
     599           0 :         if (state->completed + state->num_parallel_requests
     600           0 :             < torture_numops) {
     601           0 :                 benchrw_readwrite(tctx, state);
     602             :         }
     603             : }
     604             : 
     605             : /*
     606             :  Called when the initial write is completed is done. write or read a file.
     607             : */
     608           0 : static NTSTATUS benchrw_readwrite(struct torture_context *tctx,
     609             :                                   struct benchrw_state *state)
     610             : {
     611           0 :         struct smbcli_request *req;
     612           0 :         union smb_read  rd;
     613           0 :         union smb_write wr;
     614             :         
     615             :         /* randomize between writes and reads*/
     616           0 :         if (random() % state->lpcfg_params->writeratio == 0) {
     617           0 :                 torture_comment(tctx, "Callback WRITE file:%d (%d/%d)\n",
     618             :                                 state->nr,state->completed,torture_numops);
     619           0 :                 wr.generic.level = RAW_WRITE_WRITEX  ;
     620           0 :                 wr.writex.in.file.fnum  = state->fnum ;
     621           0 :                 wr.writex.in.offset     = 0;
     622           0 :                 wr.writex.in.wmode      = 0             ;
     623           0 :                 wr.writex.in.remaining  = 0;
     624           0 :                 wr.writex.in.count      = state->lpcfg_params->blocksize;
     625           0 :                 wr.writex.in.data       = state->buffer;
     626           0 :                 state->readcnt=0;
     627           0 :                 req = smb_raw_write_send(state->cli,&wr);
     628             :         }
     629             :         else {
     630           0 :                 torture_comment(tctx,
     631             :                                 "Callback READ file:%d (%d/%d) Offset:%d\n",
     632             :                                 state->nr,state->completed,torture_numops,
     633           0 :                                 (state->readcnt*state->lpcfg_params->blocksize));
     634           0 :                 rd.generic.level = RAW_READ_READX;
     635           0 :                 rd.readx.in.file.fnum   = state->fnum        ;
     636           0 :                 rd.readx.in.offset      = state->readcnt*state->lpcfg_params->blocksize;
     637           0 :                 rd.readx.in.mincnt      = state->lpcfg_params->blocksize;
     638           0 :                 rd.readx.in.maxcnt      = rd.readx.in.mincnt;
     639           0 :                 rd.readx.in.remaining   = 0     ;
     640           0 :                 rd.readx.out.data       = state->buffer;
     641           0 :                 rd.readx.in.read_for_execute = false;
     642           0 :                 if(state->readcnt < state->lpcfg_params->writeblocks){
     643           0 :                         state->readcnt++;    
     644             :                 }else{
     645             :                         /*start reading from beginning of file*/
     646           0 :                         state->readcnt=0;
     647             :                 }
     648           0 :                 req = smb_raw_read_send(state->cli,&rd);
     649             :         }
     650           0 :         state->num_parallel_requests += 1;
     651           0 :         NT_STATUS_HAVE_NO_MEMORY(req);
     652             :         /*register the callback function!*/
     653           0 :         req->async.fn = benchrw_rw_callback;
     654           0 :         req->async.private_data = state;
     655             :         
     656           0 :         return NT_STATUS_OK;
     657             : }
     658             : 
     659             : /*
     660             :  Called when the open is done. writes to the file.
     661             : */
     662           0 : static NTSTATUS benchrw_open(struct torture_context *tctx,
     663             :                              struct smbcli_request *req,
     664             :                              struct benchrw_state *state)
     665             : {
     666           0 :         union smb_write wr;
     667           0 :         if(state->mode == OPEN_FILE){
     668           0 :                 NTSTATUS status;
     669           0 :                 status = smb_raw_open_recv(req,tctx,(
     670           0 :                                         union smb_open*)state->req_params);
     671           0 :                 NT_STATUS_NOT_OK_RETURN(status);
     672             :         
     673           0 :                 state->fnum = ((union smb_open*)state->req_params)
     674           0 :                                                 ->openx.out.file.fnum;
     675           0 :                 torture_comment(tctx, "File opened (%d)\n",state->fnum);
     676           0 :                 state->mode=INITIAL_WRITE;
     677             :         }
     678             :                 
     679           0 :         torture_comment(tctx, "Write initial test file:%d (%d/%d)\n",state->nr,
     680           0 :                 (state->writecnt+1)*state->lpcfg_params->blocksize,
     681           0 :                 (state->lpcfg_params->writeblocks*state->lpcfg_params->blocksize));
     682           0 :         wr.generic.level = RAW_WRITE_WRITEX  ;
     683           0 :         wr.writex.in.file.fnum  = state->fnum ;
     684           0 :         wr.writex.in.offset     = state->writecnt * 
     685           0 :                                         state->lpcfg_params->blocksize;
     686           0 :         wr.writex.in.wmode      = 0             ;
     687           0 :         wr.writex.in.remaining  = (state->lpcfg_params->writeblocks *
     688           0 :                                                 state->lpcfg_params->blocksize)-
     689           0 :                                                 ((state->writecnt+1)*state->
     690             :                                                 lpcfg_params->blocksize);
     691           0 :         wr.writex.in.count      = state->lpcfg_params->blocksize;
     692           0 :         wr.writex.in.data       = state->buffer;
     693           0 :         state->writecnt++;
     694           0 :         if(state->writecnt == state->lpcfg_params->writeblocks){
     695           0 :                 state->mode=READ_WRITE_DATA;
     696             :         }
     697           0 :         req = smb_raw_write_send(state->cli,&wr);
     698           0 :         NT_STATUS_HAVE_NO_MEMORY(req);
     699             :         
     700             :         /*register the callback function!*/
     701           0 :         req->async.fn = benchrw_callback;
     702           0 :         req->async.private_data = state;
     703           0 :         return NT_STATUS_OK;
     704             : } 
     705             : 
     706             : /*
     707             :  Called when the mkdir is done. Opens a file.
     708             : */
     709           0 : static NTSTATUS benchrw_mkdir(struct torture_context *tctx,
     710             :                               struct smbcli_request *req,
     711             :                               struct benchrw_state *state)
     712             : {
     713           0 :         union smb_open *open_parms;     
     714           0 :         uint8_t *writedata;     
     715             :                 
     716           0 :         NT_STATUS_NOT_OK_RETURN(req->status);
     717             :         
     718             :         /* open/create the files */
     719           0 :         torture_comment(tctx, "Open File %d/%d\n",state->nr+1,
     720             :                         torture_setting_int(tctx, "nprocs", 4));
     721           0 :         open_parms=talloc_zero(tctx, union smb_open);
     722           0 :         NT_STATUS_HAVE_NO_MEMORY(open_parms);
     723           0 :         open_parms->openx.level = RAW_OPEN_OPENX;
     724           0 :         open_parms->openx.in.flags = 0;
     725           0 :         open_parms->openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
     726           0 :         open_parms->openx.in.search_attrs = 
     727             :                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
     728           0 :         open_parms->openx.in.file_attrs = 0;
     729           0 :         open_parms->openx.in.write_time = 0;
     730           0 :         open_parms->openx.in.open_func = OPENX_OPEN_FUNC_CREATE;
     731           0 :         open_parms->openx.in.size = 0;
     732           0 :         open_parms->openx.in.timeout = 0;
     733           0 :         open_parms->openx.in.fname = state->fname;
     734             :                 
     735           0 :         writedata = talloc_size(tctx,state->lpcfg_params->blocksize);
     736           0 :         NT_STATUS_HAVE_NO_MEMORY(writedata);
     737           0 :         generate_random_buffer(writedata,state->lpcfg_params->blocksize);
     738           0 :         state->buffer=writedata;
     739           0 :         state->writecnt=1;
     740           0 :         state->readcnt=0;
     741           0 :         state->req_params=open_parms;                
     742           0 :         state->mode=OPEN_FILE;       
     743             :                         
     744           0 :         req = smb_raw_open_send(state->cli,open_parms);
     745           0 :         NT_STATUS_HAVE_NO_MEMORY(req);
     746             :         
     747             :         /*register the callback function!*/
     748           0 :         req->async.fn = benchrw_callback;
     749           0 :         req->async.private_data = state;
     750             :                 
     751           0 :         return NT_STATUS_OK;
     752             : }
     753             : 
     754             : /*
     755             :  handler for completion of a sub-request of the bench-rw test
     756             : */
     757           0 : static void benchrw_callback(struct smbcli_request *req)
     758             : {
     759           0 :         struct benchrw_state *state = req->async.private_data;
     760           0 :         struct torture_context *tctx = state->tctx;
     761             :         
     762             :         /*don't send new requests when torture_numops is reached*/
     763           0 :         if ((state->mode == READ_WRITE_DATA)
     764           0 :             && (state->completed >= torture_numops)) {
     765           0 :                 state->mode=MAX_OPS_REACHED;
     766             :         }
     767             :         
     768           0 :         switch (state->mode) {
     769             :         
     770           0 :         case MK_TESTDIR:
     771           0 :                 if (!NT_STATUS_IS_OK(benchrw_mkdir(tctx, req,state))) {
     772           0 :                         torture_comment(tctx, "Failed to create the test "
     773             :                                         "directory - %s\n", 
     774             :                                         nt_errstr(req->status));
     775           0 :                         state->mode=ERROR;
     776           0 :                         return;
     777             :                 }
     778           0 :                 break;  
     779           0 :         case OPEN_FILE:
     780             :         case INITIAL_WRITE:
     781           0 :                 if (!NT_STATUS_IS_OK(benchrw_open(tctx, req,state))){
     782           0 :                         torture_comment(tctx, "Failed to open/write the "
     783             :                                         "file - %s\n", 
     784             :                                         nt_errstr(req->status));
     785           0 :                         state->mode=ERROR;
     786           0 :                         state->readcnt=0;
     787           0 :                         return;
     788             :                 }
     789           0 :                 break;
     790           0 :         case READ_WRITE_DATA:
     791           0 :                 while (state->num_parallel_requests
     792           0 :                        < state->lpcfg_params->num_parallel_requests) {
     793           0 :                         NTSTATUS status;
     794           0 :                         status = benchrw_readwrite(tctx,state);
     795           0 :                         if (!NT_STATUS_IS_OK(status)){
     796           0 :                                 torture_comment(tctx, "Failed to read/write "
     797             :                                                 "the file - %s\n", 
     798             :                                                 nt_errstr(req->status));
     799           0 :                                 state->mode=ERROR;
     800           0 :                                 return;
     801             :                         }
     802             :                 }
     803           0 :                 break;
     804           0 :         case MAX_OPS_REACHED:
     805           0 :                 if (!NT_STATUS_IS_OK(benchrw_close(tctx,req,state))){
     806           0 :                         torture_comment(tctx, "Failed to read/write/close "
     807             :                                         "the file - %s\n", 
     808             :                                         nt_errstr(req->status));
     809           0 :                         state->mode=ERROR;
     810           0 :                         return;
     811             :                 }
     812           0 :                 break;
     813           0 :         case CLOSE_FILE:
     814           0 :                 torture_comment(tctx, "File %d closed\n",state->nr);
     815           0 :                 if (!NT_STATUS_IS_OK(req->status)) {
     816           0 :                         torture_comment(tctx, "Failed to close the "
     817             :                                         "file - %s\n",
     818             :                                         nt_errstr(req->status));
     819           0 :                         state->mode=ERROR;
     820           0 :                         return;
     821             :                 }
     822           0 :                 state->mode=CLEANUP;
     823           0 :                 return; 
     824           0 :         default:
     825           0 :                 break;
     826             :         }
     827             :         
     828             : }
     829             : 
     830             : /* open connection async callback function*/
     831           0 : static void async_open_callback(struct composite_context *con)
     832             : {
     833           0 :         struct benchrw_state *state = con->async.private_data;
     834           0 :         struct torture_context *tctx = state->tctx;
     835           0 :         int retry = state->lpcfg_params->retry;
     836             :                 
     837           0 :         if (NT_STATUS_IS_OK(con->status)) {
     838           0 :                 state->cli=((struct smb_composite_connect*)
     839           0 :                                         state->req_params)->out.tree;
     840           0 :                 state->mode=CLEANUP_TESTDIR;
     841             :         }else{
     842           0 :                 if(state->writecnt < retry){
     843           0 :                         torture_comment(tctx, "Failed to open connection: "
     844             :                                         "%d, Retry (%d/%d)\n",
     845             :                                         state->nr,state->writecnt,retry);
     846           0 :                         state->writecnt++;
     847           0 :                         state->mode=START;
     848           0 :                         usleep(1000);   
     849             :                 }else{
     850           0 :                         torture_comment(tctx, "Failed to open connection "
     851             :                                         "(%d) - %s\n",
     852             :                                         state->nr, nt_errstr(con->status));
     853           0 :                         state->mode=ERROR;
     854             :                 }
     855           0 :                 return;
     856             :         }       
     857             : }
     858             : 
     859             : /*
     860             :  establishes a smbcli_tree from scratch (async)
     861             : */
     862           0 : static struct composite_context *torture_connect_async(
     863             :                                 struct torture_context *tctx,
     864             :                                 struct smb_composite_connect *smb,
     865             :                                 TALLOC_CTX *mem_ctx,
     866             :                                 struct tevent_context *ev,
     867             :                                 const char *host,
     868             :                                 const char *share,
     869             :                                 const char *workgroup)
     870             : {
     871           0 :         torture_comment(tctx, "Open Connection to %s/%s\n",host,share);
     872           0 :         smb->in.dest_host=talloc_strdup(mem_ctx,host);
     873           0 :         smb->in.service=talloc_strdup(mem_ctx,share);
     874           0 :         smb->in.dest_ports=lpcfg_smb_ports(tctx->lp_ctx);
     875           0 :         smb->in.socket_options = lpcfg_socket_options(tctx->lp_ctx);
     876           0 :         smb->in.called_name = strupper_talloc(mem_ctx, host);
     877           0 :         smb->in.service_type=NULL;
     878           0 :         smb->in.credentials = samba_cmdline_get_creds();
     879           0 :         smb->in.fallback_to_anonymous=false;
     880           0 :         smb->in.gensec_settings = lpcfg_gensec_settings(mem_ctx, tctx->lp_ctx);
     881           0 :         smb->in.workgroup=workgroup;
     882           0 :         lpcfg_smbcli_options(tctx->lp_ctx, &smb->in.options);
     883           0 :         lpcfg_smbcli_session_options(tctx->lp_ctx, &smb->in.session_options);
     884             :         
     885           0 :         return smb_composite_connect_send(smb,mem_ctx,
     886             :                                           lpcfg_resolve_context(tctx->lp_ctx),ev);
     887             : }
     888             : 
     889           0 : bool run_benchrw(struct torture_context *tctx)
     890             : {
     891           0 :         struct smb_composite_connect *smb_con;
     892           0 :         const char *fname = "\\rwtest.dat";
     893           0 :         struct smbcli_request *req;
     894           0 :         struct benchrw_state **state;
     895           0 :         int i , num_unc_names;
     896           0 :         struct tevent_context   *ev     ;       
     897           0 :         struct composite_context *req1;
     898           0 :         struct bench_params lpparams;
     899           0 :         union smb_mkdir parms;
     900           0 :         int finished = 0;
     901           0 :         bool success=true;
     902           0 :         int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
     903             :         
     904           0 :         torture_comment(tctx, "Start BENCH-READWRITE num_ops=%d "
     905             :                         "num_nprocs=%d\n",
     906             :                         torture_numops, torture_nprocs);
     907             : 
     908             :         /*init talloc context*/
     909           0 :         ev = tctx->ev;
     910           0 :         state = talloc_array(tctx, struct benchrw_state *, torture_nprocs);
     911             : 
     912             :         /* init params using lpcfg_parm_xxx */
     913           0 :         num_unc_names = init_benchrw_params(tctx,&lpparams);
     914             :         
     915             :         /* init private data structs*/
     916           0 :         for(i = 0; i<torture_nprocs;i++){
     917           0 :                 state[i]=talloc(tctx,struct benchrw_state);
     918           0 :                 state[i]->tctx = tctx;
     919           0 :                 state[i]->completed=0;
     920           0 :                 state[i]->num_parallel_requests=0;
     921           0 :                 state[i]->lpcfg_params=&lpparams;
     922           0 :                 state[i]->nr=i;
     923           0 :                 state[i]->dname=talloc_asprintf(tctx,"benchrw%d",i);
     924           0 :                 state[i]->fname=talloc_asprintf(tctx,"%s%s",
     925           0 :                                                 state[i]->dname,fname);      
     926           0 :                 state[i]->mode=START;
     927           0 :                 state[i]->writecnt=0;
     928             :         }
     929             :         
     930           0 :         torture_comment(tctx, "Starting async requests\n");   
     931           0 :         while(finished != torture_nprocs){
     932           0 :                 finished=0;
     933           0 :                 for(i = 0; i<torture_nprocs;i++){
     934           0 :                         switch (state[i]->mode){
     935             :                         /*open multiple connections with the same userid */
     936           0 :                         case START:
     937           0 :                                 smb_con = talloc_zero(
     938             :                                         tctx,struct smb_composite_connect);
     939           0 :                                 state[i]->req_params=smb_con; 
     940           0 :                                 state[i]->mode=OPEN_CONNECTION;
     941           0 :                                 req1 = torture_connect_async(
     942             :                                         tctx, smb_con, tctx,ev,
     943           0 :                                         lpparams.unc[i % num_unc_names]->host,
     944           0 :                                         lpparams.unc[i % num_unc_names]->share,
     945             :                                         lpparams.workgroup);
     946             :                                 /* register callback fn + private data */
     947           0 :                                 req1->async.fn = async_open_callback;
     948           0 :                                 req1->async.private_data=state[i];
     949           0 :                                 break;
     950             :                         /*setup test dirs (sync)*/
     951           0 :                         case CLEANUP_TESTDIR:
     952           0 :                                 torture_comment(tctx, "Setup test dir %d\n",i);
     953           0 :                                 smb_raw_exit(state[i]->cli->session);
     954           0 :                                 if (smbcli_deltree(state[i]->cli, 
     955           0 :                                                 state[i]->dname) == -1) {
     956           0 :                                         torture_comment(
     957             :                                                 tctx,
     958             :                                                 "Unable to delete %s - %s\n", 
     959           0 :                                                 state[i]->dname,
     960           0 :                                                 smbcli_errstr(state[i]->cli));
     961           0 :                                         state[i]->mode=ERROR;
     962           0 :                                         break;
     963             :                                 }
     964           0 :                                 state[i]->mode=MK_TESTDIR;
     965           0 :                                 parms.mkdir.level = RAW_MKDIR_MKDIR;
     966           0 :                                 parms.mkdir.in.path = state[i]->dname;
     967           0 :                                 req = smb_raw_mkdir_send(state[i]->cli,&parms);
     968             :                                 /* register callback fn + private data */
     969           0 :                                 req->async.fn = benchrw_callback;
     970           0 :                                 req->async.private_data=state[i];
     971           0 :                                 break;
     972             :                         /* error occurred , finish */
     973           0 :                         case ERROR:
     974           0 :                                 finished++;
     975           0 :                                 success=false;
     976           0 :                                 break;
     977             :                         /* cleanup , close connection */
     978           0 :                         case CLEANUP:
     979           0 :                                 torture_comment(tctx, "Deleting test dir %s "
     980           0 :                                                 "%d/%d\n",state[i]->dname,
     981             :                                                 i+1,torture_nprocs);
     982           0 :                                 smbcli_deltree(state[i]->cli,state[i]->dname);
     983           0 :                                 if (NT_STATUS_IS_ERR(smb_tree_disconnect(
     984             :                                                              state[i]->cli))) {
     985           0 :                                         torture_comment(tctx, "ERROR: Tree "
     986             :                                                         "disconnect failed");
     987           0 :                                         state[i]->mode=ERROR;
     988           0 :                                         break;
     989             :                                 }
     990           0 :                                 state[i]->mode=FINISHED;
     991             : 
     992           0 :                                 FALL_THROUGH;
     993           0 :                         case FINISHED:
     994           0 :                                 finished++;
     995           0 :                                 break;
     996           0 :                         default:
     997           0 :                                 tevent_loop_once(ev);
     998             :                         }
     999             :                 }
    1000             :         }
    1001             :                                 
    1002           0 :         return success; 
    1003             : }
    1004             : 

Generated by: LCOV version 1.14