summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2019-06-14 21:55:09 -0700
committerJeremy Allison <jra@samba.org>2019-06-20 17:18:18 +0000
commitb20231a1abb6d790dcb667f7010ec3b0b1ecb00b (patch)
treef851727c31ceb5c03c02dcce0f4da14ea6e1bf7f /source3
parent2f1a459b7425db316d6c066115889134e67fa2cd (diff)
downloadsamba-b20231a1abb6d790dcb667f7010ec3b0b1ecb00b.tar.gz
torture3: Test blocking posix locks
Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source3')
-rwxr-xr-xsource3/selftest/tests.py4
-rw-r--r--source3/torture/torture.c281
2 files changed, 284 insertions, 1 deletions
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 9dec692cb5a..df30cb49cec 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -156,7 +156,9 @@ for s in shares:
plansmbtorture4testsuite(t, "simpleserver", "//%s/%s %s" % ('$SERVER_IP', s, ' -U$USERNAME%$PASSWORD'), description=s)
posix_tests = ["POSIX", "POSIX-APPEND", "POSIX-SYMLINK-ACL", "POSIX-SYMLINK-EA", "POSIX-OFD-LOCK",
- "POSIX-STREAM-DELETE", "WINDOWS-BAD-SYMLINK", "POSIX-MKDIR"]
+ "POSIX-STREAM-DELETE", "WINDOWS-BAD-SYMLINK", "POSIX-MKDIR",
+ "POSIX-BLOCKING-LOCK",
+ ]
for t in posix_tests:
plantestsuite("samba3.smbtorture_s3.plain.%s" % t, "nt4_dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/posix_share', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"])
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index a74598f68c2..d5043750be6 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -7479,6 +7479,283 @@ static bool run_posix_ofd_lock_test(int dummy)
return correct;
}
+struct posix_blocking_state {
+ struct tevent_context *ev;
+ struct cli_state *cli1;
+ uint16_t fnum1;
+ struct cli_state *cli2;
+ uint16_t fnum2;
+ bool gotblocked;
+ bool gotecho;
+};
+
+static void posix_blocking_locked(struct tevent_req *subreq);
+static void posix_blocking_gotblocked(struct tevent_req *subreq);
+static void posix_blocking_gotecho(struct tevent_req *subreq);
+static void posix_blocking_unlocked(struct tevent_req *subreq);
+
+static struct tevent_req *posix_blocking_send(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli1,
+ uint16_t fnum1,
+ struct cli_state *cli2,
+ uint16_t fnum2)
+{
+ struct tevent_req *req = NULL, *subreq = NULL;
+ struct posix_blocking_state *state = NULL;
+
+ req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+ state->cli1 = cli1;
+ state->fnum1 = fnum1;
+ state->cli2 = cli2;
+ state->fnum2 = fnum2;
+
+ subreq = cli_posix_lock_send(
+ state,
+ state->ev,
+ state->cli1,
+ state->fnum1,
+ 0,
+ 1,
+ false,
+ WRITE_LOCK);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, posix_blocking_locked, req);
+ return req;
+}
+
+static void posix_blocking_locked(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct posix_blocking_state *state = tevent_req_data(
+ req, struct posix_blocking_state);
+ NTSTATUS status;
+
+ status = cli_posix_lock_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
+ subreq = cli_posix_lock_send(
+ state,
+ state->ev,
+ state->cli2,
+ state->fnum2,
+ 0,
+ 1,
+ true,
+ WRITE_LOCK);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
+
+ /* Make sure the blocking request is delivered */
+ subreq = cli_echo_send(
+ state,
+ state->ev,
+ state->cli2,
+ 1,
+ (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
+}
+
+static void posix_blocking_gotblocked(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct posix_blocking_state *state = tevent_req_data(
+ req, struct posix_blocking_state);
+ NTSTATUS status;
+
+ status = cli_posix_lock_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ if (!state->gotecho) {
+ printf("blocked req got through before echo\n");
+ tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+static void posix_blocking_gotecho(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct posix_blocking_state *state = tevent_req_data(
+ req, struct posix_blocking_state);
+ NTSTATUS status;
+
+ status = cli_echo_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ if (state->gotblocked) {
+ printf("blocked req got through before echo\n");
+ tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
+ return;
+ }
+ state->gotecho = true;
+
+ subreq = cli_posix_lock_send(
+ state,
+ state->ev,
+ state->cli1,
+ state->fnum1,
+ 0,
+ 1,
+ false,
+ UNLOCK_LOCK);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
+}
+
+static void posix_blocking_unlocked(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ NTSTATUS status;
+
+ status = cli_posix_lock_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ /* tevent_req_done in posix_blocking_gotlocked */
+}
+
+static NTSTATUS posix_blocking_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
+}
+
+static bool run_posix_blocking_lock(int dummy)
+{
+ struct tevent_context *ev = NULL;
+ struct cli_state *cli1 = NULL, *cli2 = NULL;
+ const char *fname = "posix_blocking";
+ uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
+ struct tevent_req *req = NULL;
+ NTSTATUS status;
+ bool ret = false;
+ bool ok;
+
+ printf("Starting posix blocking lock test\n");
+
+ ev = samba_tevent_context_init(NULL);
+ if (ev == NULL) {
+ return false;
+ }
+
+ ok = torture_open_connection(&cli1, 0);
+ if (!ok) {
+ goto fail;
+ }
+ ok = torture_open_connection(&cli2, 0);
+ if (!ok) {
+ goto fail;
+ }
+
+ smbXcli_conn_set_sockopt(cli1->conn, sockops);
+
+ status = torture_setup_unix_extensions(cli1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+
+ cli_setatr(cli1, fname, 0, 0);
+ cli_posix_unlink(cli1, fname);
+
+ status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
+ 0600, &fnum1);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("First POSIX open of %s failed: %s\n",
+ fname,
+ nt_errstr(status));
+ goto fail;
+ }
+
+ status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Second POSIX open of %s failed: %s\n",
+ fname,
+ nt_errstr(status));
+ goto fail;
+ }
+
+ req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
+ if (req == NULL) {
+ printf("cli_posix_blocking failed\n");
+ goto fail;
+ }
+
+ ok = tevent_req_poll_ntstatus(req, ev, &status);
+ if (!ok) {
+ printf("tevent_req_poll_ntstatus failed: %s\n",
+ nt_errstr(status));
+ goto fail;
+ }
+ status = posix_blocking_recv(req);
+ TALLOC_FREE(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("posix_blocking_recv returned %s\n",
+ nt_errstr(status));
+ goto fail;
+ }
+
+ ret = true;
+fail:
+
+ if (fnum1 != UINT16_MAX) {
+ cli_close(cli1, fnum1);
+ fnum1 = UINT16_MAX;
+ }
+ if (fnum2 != UINT16_MAX) {
+ cli_close(cli2, fnum2);
+ fnum2 = UINT16_MAX;
+ }
+
+ if (cli1 != NULL) {
+ cli_setatr(cli1, fname, 0, 0);
+ cli_posix_unlink(cli1, fname);
+ }
+
+ ok = true;
+
+ if (cli1 != NULL) {
+ ok &= torture_close_connection(cli1);
+ cli1 = NULL;
+ }
+ if (cli2 != NULL) {
+ ok &= torture_close_connection(cli2);
+ cli2 = NULL;
+ }
+
+ if (!ok) {
+ ret = false;
+ }
+ TALLOC_FREE(ev);
+ return ret;
+}
+
/*
Test POSIX mkdir is case-sensitive.
*/
@@ -12401,6 +12678,10 @@ static struct {
.fn = run_posix_ofd_lock_test,
},
{
+ .name = "POSIX-BLOCKING-LOCK",
+ .fn = run_posix_blocking_lock,
+ },
+ {
.name = "POSIX-MKDIR",
.fn = run_posix_mkdir_test,
},