summaryrefslogtreecommitdiff
path: root/source3/torture
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2019-06-20 10:46:21 +0200
committerJeremy Allison <jra@samba.org>2019-06-20 17:18:18 +0000
commitb752e242a6a963253d54a16b2a071f2cfa9797ce (patch)
tree5cddbbe97bdc1233f520fc30fa35a399de180c51 /source3/torture
parent56521c5fbf0bea3dcf0d58a686879485a939b7af (diff)
downloadsamba-b752e242a6a963253d54a16b2a071f2cfa9797ce.tar.gz
torture3: Test cancelling locking&x with ntcancel
Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source3/torture')
-rw-r--r--source3/torture/torture.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 9ffb07a6c93..9a3e10fb32d 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -3331,6 +3331,206 @@ done:
return ret;
}
+struct lock_ntcancel_state {
+ struct timeval start;
+ struct smb1_lock_element lck;
+ struct tevent_req *subreq;
+};
+
+static void lock_ntcancel_waited(struct tevent_req *subreq);
+static void lock_ntcancel_done(struct tevent_req *subreq);
+
+static struct tevent_req *lock_ntcancel_send(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ uint16_t fnum)
+{
+ struct tevent_req *req = NULL, *subreq = NULL;
+ struct lock_ntcancel_state *state = NULL;
+
+ req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->lck = (struct smb1_lock_element) {
+ .pid = cli_getpid(cli), .offset = 0, .length = 1,
+ };
+ state->start = timeval_current();
+
+ state->subreq = cli_lockingx_send(
+ state, /* mem_ctx */
+ ev, /* tevent_context */
+ cli, /* cli */
+ fnum, /* fnum */
+ LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
+ 0, /* newoplocklevel */
+ 10000, /* timeout */
+ 0, /* num_unlocks */
+ NULL, /* unlocks */
+ 1, /* num_locks */
+ &state->lck); /* locks */
+ if (tevent_req_nomem(state->subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
+
+ subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
+ return req;
+}
+
+static void lock_ntcancel_waited(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct lock_ntcancel_state *state = tevent_req_data(
+ req, struct lock_ntcancel_state);
+ bool ok;
+
+ ok = tevent_wakeup_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!ok) {
+ tevent_req_oom(req);
+ return;
+ }
+
+ ok = tevent_req_cancel(state->subreq);
+ if (!ok) {
+ d_fprintf(stderr, "Could not cancel subreq\n");
+ tevent_req_oom(req);
+ return;
+ }
+}
+
+static void lock_ntcancel_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct lock_ntcancel_state *state = tevent_req_data(
+ req, struct lock_ntcancel_state);
+ NTSTATUS status;
+ double elapsed;
+
+ status = cli_lockingx_recv(subreq);
+ TALLOC_FREE(subreq);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
+ d_printf("cli_lockingx returned %s\n", nt_errstr(status));
+ tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
+ return;
+ }
+
+ elapsed = timeval_elapsed(&state->start);
+
+ if (elapsed > 3) {
+ d_printf("cli_lockingx was too slow, cancel did not work\n");
+ tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
+}
+
+static bool run_locktest13(int dummy)
+{
+ struct tevent_context *ev = NULL;
+ struct tevent_req *req = NULL;
+ struct cli_state *cli = NULL;
+ const char fname[] = "\\lockt13.lck";
+ uint16_t fnum1, fnum2;
+ bool ret = false;
+ bool ok;
+ uint8_t data = 1;
+ NTSTATUS status;
+
+ printf("starting locktest13\n");
+
+ ev = samba_tevent_context_init(NULL);
+ if (ev == NULL) {
+ d_fprintf(stderr, "samba_tevent_context_init failed\n");
+ goto done;
+ }
+
+ ok = torture_open_connection(&cli, 0);
+ if (!ok) {
+ goto done;
+ }
+ smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+ status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr,
+ "cli_openx failed: %s\n",
+ nt_errstr(status));
+ goto done;
+ }
+
+ status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr,
+ "cli_openx failed: %s\n",
+ nt_errstr(status));
+ goto done;
+ }
+
+ status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr,
+ "cli_writeall failed: %s\n",
+ nt_errstr(status));
+ goto done;
+ }
+
+ status = cli_locktype(
+ cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr,
+ "cli_locktype failed: %s\n",
+ nt_errstr(status));
+ goto done;
+ }
+
+ req = lock_ntcancel_send(ev, ev, cli, fnum2);
+ if (req == NULL) {
+ d_fprintf(stderr, "lock_ntcancel_send failed\n");
+ goto done;
+ }
+
+ ok = tevent_req_poll_ntstatus(req, ev, &status);
+ if (!ok) {
+ d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
+ goto done;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr,
+ "tevent_req_poll_ntstatus returned %s\n",
+ nt_errstr(status));
+ goto done;
+ }
+
+ status = lock_ntcancel_recv(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr,
+ "lock_ntcancel returned %s\n",
+ nt_errstr(status));
+ goto done;
+ }
+
+ ret = true;
+done:
+ torture_close_connection(cli);
+ return ret;
+}
/*
test whether fnums and tids open on one VC are available on another (a major
@@ -12941,6 +13141,10 @@ static struct {
.fn = run_locktest12,
},
{
+ .name = "LOCK13",
+ .fn = run_locktest13,
+ },
+ {
.name = "UNLINK",
.fn = run_unlinktest,
},