From be7e3536518bbb1234cef197eebd43d42d7a03b1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 7 Jul 2020 09:25:20 +0200 Subject: [PATCH] notify-bench4 --- source3/torture/proto.h | 1 + source3/torture/test_notify.c | 305 ++++++++++++++++++++++++++++++++++ source3/torture/torture.c | 4 + 3 files changed, 310 insertions(+) diff --git a/source3/torture/proto.h b/source3/torture/proto.h index 18e686089ed..00fa113e6e2 100644 --- a/source3/torture/proto.h +++ b/source3/torture/proto.h @@ -113,6 +113,7 @@ bool run_cleanup2(int dummy); bool run_cleanup4(int dummy); bool run_notify_bench2(int dummy); bool run_notify_bench3(int dummy); +bool run_notify_bench4(int dummy); bool run_dbwrap_watch1(int dummy); bool run_dbwrap_watch2(int dummy); bool run_dbwrap_watch3(int dummy); diff --git a/source3/torture/test_notify.c b/source3/torture/test_notify.c index 33c2381fbbd..e6e7aa8c710 100644 --- a/source3/torture/test_notify.c +++ b/source3/torture/test_notify.c @@ -726,3 +726,308 @@ bool run_notify_bench3(int dummy) TALLOC_FREE(large); return true; } + +struct notify_bench4_one_state { + struct tevent_context *ev; + struct cli_state *cli; + uint16_t dnum; +}; + +static void notify_bench4_one_opened(struct tevent_req *subreq); +static void notify_bench4_one_notified(struct tevent_req *subreq); +static void notify_bench4_one_echoed(struct tevent_req *subreq); + +static struct tevent_req *notify_bench4_one_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, + const char *dname) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct notify_bench4_one_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, struct notify_bench4_one_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->cli = cli; + + subreq = cli_ntcreate_send( + state, /* mem_ctx */ + ev, /* ev */ + cli, /* cli */ + dname, /* dname */ + 0, /* create_flags */ + SEC_FILE_READ_DATA| + SEC_FILE_READ_ATTRIBUTE, /* desired_access */ + 0, /* file_attributes */ + FILE_SHARE_READ| + FILE_SHARE_WRITE| + FILE_SHARE_DELETE, /* share_access */ + FILE_OPEN, /* create_disposition */ + FILE_DIRECTORY_FILE, /* create_options */ + SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level */ + 0); /* security_flags */ + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, notify_bench4_one_opened, req); + return req; +} + +static void notify_bench4_one_opened(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct notify_bench4_one_state *state = tevent_req_data( + req, struct notify_bench4_one_state); + NTSTATUS status; + + status = cli_ntcreate_recv(subreq, &state->dnum, NULL); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + + /* + * Hang the notify off long-running "cli", we don't want this + * to be cancelled when things are set up + */ + + subreq = cli_notify_send( + state->cli, /* mem_ctx */ + state->ev, /* ev */ + state->cli, /* cli */ + state->dnum, /* fnum */ + 32, /* buffer_size */ + FILE_NOTIFY_CHANGE_FILE_NAME| + FILE_NOTIFY_CHANGE_DIR_NAME| + FILE_NOTIFY_CHANGE_ATTRIBUTES| + FILE_NOTIFY_CHANGE_SIZE| + FILE_NOTIFY_CHANGE_LAST_WRITE| + FILE_NOTIFY_CHANGE_LAST_ACCESS| + FILE_NOTIFY_CHANGE_CREATION| + FILE_NOTIFY_CHANGE_SECURITY, /* completion_filter */ + false); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, notify_bench4_one_notified, req); + + /* + * Make sure the notify was delivered to the server + */ + subreq = cli_echo_send( + state, /* mem_ctx */ + state->ev, /* ev */ + state->cli, /* cli */ + 1, /* num_echos */ + (DATA_BLOB){0}); /* data */ + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, notify_bench4_one_echoed, req); +} + +static void notify_bench4_one_notified(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct notify_bench4_one_state *state = tevent_req_data( + req, struct notify_bench4_one_state); + uint32_t num_changes; + struct notify_change *changes = NULL; + NTSTATUS status; + + status = cli_notify_recv( + subreq, state, &num_changes, &changes); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + + printf("Got %"PRIu32" changes\n", num_changes); + + TALLOC_FREE(changes); + + tevent_req_done(req); +} + +static void notify_bench4_one_echoed(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + NTSTATUS status; + + status = cli_echo_recv(subreq); + TALLOC_FREE(subreq); + if (tevent_req_nterror(subreq, status)) { + return; + } + tevent_req_done(req); +} + +static NTSTATUS notify_bench4_one_recv(struct tevent_req *req, uint16_t *dnum) +{ + struct notify_bench4_one_state *state = tevent_req_data( + req, struct notify_bench4_one_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *dnum = state->dnum; + return NT_STATUS_OK; +} + +struct notify_bench4_state { + struct tevent_req **reqs; + uint16_t *dnums; + size_t num_done; +}; + +static void notify_bench4_done(struct tevent_req *subreq); + +static struct tevent_req *notify_bench4_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, + const char *dname, + size_t num_ops) +{ + struct tevent_req *req = NULL; + struct notify_bench4_state *state = NULL; + size_t i; + + req = tevent_req_create(mem_ctx, &state, struct notify_bench4_state); + if (req == NULL) { + return NULL; + } + state->reqs = talloc_zero_array(state, struct tevent_req *, num_ops); + if (tevent_req_nomem(state->reqs, req)) { + return tevent_req_post(req, ev); + } + state->dnums = talloc_array(state, uint16_t, num_ops); + if (tevent_req_nomem(state->dnums, req)) { + return tevent_req_post(req, ev); + } + + for (i=0; ireqs[i] = notify_bench4_one_send( + state->reqs, ev, cli, dname); + if (tevent_req_nomem(state->reqs[i], req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback( + state->reqs[i], notify_bench4_done, req); + } + + return req; +} + +static void notify_bench4_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct notify_bench4_state *state = tevent_req_data( + req, struct notify_bench4_state); + size_t num_ops = talloc_array_length(state->reqs); + size_t i; + NTSTATUS status; + + for (i=0; ireqs[i] == subreq) { + break; + } + } + if (i == num_ops) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + + status = notify_bench4_one_recv(subreq, &state->dnums[i]); + if (tevent_req_nterror(req, status)) { + return; + } + + state->num_done += 1; + + if (state->num_done == num_ops) { + tevent_req_done(req); + } +} + +static NTSTATUS notify_bench4_recv( + struct tevent_req *req, TALLOC_CTX *mem_ctx, uint16_t **dnums) +{ + struct notify_bench4_state *state = tevent_req_data( + req, struct notify_bench4_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *dnums = talloc_move(mem_ctx, &state->dnums); + return NT_STATUS_OK; +} + +bool run_notify_bench4(int dummy) +{ + const char dname[] = "\\notify.dir\\subdir"; + struct cli_state *cli = NULL; + struct tevent_context *ev = NULL; + struct tevent_req *req = NULL; + uint16_t *dnums = NULL; + NTSTATUS status; + bool ok; + + printf("Starting to open many notifies on one directory\n"); + + if (!torture_open_connection_flags(&cli, 0, 0)) { + return false; + } + + cli_rmdir(cli, dname); + cli_rmdir(cli, "\\notify.dir"); + + status = cli_mkdir(cli, "\\notify.dir"); + if (!NT_STATUS_IS_OK(status)) { + printf("mkdir failed : %s\n", nt_errstr(status)); + return false; + } + status = cli_mkdir(cli, dname); + if (!NT_STATUS_IS_OK(status)) { + printf("mkdir failed : %s\n", nt_errstr(status)); + return false; + } + + ev = samba_tevent_context_init(talloc_tos()); + if (ev == NULL) { + printf("tevent_context_create failed\n"); + return false; + } + + req = notify_bench4_send(ev, ev, cli, dname, torture_numops); + if (req == 0) { + printf("notify_bench4_send failed\n"); + return false; + } + + ok = tevent_req_poll_ntstatus(req, ev, &status); + if (!ok) { + printf("tevent_req_poll_ntstatus failed: %s\n", + nt_errstr(status)); + return false; + } + + status = notify_bench4_recv(req, ev, &dnums); + if (!NT_STATUS_IS_OK(status)) { + printf("notify_bench4_recv failed: %s\n", nt_errstr(status)); + return false; + } + + system("/bin/sleep 9999"); + + return false; +} diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 2a3133373e9..7083ec6b3a6 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -14787,6 +14787,10 @@ static struct { .name = "NOTIFY-BENCH3", .fn = run_notify_bench3, }, + { + .name = "NOTIFY-BENCH4", + .fn = run_notify_bench4, + }, { .name = "BAD-NBT-SESSION", .fn = run_bad_nbt_session, -- 2.20.1