2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Volker Lendecke 2017
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.
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.
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/>.
21 #include "torture/proto.h"
22 #include "system/filesys.h"
25 #include "lib/util/server_id.h"
26 #include "lib/util/sys_rw.h"
27 #include "lib/util/util_tdb.h"
28 #include "lib/util/tevent_ntstatus.h"
29 #include "lib/global_contexts.h"
31 static bool get_g_lock_ctx(TALLOC_CTX *mem_ctx,
32 struct tevent_context **ev,
33 struct messaging_context **msg,
34 struct g_lock_ctx **ctx)
36 *ev = global_event_context();
38 fprintf(stderr, "tevent_context_init failed\n");
41 *msg = global_messaging_context();
43 fprintf(stderr, "messaging_init failed\n");
47 *ctx = g_lock_ctx_init(*ev, *msg);
49 fprintf(stderr, "g_lock_ctx_init failed\n");
58 bool run_g_lock1(int dummy)
60 struct tevent_context *ev = NULL;
61 struct messaging_context *msg = NULL;
62 struct g_lock_ctx *ctx = NULL;
63 const char *lockname = "lock1";
68 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
73 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_WRITE,
74 (struct timeval) { .tv_sec = 1 },
76 if (!NT_STATUS_IS_OK(status)) {
77 fprintf(stderr, "g_lock_lock failed: %s\n",
82 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_WRITE,
83 (struct timeval) { .tv_sec = 1 },
85 if (!NT_STATUS_EQUAL(status, NT_STATUS_WAS_LOCKED)) {
86 fprintf(stderr, "Double lock got %s\n",
91 status = g_lock_unlock(ctx, string_term_tdb_data(lockname));
92 if (!NT_STATUS_IS_OK(status)) {
93 fprintf(stderr, "g_lock_unlock failed: %s\n",
98 status = g_lock_unlock(ctx, string_term_tdb_data(lockname));
99 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
100 fprintf(stderr, "g_lock_unlock returned: %s\n",
113 struct lock2_parser_state {
118 static void lock2_parser(struct server_id exclusive,
120 const struct server_id *shared,
125 struct lock2_parser_state *state = private_data;
127 if (datalen != sizeof(uint8_t)) {
130 *state->rdata = *data;
135 * Test g_lock_write_data
138 bool run_g_lock2(int dummy)
140 struct tevent_context *ev = NULL;
141 struct messaging_context *msg = NULL;
142 struct g_lock_ctx *ctx = NULL;
143 const char *lockname = "lock2";
146 struct lock2_parser_state state = { .rdata = &rdata };
151 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
156 status = g_lock_write_data(ctx, string_term_tdb_data(lockname),
157 &data, sizeof(data));
158 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_LOCKED)) {
159 fprintf(stderr, "unlocked g_lock_write_data returned %s\n",
164 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_WRITE,
165 (struct timeval) { .tv_sec = 1 },
167 if (!NT_STATUS_IS_OK(status)) {
168 fprintf(stderr, "g_lock_lock returned %s\n",
173 status = g_lock_write_data(ctx, string_term_tdb_data(lockname),
174 &data, sizeof(data));
175 if (!NT_STATUS_IS_OK(status)) {
176 fprintf(stderr, "g_lock_write_data failed: %s\n",
181 status = g_lock_unlock(ctx, string_term_tdb_data(lockname));
182 if (!NT_STATUS_IS_OK(status)) {
183 fprintf(stderr, "g_lock_unlock failed: %s\n",
188 status = g_lock_dump(ctx, string_term_tdb_data(lockname),
189 lock2_parser, &state);
190 if (!NT_STATUS_IS_OK(status)) {
191 fprintf(stderr, "g_lock_dump failed: %s\n",
197 fprintf(stderr, "Could not parse data\n");
201 fprintf(stderr, "Returned %"PRIu8", expected %"PRIu8"\n",
214 struct lock3_parser_state {
215 struct server_id self;
216 enum g_lock_type lock_type;
220 static void lock3_parser(struct server_id exclusive,
222 const struct server_id *shared,
227 struct lock3_parser_state *state = private_data;
228 size_t num_locks = num_shared + ((exclusive.pid != 0) ? 1 : 0);
229 const struct server_id *pid;
232 fprintf(stderr, "datalen=%zu\n", datalen);
235 if (num_locks != 1) {
236 fprintf(stderr, "num_locks=%zu\n", num_locks);
240 if (state->lock_type == G_LOCK_WRITE) {
241 if (exclusive.pid == 0) {
242 fprintf(stderr, "Found READ, expected WRITE\n");
246 if (exclusive.pid != 0) {
247 fprintf(stderr, "Found WRITE, expected READ\n");
252 pid = (exclusive.pid != 0) ? &exclusive : &shared[0];
254 if (!server_id_equal(pid, &state->self)) {
255 struct server_id_buf tmp1, tmp2;
256 fprintf(stderr, "found pid %s, expected %s\n",
257 server_id_str_buf(*pid, &tmp1),
258 server_id_str_buf(state->self, &tmp2));
266 * Test lock upgrade/downgrade
269 bool run_g_lock3(int dummy)
271 struct tevent_context *ev = NULL;
272 struct messaging_context *msg = NULL;
273 struct g_lock_ctx *ctx = NULL;
274 const char *lockname = "lock3";
275 struct lock3_parser_state state;
280 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
285 state.self = messaging_server_id(msg);
287 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_READ,
288 (struct timeval) { .tv_sec = 1 },
290 if (!NT_STATUS_IS_OK(status)) {
291 fprintf(stderr, "g_lock_lock returned %s\n",
296 state.lock_type = G_LOCK_READ;
299 status = g_lock_dump(ctx, string_term_tdb_data(lockname),
300 lock3_parser, &state);
301 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
302 fprintf(stderr, "g_lock_dump returned %s\n",
310 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_UPGRADE,
311 (struct timeval) { .tv_sec = 1 },
313 if (!NT_STATUS_IS_OK(status)) {
314 fprintf(stderr, "g_lock_lock returned %s\n",
319 state.lock_type = G_LOCK_WRITE;
322 status = g_lock_dump(ctx, string_term_tdb_data(lockname),
323 lock3_parser, &state);
324 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
325 fprintf(stderr, "g_lock_dump returned %s\n",
342 static bool lock4_child(const char *lockname,
343 enum g_lock_type lock_type,
347 struct tevent_context *ev = NULL;
348 struct messaging_context *msg = NULL;
349 struct g_lock_ctx *ctx = NULL;
354 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
359 status = g_lock_lock(
361 string_term_tdb_data(lockname),
363 (struct timeval) { .tv_sec = 1 },
366 if (!NT_STATUS_IS_OK(status)) {
367 fprintf(stderr, "child: g_lock_lock returned %s\n",
372 n = sys_write(ready_pipe, &ok, sizeof(ok));
373 if (n != sizeof(ok)) {
374 fprintf(stderr, "child: write failed\n");
379 n = sys_read(exit_pipe, &ok, sizeof(ok));
381 fprintf(stderr, "child: read failed\n");
389 static void lock4_done(struct tevent_req *subreq)
391 int *done = tevent_req_callback_data_void(subreq);
394 status = g_lock_lock_recv(subreq);
396 if (!NT_STATUS_IS_OK(status)) {
397 fprintf(stderr, "g_lock_lock_recv returned %s\n",
405 static void lock4_waited(struct tevent_req *subreq)
407 int *exit_pipe = tevent_req_callback_data_void(subreq);
414 ok = tevent_wakeup_recv(subreq);
417 fprintf(stderr, "tevent_wakeup_recv failed\n");
421 child = wait(&status);
423 printf("child %d exited with %d\n", (int)child, status);
426 struct lock4_check_state {
431 static void lock4_check(struct server_id exclusive,
433 const struct server_id *shared,
438 struct lock4_check_state *state = private_data;
439 size_t num_locks = num_shared + ((exclusive.pid != 0) ? 1 : 0);
441 if (num_locks != 1) {
442 fprintf(stderr, "num_locks=%zu\n", num_locks);
446 if (exclusive.pid == 0) {
447 fprintf(stderr, "Wrong lock type, not WRITE\n");
451 if (!server_id_equal(&state->me, &exclusive)) {
452 struct server_id_buf buf1, buf2;
453 fprintf(stderr, "me=%s, locker=%s\n",
454 server_id_str_buf(state->me, &buf1),
455 server_id_str_buf(exclusive, &buf2));
463 * Test a lock conflict: Contend with a WRITE lock
466 bool run_g_lock4(int dummy)
468 struct tevent_context *ev = NULL;
469 struct messaging_context *msg = NULL;
470 struct g_lock_ctx *ctx = NULL;
471 const char *lockname = "lock4";
472 TDB_DATA key = string_term_tdb_data(lockname);
478 struct tevent_req *req;
482 if ((pipe(ready_pipe) != 0) || (pipe(exit_pipe) != 0)) {
483 perror("pipe failed");
489 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
495 perror("fork failed");
500 close(ready_pipe[0]);
503 lockname, G_LOCK_WRITE, ready_pipe[1], exit_pipe[0]);
507 close(ready_pipe[1]);
510 if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
511 perror("read failed");
516 fprintf(stderr, "child returned error\n");
520 status = g_lock_lock(ctx, key, G_LOCK_WRITE,
521 (struct timeval) { .tv_usec = 1 },
523 if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
524 fprintf(stderr, "g_lock_lock returned %s\n",
529 status = g_lock_lock(ctx, key, G_LOCK_READ,
530 (struct timeval) { .tv_usec = 1 },
532 if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
533 fprintf(stderr, "g_lock_lock returned %s\n",
538 req = g_lock_lock_send(ev, ev, ctx, key, G_LOCK_WRITE, NULL, NULL);
540 fprintf(stderr, "g_lock_lock send failed\n");
543 tevent_req_set_callback(req, lock4_done, &done);
545 req = tevent_wakeup_send(ev, ev, timeval_current_ofs(1, 0));
547 fprintf(stderr, "tevent_wakeup_send failed\n");
550 tevent_req_set_callback(req, lock4_waited, &exit_pipe[1]);
555 int tevent_ret = tevent_loop_once(ev);
556 if (tevent_ret != 0) {
557 perror("tevent_loop_once failed");
563 struct lock4_check_state state = {
564 .me = messaging_server_id(msg)
567 status = g_lock_dump(ctx, key, lock4_check, &state);
568 if (!NT_STATUS_IS_OK(status)) {
569 fprintf(stderr, "g_lock_dump failed: %s\n",
574 fprintf(stderr, "lock4_check failed\n");
588 * Test a lock conflict: Contend with a READ lock
591 bool run_g_lock4a(int dummy)
593 struct tevent_context *ev = NULL;
594 struct messaging_context *msg = NULL;
595 struct g_lock_ctx *ctx = NULL;
596 const char *lockname = "lock4a";
597 TDB_DATA key = string_term_tdb_data(lockname);
603 struct tevent_req *req;
607 if ((pipe(ready_pipe) != 0) || (pipe(exit_pipe) != 0)) {
608 perror("pipe failed");
614 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
620 perror("fork failed");
625 close(ready_pipe[0]);
628 lockname, G_LOCK_READ, ready_pipe[1], exit_pipe[0]);
632 close(ready_pipe[1]);
635 if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
636 perror("read failed");
641 fprintf(stderr, "child returned error\n");
645 status = g_lock_lock(ctx, key, G_LOCK_WRITE,
646 (struct timeval) { .tv_usec = 1 },
648 if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
649 fprintf(stderr, "g_lock_lock returned %s\n",
654 status = g_lock_lock(ctx, key, G_LOCK_READ,
655 (struct timeval) { .tv_usec = 1 },
657 if (!NT_STATUS_IS_OK(status)) {
658 fprintf(stderr, "g_lock_lock returned %s\n",
663 status = g_lock_unlock(ctx, key);
664 if (!NT_STATUS_IS_OK(status)) {
666 "g_lock_unlock returned %s\n",
671 req = g_lock_lock_send(ev, ev, ctx, key, G_LOCK_WRITE, NULL, NULL);
673 fprintf(stderr, "g_lock_lock send failed\n");
676 tevent_req_set_callback(req, lock4_done, &done);
678 req = tevent_wakeup_send(ev, ev, timeval_current_ofs(1, 0));
680 fprintf(stderr, "tevent_wakeup_send failed\n");
683 tevent_req_set_callback(req, lock4_waited, &exit_pipe[1]);
688 int tevent_ret = tevent_loop_once(ev);
689 if (tevent_ret != 0) {
690 perror("tevent_loop_once failed");
696 struct lock4_check_state state = {
697 .me = messaging_server_id(msg)
700 status = g_lock_dump(ctx, key, lock4_check, &state);
701 if (!NT_STATUS_IS_OK(status)) {
702 fprintf(stderr, "g_lock_dump failed: %s\n",
707 fprintf(stderr, "lock4_check failed\n");
720 struct lock5_parser_state {
724 static void lock5_parser(struct server_id exclusive,
726 const struct server_id *shared,
731 struct lock5_parser_state *state = private_data;
732 state->num_locks = num_shared + ((exclusive.pid != 0) ? 1 : 0);
736 * Test heuristic cleanup
739 bool run_g_lock5(int dummy)
741 struct tevent_context *ev = NULL;
742 struct messaging_context *msg = NULL;
743 struct g_lock_ctx *ctx = NULL;
744 const char *lockname = "lock5";
746 int exit_pipe[2], ready_pipe[2];
756 if ((pipe(exit_pipe) != 0) || (pipe(ready_pipe) != 0)) {
757 perror("pipe failed");
761 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
763 fprintf(stderr, "get_g_lock_ctx failed");
767 for (i=0; i<nprocs; i++) {
772 perror("fork failed");
779 status = reinit_after_fork(msg, ev, false, "");
781 close(ready_pipe[0]);
784 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
786 fprintf(stderr, "get_g_lock_ctx failed");
789 status = g_lock_lock(ctx,
790 string_term_tdb_data(lockname),
792 (struct timeval) { .tv_sec = 1 },
794 if (!NT_STATUS_IS_OK(status)) {
796 "child g_lock_lock failed %s\n",
800 close(ready_pipe[1]);
801 nread = sys_read(exit_pipe[0], &c, sizeof(c));
803 fprintf(stderr, "sys_read returned %zu (%s)\n",
804 nread, strerror(errno));
811 close(ready_pipe[1]);
813 nread = sys_read(ready_pipe[0], &c, sizeof(c));
815 fprintf(stderr, "sys_read returned %zu (%s)\n",
816 nread, strerror(errno));
822 for (i=0; i<nprocs; i++) {
824 ret = waitpid(-1, &child_status, 0);
826 perror("waitpid failed");
831 for (i=0; i<nprocs; i++) {
832 struct lock5_parser_state state;
834 status = g_lock_dump(ctx, string_term_tdb_data(lockname),
835 lock5_parser, &state);
836 if (!NT_STATUS_IS_OK(status)) {
837 fprintf(stderr, "g_lock_dump returned %s\n",
842 if (state.num_locks != (nprocs - i)) {
843 fprintf(stderr, "nlocks=%zu, expected %zu\n",
844 state.num_locks, (nprocs-i));
848 status = g_lock_lock(ctx, string_term_tdb_data(lockname),
850 (struct timeval) { .tv_sec = 1 },
852 if (!NT_STATUS_IS_OK(status)) {
853 fprintf(stderr, "g_lock_lock failed %s\n",
857 status = g_lock_unlock(ctx, string_term_tdb_data(lockname));
858 if (!NT_STATUS_IS_OK(status)) {
859 fprintf(stderr, "g_lock_unlock failed %s\n",
869 struct lock6_parser_state {
873 static void lock6_parser(struct server_id exclusive,
875 const struct server_id *shared,
880 struct lock6_parser_state *state = private_data;
881 state->num_locks = num_shared + ((exclusive.pid != 0) ? 1 : 0);
885 * Test cleanup with contention and stale locks
888 bool run_g_lock6(int dummy)
890 struct tevent_context *ev = NULL;
891 struct messaging_context *msg = NULL;
892 struct g_lock_ctx *ctx = NULL;
893 TDB_DATA lockname = string_term_tdb_data("lock6");
895 int exit_pipe[2], ready_pipe[2];
903 if ((pipe(exit_pipe) != 0) || (pipe(ready_pipe) != 0)) {
904 perror("pipe failed");
908 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
910 fprintf(stderr, "get_g_lock_ctx failed");
915 * Wipe all stale locks -- in clustered mode there's no
918 status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
919 (struct timeval) { .tv_sec = 1 },
921 if (!NT_STATUS_IS_OK(status)) {
922 fprintf(stderr, "g_lock_lock failed: %s\n",
926 status = g_lock_unlock(ctx, lockname);
927 if (!NT_STATUS_IS_OK(status)) {
928 fprintf(stderr, "g_lock_unlock failed: %s\n",
934 for (i=0; i<nprocs; i++) {
939 perror("fork failed");
946 status = reinit_after_fork(msg, ev, false, "");
947 if (!NT_STATUS_IS_OK(status)) {
948 fprintf(stderr, "reinit_after_fork failed: %s\n",
953 close(ready_pipe[0]);
956 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
958 fprintf(stderr, "get_g_lock_ctx failed");
961 status = g_lock_lock(ctx,
964 (struct timeval) { .tv_sec = 1 },
966 if (!NT_STATUS_IS_OK(status)) {
968 "child g_lock_lock failed %s\n",
975 close(ready_pipe[1]);
976 nread = sys_read(exit_pipe[0], &c, sizeof(c));
978 fprintf(stderr, "sys_read returned %zu (%s)\n",
979 nread, strerror(errno));
986 close(ready_pipe[1]);
988 nread = sys_read(ready_pipe[0], &c, sizeof(c));
990 fprintf(stderr, "sys_read returned %zd (%s)\n",
991 nread, strerror(errno));
997 ret = waitpid(-1, &child_status, 0);
999 perror("waitpid failed");
1005 struct lock6_parser_state state;
1007 status = g_lock_dump(ctx, lockname, lock6_parser, &state);
1008 if (!NT_STATUS_IS_OK(status)) {
1009 fprintf(stderr, "g_lock_dump returned %s\n",
1014 if (state.num_locks != nprocs) {
1015 fprintf(stderr, "nlocks=%zu, expected %zu\n",
1016 state.num_locks, nprocs);
1020 status = g_lock_lock(ctx,
1023 (struct timeval) { .tv_sec = 1 },
1025 if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1026 fprintf(stderr, "g_lock_lock should have failed with %s - %s\n",
1027 nt_errstr(NT_STATUS_IO_TIMEOUT),
1032 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
1033 (struct timeval) { .tv_sec = 1 },
1035 if (!NT_STATUS_IS_OK(status)) {
1036 fprintf(stderr, "g_lock_lock failed: %s\n",
1042 close(exit_pipe[1]);
1046 ret = waitpid(-1, &child_status, 0);
1048 perror("waitpid failed");
1053 status = g_lock_lock(ctx, lockname, G_LOCK_UPGRADE,
1054 (struct timeval) { .tv_sec = 1 },
1056 if (!NT_STATUS_IS_OK(status)) {
1057 fprintf(stderr, "g_lock_lock failed: %s\n",
1066 * Test upgrade deadlock
1069 bool run_g_lock7(int dummy)
1071 struct tevent_context *ev = NULL;
1072 struct messaging_context *msg = NULL;
1073 struct g_lock_ctx *ctx = NULL;
1074 const char *lockname = "lock7";
1075 TDB_DATA key = string_term_tdb_data(lockname);
1084 if ((pipe(ready_pipe) != 0) || (pipe(down_pipe) != 0)) {
1085 perror("pipe failed");
1091 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
1097 perror("fork failed");
1102 struct tevent_req *req = NULL;
1104 close(ready_pipe[0]);
1106 close(down_pipe[1]);
1109 status = reinit_after_fork(msg, ev, false, "");
1110 if (!NT_STATUS_IS_OK(status)) {
1112 "reinit_after_fork failed: %s\n",
1117 printf("%d: locking READ\n", (int)getpid());
1119 status = g_lock_lock(
1123 (struct timeval) { .tv_usec = 1 },
1125 if (!NT_STATUS_IS_OK(status)) {
1127 "g_lock_lock(READ) failed: %s\n",
1134 n = sys_write(ready_pipe[1], &ok, sizeof(ok));
1135 if (n != sizeof(ok)) {
1137 "sys_write failed: %s\n",
1142 n = sys_read(down_pipe[0], &ok, sizeof(ok));
1143 if (n != sizeof(ok)) {
1145 "sys_read failed: %s\n",
1150 printf("%d: starting UPGRADE\n", (int)getpid());
1152 req = g_lock_lock_send(
1160 fprintf(stderr, "g_lock_lock_send(UPGRADE) failed\n");
1164 n = sys_write(ready_pipe[1], &ok, sizeof(ok));
1165 if (n != sizeof(ok)) {
1167 "sys_write failed: %s\n",
1175 close(ready_pipe[1]);
1176 close(down_pipe[0]);
1178 if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
1179 perror("read failed");
1183 fprintf(stderr, "child returned error\n");
1187 status = g_lock_lock(
1191 (struct timeval) { .tv_usec = 1 },
1193 if (!NT_STATUS_IS_OK(status)) {
1195 "g_lock_lock(READ) failed: %s\n",
1200 n = sys_write(down_pipe[1], &ok, sizeof(ok));
1201 if (n != sizeof(ok)) {
1203 "sys_write failed: %s\n",
1208 if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
1209 perror("read failed");
1213 status = g_lock_lock(
1217 (struct timeval) { .tv_sec = 10 },
1219 if (!NT_STATUS_EQUAL(status, NT_STATUS_POSSIBLE_DEADLOCK)) {
1221 "g_lock_lock returned %s\n",
1234 bool run_g_lock8(int dummy)
1236 struct tevent_context *ev = NULL;
1237 struct messaging_context *msg = NULL;
1238 struct g_lock_ctx *ctx = NULL;
1239 struct tevent_req *req = NULL;
1240 TDB_DATA lockname = string_term_tdb_data("lock8");
1244 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
1246 fprintf(stderr, "get_g_lock_ctx failed");
1250 req = g_lock_watch_data_send(
1251 ev, ev, ctx, lockname, (struct server_id) { .pid = 0 });
1253 fprintf(stderr, "get_g_lock_ctx failed");
1257 status = g_lock_lock(
1261 (struct timeval) { .tv_sec = 999 },
1263 if (!NT_STATUS_IS_OK(status)) {
1265 "g_lock_lock failed: %s\n",
1270 status = g_lock_write_data(
1271 ctx, lockname, lockname.dptr, lockname.dsize);
1272 if (!NT_STATUS_IS_OK(status)) {
1274 "g_lock_write_data failed: %s\n",
1279 status = g_lock_write_data(ctx, lockname, NULL, 0);
1280 if (!NT_STATUS_IS_OK(status)) {
1282 "g_lock_write_data failed: %s\n",
1287 status = g_lock_unlock(ctx, lockname);
1288 if (!NT_STATUS_IS_OK(status)) {
1290 "g_lock_unlock failed: %s\n",
1295 ok = tevent_req_poll_ntstatus(req, ev, &status);
1297 fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
1300 if (!NT_STATUS_IS_OK(status)) {
1302 "tevent_req_poll_ntstatus failed: %s\n",
1310 extern int torture_numops;
1311 extern int torture_nprocs;
1313 static struct timeval tp1, tp2;
1315 static void start_timer(void)
1317 gettimeofday(&tp1,NULL);
1320 static double end_timer(void)
1322 gettimeofday(&tp2,NULL);
1323 return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) -
1324 (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
1331 bool run_g_lock_ping_pong(int dummy)
1333 struct tevent_context *ev = NULL;
1334 struct messaging_context *msg = NULL;
1335 struct g_lock_ctx *ctx = NULL;
1343 torture_nprocs = MAX(2, torture_nprocs);
1345 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
1352 snprintf(name, sizeof(name), "ping_pong_%d", i);
1354 status = g_lock_lock(ctx, string_term_tdb_data(name), G_LOCK_WRITE,
1355 (struct timeval) { .tv_sec = 60 },
1357 if (!NT_STATUS_IS_OK(status)) {
1358 fprintf(stderr, "g_lock_lock failed: %s\n",
1363 for (i=0; i<torture_numops; i++) {
1365 name[10] = '0' + ((i+1) % torture_nprocs);
1367 status = g_lock_lock(ctx, string_term_tdb_data(name),
1369 (struct timeval) { .tv_sec = 60 },
1371 if (!NT_STATUS_IS_OK(status)) {
1372 fprintf(stderr, "g_lock_lock failed: %s\n",
1377 name[10] = '0' + ((i) % torture_nprocs);
1379 status = g_lock_unlock(ctx, string_term_tdb_data(name));
1380 if (!NT_STATUS_IS_OK(status)) {
1381 fprintf(stderr, "g_lock_unlock failed: %s\n",
1388 if (end_timer() > 1.0) {
1389 printf("%8u locks/sec\r",
1390 (unsigned)(2*count/end_timer()));