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

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    In-memory cache
       4             :    Copyright (C) Volker Lendecke 2007
       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 "torture/proto.h"
      22             : #include "libsmb/libsmb.h"
      23             : #include "libsmb/clirap.h"
      24             : #include "../lib/util/tevent_ntstatus.h"
      25             : 
      26           0 : static long long int ival(const char *str)
      27             : {
      28           0 :         return strtoll(str, NULL, 0);
      29             : }
      30             : 
      31             : struct nbench_state {
      32             :         struct tevent_context *ev;
      33             :         struct cli_state *cli;
      34             :         const char *cliname;
      35             :         FILE *loadfile;
      36             :         struct ftable *ftable;
      37             :         void (*bw_report)(size_t nread,
      38             :                           size_t nwritten,
      39             :                           void *private_data);
      40             :         void *bw_report_private;
      41             : };
      42             : 
      43             : struct lock_info {
      44             :         struct lock_info *next, *prev;
      45             :         off_t offset;
      46             :         int size;
      47             : };
      48             : 
      49             : struct createx_params {
      50             :         char *fname;
      51             :         unsigned int cr_options;
      52             :         unsigned int cr_disposition;
      53             :         int handle;
      54             : };
      55             : 
      56             : struct ftable {
      57             :         struct ftable *next, *prev;
      58             :         struct createx_params cp;
      59             :         struct lock_info *locks;
      60             :         uint16_t fnum; /* the fd that we got back from the server */
      61             : };
      62             : 
      63             : enum nbench_cmd {
      64             :         NBENCH_CMD_NTCREATEX,
      65             :         NBENCH_CMD_CLOSE,
      66             :         NBENCH_CMD_RENAME,
      67             :         NBENCH_CMD_UNLINK,
      68             :         NBENCH_CMD_DELTREE,
      69             :         NBENCH_CMD_RMDIR,
      70             :         NBENCH_CMD_MKDIR,
      71             :         NBENCH_CMD_QUERY_PATH_INFORMATION,
      72             :         NBENCH_CMD_QUERY_FILE_INFORMATION,
      73             :         NBENCH_CMD_QUERY_FS_INFORMATION,
      74             :         NBENCH_CMD_SET_FILE_INFORMATION,
      75             :         NBENCH_CMD_FIND_FIRST,
      76             :         NBENCH_CMD_WRITEX,
      77             :         NBENCH_CMD_WRITE,
      78             :         NBENCH_CMD_LOCKX,
      79             :         NBENCH_CMD_UNLOCKX,
      80             :         NBENCH_CMD_READX,
      81             :         NBENCH_CMD_FLUSH,
      82             :         NBENCH_CMD_SLEEP,
      83             : };
      84             : 
      85             : struct nbench_cmd_struct {
      86             :         char **params;
      87             :         int num_params;
      88             :         NTSTATUS status;
      89             :         enum nbench_cmd cmd;
      90             : };
      91             : 
      92           0 : static struct nbench_cmd_struct *nbench_parse(TALLOC_CTX *mem_ctx,
      93             :                                               const char *line)
      94             : {
      95           0 :         struct nbench_cmd_struct *result;
      96           0 :         char *cmd;
      97           0 :         char *status;
      98             : 
      99           0 :         result = talloc(mem_ctx, struct nbench_cmd_struct);
     100           0 :         if (result == NULL) {
     101           0 :                 return NULL;
     102             :         }
     103           0 :         result->params = str_list_make_shell(mem_ctx, line, " ");
     104           0 :         if (result->params == NULL) {
     105           0 :                 goto fail;
     106             :         }
     107           0 :         result->num_params = talloc_array_length(result->params) - 1;
     108           0 :         if (result->num_params < 2) {
     109           0 :                 goto fail;
     110             :         }
     111           0 :         status = result->params[result->num_params-1];
     112           0 :         if (strncmp(status, "NT_STATUS_", 10) != 0 &&
     113           0 :             strncmp(status, "0x", 2) != 0) {
     114           0 :                 goto fail;
     115             :         }
     116             :         /* accept numeric or string status codes */
     117           0 :         if (strncmp(status, "0x", 2) == 0) {
     118           0 :                 result->status = NT_STATUS(strtoul(status, NULL, 16));
     119             :         } else {
     120           0 :                 result->status = nt_status_string_to_code(status);
     121             :         }
     122             : 
     123           0 :         cmd = result->params[0];
     124             : 
     125           0 :         if (!strcmp(cmd, "NTCreateX")) {
     126           0 :                 result->cmd = NBENCH_CMD_NTCREATEX;
     127           0 :         } else if (!strcmp(cmd, "Close")) {
     128           0 :                 result->cmd = NBENCH_CMD_CLOSE;
     129           0 :         } else if (!strcmp(cmd, "Rename")) {
     130           0 :                 result->cmd = NBENCH_CMD_RENAME;
     131           0 :         } else if (!strcmp(cmd, "Unlink")) {
     132           0 :                 result->cmd = NBENCH_CMD_UNLINK;
     133           0 :         } else if (!strcmp(cmd, "Deltree")) {
     134           0 :                 result->cmd = NBENCH_CMD_DELTREE;
     135           0 :         } else if (!strcmp(cmd, "Rmdir")) {
     136           0 :                 result->cmd = NBENCH_CMD_RMDIR;
     137           0 :         } else if (!strcmp(cmd, "Mkdir")) {
     138           0 :                 result->cmd = NBENCH_CMD_MKDIR;
     139           0 :         } else if (!strcmp(cmd, "QUERY_PATH_INFORMATION")) {
     140           0 :                 result->cmd = NBENCH_CMD_QUERY_PATH_INFORMATION;
     141           0 :         } else if (!strcmp(cmd, "QUERY_FILE_INFORMATION")) {
     142           0 :                 result->cmd = NBENCH_CMD_QUERY_FILE_INFORMATION;
     143           0 :         } else if (!strcmp(cmd, "QUERY_FS_INFORMATION")) {
     144           0 :                 result->cmd = NBENCH_CMD_QUERY_FS_INFORMATION;
     145           0 :         } else if (!strcmp(cmd, "SET_FILE_INFORMATION")) {
     146           0 :                 result->cmd = NBENCH_CMD_SET_FILE_INFORMATION;
     147           0 :         } else if (!strcmp(cmd, "FIND_FIRST")) {
     148           0 :                 result->cmd = NBENCH_CMD_FIND_FIRST;
     149           0 :         } else if (!strcmp(cmd, "WriteX")) {
     150           0 :                 result->cmd = NBENCH_CMD_WRITEX;
     151           0 :         } else if (!strcmp(cmd, "Write")) {
     152           0 :                 result->cmd = NBENCH_CMD_WRITE;
     153           0 :         } else if (!strcmp(cmd, "LockX")) {
     154           0 :                 result->cmd = NBENCH_CMD_LOCKX;
     155           0 :         } else if (!strcmp(cmd, "UnlockX")) {
     156           0 :                 result->cmd = NBENCH_CMD_UNLOCKX;
     157           0 :         } else if (!strcmp(cmd, "ReadX")) {
     158           0 :                 result->cmd = NBENCH_CMD_READX;
     159           0 :         } else if (!strcmp(cmd, "Flush")) {
     160           0 :                 result->cmd = NBENCH_CMD_FLUSH;
     161           0 :         } else if (!strcmp(cmd, "Sleep")) {
     162           0 :                 result->cmd = NBENCH_CMD_SLEEP;
     163             :         } else {
     164           0 :                 goto fail;
     165             :         }
     166           0 :         return result;
     167           0 : fail:
     168           0 :         TALLOC_FREE(result);
     169           0 :         return NULL;
     170             : }
     171             : 
     172           0 : static struct ftable *ft_find(struct ftable *ftlist, int handle)
     173             : {
     174           0 :         while (ftlist != NULL) {
     175           0 :                 if (ftlist->cp.handle == handle) {
     176           0 :                         return ftlist;
     177             :                 }
     178           0 :                 ftlist = ftlist->next;
     179             :         }
     180           0 :         return NULL;
     181             : }
     182             : 
     183             : struct nbench_cmd_state {
     184             :         struct tevent_context *ev;
     185             :         struct nbench_state *state;
     186             :         struct nbench_cmd_struct *cmd;
     187             :         struct ftable *ft;
     188             :         bool eof;
     189             : };
     190             : 
     191             : static void nbench_cmd_done(struct tevent_req *subreq);
     192             : 
     193           0 : static struct tevent_req *nbench_cmd_send(TALLOC_CTX *mem_ctx,
     194             :                                           struct tevent_context *ev,
     195             :                                           struct nbench_state *nb_state)
     196             : {
     197           0 :         struct tevent_req *req, *subreq;
     198           0 :         struct nbench_cmd_state *state;
     199           0 :         char line[1024];
     200           0 :         size_t len;
     201             : 
     202           0 :         req = tevent_req_create(mem_ctx, &state, struct nbench_cmd_state);
     203           0 :         if (req == NULL) {
     204           0 :                 return NULL;
     205             :         }
     206           0 :         state->ev = ev;
     207           0 :         state->state = nb_state;
     208             : 
     209           0 :         if (fgets(line, sizeof(line), nb_state->loadfile) == NULL) {
     210           0 :                 tevent_req_nterror(req, NT_STATUS_END_OF_FILE);
     211           0 :                 return tevent_req_post(req, ev);
     212             :         }
     213           0 :         len = strlen(line);
     214           0 :         if (len == 0) {
     215           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     216           0 :                 return tevent_req_post(req, ev);
     217             :         }
     218           0 :         if (line[len-1] == '\n') {
     219           0 :                 line[len-1] = '\0';
     220             :         }
     221             : 
     222           0 :         state->cmd = nbench_parse(state, line);
     223           0 :         if (state->cmd == NULL) {
     224           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     225           0 :                 return tevent_req_post(req, ev);
     226             :         }
     227             : 
     228           0 :         switch (state->cmd->cmd) {
     229           0 :         case NBENCH_CMD_NTCREATEX: {
     230           0 :                 uint32_t desired_access;
     231           0 :                 uint32_t share_mode;
     232           0 :                 unsigned int flags = 0;
     233             : 
     234           0 :                 state->ft = talloc(state, struct ftable);
     235           0 :                 if (tevent_req_nomem(state->ft, req)) {
     236           0 :                         return tevent_req_post(req, ev);
     237             :                 }
     238             : 
     239           0 :                 state->ft->cp.fname = talloc_all_string_sub(
     240           0 :                         state->ft, state->cmd->params[1], "client1",
     241             :                         nb_state->cliname);
     242           0 :                 if (tevent_req_nomem(state->ft->cp.fname, req)) {
     243           0 :                         return tevent_req_post(req, ev);
     244             :                 }
     245           0 :                 state->ft->cp.cr_options = ival(state->cmd->params[2]);
     246           0 :                 state->ft->cp.cr_disposition = ival(state->cmd->params[3]);
     247           0 :                 state->ft->cp.handle = ival(state->cmd->params[4]);
     248             : 
     249           0 :                 if (state->ft->cp.cr_options & FILE_DIRECTORY_FILE) {
     250           0 :                         desired_access = SEC_FILE_READ_DATA;
     251             :                 } else {
     252           0 :                         desired_access =
     253             :                                 SEC_FILE_READ_DATA |
     254             :                                 SEC_FILE_WRITE_DATA |
     255             :                                 SEC_FILE_READ_ATTRIBUTE |
     256             :                                 SEC_FILE_WRITE_ATTRIBUTE;
     257           0 :                         flags = EXTENDED_RESPONSE_REQUIRED
     258             :                                 | REQUEST_OPLOCK | REQUEST_BATCH_OPLOCK;
     259             :                 }
     260           0 :                 share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
     261             : 
     262           0 :                 subreq = cli_ntcreate_send(
     263           0 :                         state, ev, nb_state->cli, state->ft->cp.fname, flags,
     264             :                         desired_access, 0, share_mode,
     265           0 :                         state->ft->cp.cr_disposition,
     266           0 :                         state->ft->cp.cr_options,
     267             :                         SMB2_IMPERSONATION_IMPERSONATION, 0);
     268           0 :                 break;
     269             :         }
     270           0 :         case NBENCH_CMD_CLOSE: {
     271           0 :                 state->ft = ft_find(state->state->ftable,
     272           0 :                                     ival(state->cmd->params[1]));
     273           0 :                 if (state->ft == NULL) {
     274           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     275           0 :                         return tevent_req_post(req, ev);
     276             :                 }
     277           0 :                 subreq = cli_close_send(state,
     278             :                                         ev,
     279             :                                         nb_state->cli,
     280           0 :                                         state->ft->fnum,
     281             :                                         0);
     282           0 :                 break;
     283             :         }
     284           0 :         case NBENCH_CMD_MKDIR: {
     285           0 :                 char *fname;
     286           0 :                 fname = talloc_all_string_sub(
     287           0 :                         state, state->cmd->params[1], "client1",
     288             :                         nb_state->cliname);
     289           0 :                 if (tevent_req_nomem(state->ft->cp.fname, req)) {
     290           0 :                         return tevent_req_post(req, ev);
     291             :                 }
     292           0 :                 subreq = cli_mkdir_send(state, ev, nb_state->cli, fname);
     293           0 :                 break;
     294             :         }
     295           0 :         case NBENCH_CMD_QUERY_PATH_INFORMATION: {
     296           0 :                 char *fname;
     297           0 :                 fname = talloc_all_string_sub(
     298           0 :                         state, state->cmd->params[1], "client1",
     299             :                         nb_state->cliname);
     300           0 :                 if (tevent_req_nomem(state->ft->cp.fname, req)) {
     301           0 :                         return tevent_req_post(req, ev);
     302             :                 }
     303           0 :                 subreq = cli_qpathinfo_send(state, ev, nb_state->cli, fname,
     304           0 :                                             ival(state->cmd->params[2]),
     305             :                                             0, CLI_BUFFER_SIZE);
     306           0 :                 break;
     307             :         }
     308           0 :         default:
     309           0 :                 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
     310           0 :                 return tevent_req_post(req, ev);
     311             :         }
     312             : 
     313           0 :         if (tevent_req_nomem(subreq, req)) {
     314           0 :                 return tevent_req_post(req, ev);
     315             :         }
     316           0 :         tevent_req_set_callback(subreq, nbench_cmd_done, req);
     317           0 :         return req;
     318             : }
     319             : 
     320           0 : static bool status_wrong(struct tevent_req *req, NTSTATUS expected,
     321             :                          NTSTATUS status)
     322             : {
     323           0 :         if (NT_STATUS_EQUAL(expected, status)) {
     324           0 :                 return false;
     325             :         }
     326           0 :         if (NT_STATUS_IS_OK(status)) {
     327           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     328             :         }
     329           0 :         tevent_req_nterror(req, status);
     330           0 :         return true;
     331             : }
     332             : 
     333           0 : static void nbench_cmd_done(struct tevent_req *subreq)
     334             : {
     335           0 :         struct tevent_req *req = tevent_req_callback_data(
     336             :                 subreq, struct tevent_req);
     337           0 :         struct nbench_cmd_state *state = tevent_req_data(
     338             :                 req, struct nbench_cmd_state);
     339           0 :         struct nbench_state *nbstate = state->state;
     340           0 :         NTSTATUS status;
     341             : 
     342           0 :         switch (state->cmd->cmd) {
     343           0 :         case NBENCH_CMD_NTCREATEX: {
     344           0 :                 struct ftable *ft;
     345           0 :                 status = cli_ntcreate_recv(subreq, &state->ft->fnum, NULL);
     346           0 :                 TALLOC_FREE(subreq);
     347           0 :                 if (status_wrong(req, state->cmd->status, status)) {
     348           0 :                         return;
     349             :                 }
     350           0 :                 if (!NT_STATUS_IS_OK(status)) {
     351           0 :                         tevent_req_done(req);
     352           0 :                         return;
     353             :                 }
     354           0 :                 ft = talloc_move(nbstate, &state->ft);
     355           0 :                 DLIST_ADD(nbstate->ftable, ft);
     356           0 :                 break;
     357             :         }
     358           0 :         case NBENCH_CMD_CLOSE: {
     359           0 :                 status = cli_close_recv(subreq);
     360           0 :                 TALLOC_FREE(subreq);
     361           0 :                 if (status_wrong(req, state->cmd->status, status)) {
     362           0 :                         return;
     363             :                 }
     364           0 :                 DLIST_REMOVE(state->state->ftable, state->ft);
     365           0 :                 TALLOC_FREE(state->ft);
     366           0 :                 break;
     367             :         }
     368           0 :         case NBENCH_CMD_MKDIR: {
     369           0 :                 status = cli_mkdir_recv(subreq);
     370           0 :                 TALLOC_FREE(subreq);
     371           0 :                 if (status_wrong(req, state->cmd->status, status)) {
     372           0 :                         return;
     373             :                 }
     374           0 :                 break;
     375             :         }
     376           0 :         case NBENCH_CMD_QUERY_PATH_INFORMATION: {
     377           0 :                 status = cli_qpathinfo_recv(subreq, NULL, NULL, NULL);
     378           0 :                 TALLOC_FREE(subreq);
     379           0 :                 if (status_wrong(req, state->cmd->status, status)) {
     380           0 :                         return;
     381             :                 }
     382           0 :                 break;
     383             :         }
     384           0 :         default:
     385           0 :                 break;
     386             :         }
     387           0 :         tevent_req_done(req);
     388             : }
     389             : 
     390           0 : static NTSTATUS nbench_cmd_recv(struct tevent_req *req)
     391             : {
     392           0 :         return tevent_req_simple_recv_ntstatus(req);
     393             : }
     394             : 
     395             : static void nbench_done(struct tevent_req *subreq);
     396             : 
     397           0 : static struct tevent_req *nbench_send(
     398             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
     399             :         const char *cliname, FILE *loadfile,
     400             :         void (*bw_report)(size_t nread, size_t nwritten, void *private_data),
     401             :         void *bw_report_private)
     402             : {
     403           0 :         struct tevent_req *req, *subreq;
     404           0 :         struct nbench_state *state;
     405             : 
     406           0 :         req = tevent_req_create(mem_ctx, &state, struct nbench_state);
     407           0 :         if (req == NULL) {
     408           0 :                 return NULL;
     409             :         }
     410           0 :         state->ev = ev;
     411           0 :         state->cli = cli;
     412           0 :         state->cliname = cliname;
     413           0 :         state->loadfile = loadfile;
     414           0 :         state->bw_report = bw_report;
     415           0 :         state->bw_report_private = bw_report_private;
     416             : 
     417           0 :         subreq = nbench_cmd_send(state, ev, state);
     418           0 :         if (tevent_req_nomem(subreq, req)) {
     419           0 :                 return tevent_req_post(req, ev);
     420             :         }
     421           0 :         tevent_req_set_callback(subreq, nbench_done, req);
     422           0 :         return req;
     423             : }
     424             : 
     425           0 : static void nbench_done(struct tevent_req *subreq)
     426             : {
     427           0 :         struct tevent_req *req = tevent_req_callback_data(
     428             :                 subreq, struct tevent_req);
     429           0 :         struct nbench_state *state = tevent_req_data(
     430             :                 req, struct nbench_state);
     431           0 :         NTSTATUS status;
     432             : 
     433           0 :         status = nbench_cmd_recv(subreq);
     434           0 :         TALLOC_FREE(subreq);
     435             : 
     436           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
     437           0 :                 tevent_req_done(req);
     438           0 :                 return;
     439             :         }
     440           0 :         if (!NT_STATUS_IS_OK(status)) {
     441           0 :                 tevent_req_nterror(req, status);
     442           0 :                 return;
     443             :         }
     444           0 :         subreq = nbench_cmd_send(state, state->ev, state);
     445           0 :         if (tevent_req_nomem(subreq, req)) {
     446           0 :                 return;
     447             :         }
     448           0 :         tevent_req_set_callback(subreq, nbench_done, req);
     449             : }
     450             : 
     451           0 : static NTSTATUS nbench_recv(struct tevent_req *req)
     452             : {
     453           0 :         return tevent_req_simple_recv_ntstatus(req);
     454             : }
     455             : 
     456           0 : bool run_nbench2(int dummy)
     457             : {
     458           0 :         TALLOC_CTX *frame = talloc_stackframe();
     459           0 :         struct tevent_context *ev;
     460           0 :         struct cli_state *cli = NULL;
     461           0 :         FILE *loadfile;
     462           0 :         bool ret = false;
     463           0 :         struct tevent_req *req;
     464           0 :         NTSTATUS status;
     465             : 
     466           0 :         loadfile = fopen("client.txt", "r");
     467           0 :         if (loadfile == NULL) {
     468           0 :                 fprintf(stderr, "Could not open \"client.txt\": %s\n",
     469           0 :                         strerror(errno));
     470           0 :                 return false;
     471             :         }
     472           0 :         ev = samba_tevent_context_init(talloc_tos());
     473           0 :         if (ev == NULL) {
     474           0 :                 goto fail;
     475             :         }
     476           0 :         if (!torture_open_connection(&cli, 0)) {
     477           0 :                 goto fail;
     478             :         }
     479             : 
     480           0 :         req = nbench_send(talloc_tos(), ev, cli, "client1", loadfile,
     481             :                           NULL, NULL);
     482           0 :         if (req == NULL) {
     483           0 :                 goto fail;
     484             :         }
     485           0 :         if (!tevent_req_poll(req, ev)) {
     486           0 :                 goto fail;
     487             :         }
     488           0 :         status = nbench_recv(req);
     489           0 :         TALLOC_FREE(req);
     490           0 :         printf("nbench returned %s\n", nt_errstr(status));
     491             : 
     492           0 :         ret = true;
     493           0 : fail:
     494           0 :         if (cli != NULL) {
     495           0 :                 torture_close_connection(cli);
     496             :         }
     497           0 :         TALLOC_FREE(ev);
     498           0 :         if (loadfile != NULL) {
     499           0 :                 fclose(loadfile);
     500           0 :                 loadfile = NULL;
     501             :         }
     502           0 :         TALLOC_FREE(frame);
     503           0 :         return ret;
     504             : }

Generated by: LCOV version 1.14