libnet: Add NULL checks to py_net_finddc
[Samba.git] / source3 / torture / test_g_lock.c
blob718c196bfe69bb078abcf434c8ea81aad05d3027
1 /*
2 * Unix SMB/CIFS implementation.
3 * Test g_lock API
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/>.
20 #include "includes.h"
21 #include "torture/proto.h"
22 #include "system/filesys.h"
23 #include "g_lock.h"
24 #include "messages.h"
25 #include "lib/util/server_id.h"
26 #include "lib/util/sys_rw.h"
28 static bool get_g_lock_ctx(TALLOC_CTX *mem_ctx,
29 struct tevent_context **ev,
30 struct messaging_context **msg,
31 struct g_lock_ctx **ctx)
33 *ev = server_event_context();
34 if (*ev == NULL) {
35 fprintf(stderr, "tevent_context_init failed\n");
36 return false;
38 *msg = server_messaging_context();
39 if (*msg == NULL) {
40 fprintf(stderr, "messaging_init failed\n");
41 TALLOC_FREE(*ev);
42 return false;
44 *ctx = g_lock_ctx_init(*ev, *msg);
45 if (*ctx == NULL) {
46 fprintf(stderr, "g_lock_ctx_init failed\n");
47 TALLOC_FREE(*msg);
48 TALLOC_FREE(*ev);
49 return false;
52 return true;
55 bool run_g_lock1(int dummy)
57 struct tevent_context *ev = NULL;
58 struct messaging_context *msg = NULL;
59 struct g_lock_ctx *ctx = NULL;
60 const char *lockname = "lock1";
61 NTSTATUS status;
62 bool ret = false;
63 bool ok;
65 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
66 if (!ok) {
67 goto fail;
70 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
71 (struct timeval) { .tv_sec = 1 });
72 if (!NT_STATUS_IS_OK(status)) {
73 fprintf(stderr, "g_lock_lock failed: %s\n",
74 nt_errstr(status));
75 goto fail;
78 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
79 (struct timeval) { .tv_sec = 1 });
80 if (!NT_STATUS_EQUAL(status, NT_STATUS_WAS_LOCKED)) {
81 fprintf(stderr, "Double lock got %s\n",
82 nt_errstr(status));
83 goto fail;
86 status = g_lock_unlock(ctx, lockname);
87 if (!NT_STATUS_IS_OK(status)) {
88 fprintf(stderr, "g_lock_unlock failed: %s\n",
89 nt_errstr(status));
90 goto fail;
93 status = g_lock_unlock(ctx, lockname);
94 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
95 fprintf(stderr, "g_lock_unlock returned: %s\n",
96 nt_errstr(status));
97 goto fail;
100 ret = true;
101 fail:
102 TALLOC_FREE(ctx);
103 TALLOC_FREE(msg);
104 TALLOC_FREE(ev);
105 return ret;
108 struct lock2_parser_state {
109 uint8_t *rdata;
110 bool ok;
113 static void lock2_parser(const struct g_lock_rec *locks,
114 size_t num_locks,
115 const uint8_t *data,
116 size_t datalen,
117 void *private_data)
119 struct lock2_parser_state *state = private_data;
121 if (datalen != sizeof(uint8_t)) {
122 return;
124 *state->rdata = *data;
125 state->ok = true;
129 * Test g_lock_write_data
132 bool run_g_lock2(int dummy)
134 struct tevent_context *ev = NULL;
135 struct messaging_context *msg = NULL;
136 struct g_lock_ctx *ctx = NULL;
137 const char *lockname = "lock2";
138 uint8_t data = 42;
139 uint8_t rdata;
140 struct lock2_parser_state state = { .rdata = &rdata };
141 NTSTATUS status;
142 bool ret = false;
143 bool ok;
145 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
146 if (!ok) {
147 goto fail;
150 status = g_lock_write_data(ctx, lockname, &data, sizeof(data));
151 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_LOCKED)) {
152 fprintf(stderr, "unlocked g_lock_write_data returned %s\n",
153 nt_errstr(status));
154 goto fail;
157 status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
158 (struct timeval) { .tv_sec = 1 });
159 if (!NT_STATUS_IS_OK(status)) {
160 fprintf(stderr, "g_lock_lock returned %s\n",
161 nt_errstr(status));
162 goto fail;
165 status = g_lock_write_data(ctx, lockname, &data, sizeof(data));
166 if (!NT_STATUS_IS_OK(status)) {
167 fprintf(stderr, "g_lock_write_data failed: %s\n",
168 nt_errstr(status));
169 goto fail;
172 status = g_lock_unlock(ctx, lockname);
173 if (!NT_STATUS_IS_OK(status)) {
174 fprintf(stderr, "g_lock_unlock failed: %s\n",
175 nt_errstr(status));
176 goto fail;
179 status = g_lock_dump(ctx, lockname, lock2_parser, &state);
180 if (!NT_STATUS_IS_OK(status)) {
181 fprintf(stderr, "g_lock_dump failed: %s\n",
182 nt_errstr(status));
183 goto fail;
186 if (!state.ok) {
187 fprintf(stderr, "Could not parse data\n");
188 goto fail;
190 if (rdata != data) {
191 fprintf(stderr, "Returned %"PRIu8", expected %"PRIu8"\n",
192 rdata, data);
193 goto fail;
196 ret = true;
197 fail:
198 TALLOC_FREE(ctx);
199 TALLOC_FREE(msg);
200 TALLOC_FREE(ev);
201 return ret;
204 struct lock3_parser_state {
205 struct server_id self;
206 enum g_lock_type lock_type;
207 bool ok;
210 static void lock3_parser(const struct g_lock_rec *locks,
211 size_t num_locks,
212 const uint8_t *data,
213 size_t datalen,
214 void *private_data)
216 struct lock3_parser_state *state = private_data;
218 if (datalen != 0) {
219 fprintf(stderr, "datalen=%zu\n", datalen);
220 return;
222 if (num_locks != 1) {
223 fprintf(stderr, "num_locks=%zu\n", num_locks);
224 return;
226 if (locks[0].lock_type != state->lock_type) {
227 fprintf(stderr, "found type %d, expected %d\n",
228 (int)locks[0].lock_type, (int)state->lock_type);
229 return;
231 if (!server_id_equal(&locks[0].pid, &state->self)) {
232 struct server_id_buf tmp1, tmp2;
233 fprintf(stderr, "found pid %s, expected %s\n",
234 server_id_str_buf(locks[0].pid, &tmp1),
235 server_id_str_buf(state->self, &tmp2));
236 return;
239 state->ok = true;
243 * Test lock upgrade/downgrade
246 bool run_g_lock3(int dummy)
248 struct tevent_context *ev = NULL;
249 struct messaging_context *msg = NULL;
250 struct g_lock_ctx *ctx = NULL;
251 const char *lockname = "lock3";
252 struct lock3_parser_state state;
253 NTSTATUS status;
254 bool ret = false;
255 bool ok;
257 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
258 if (!ok) {
259 goto fail;
262 state.self = messaging_server_id(msg);
264 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
265 (struct timeval) { .tv_sec = 1 });
266 if (!NT_STATUS_IS_OK(status)) {
267 fprintf(stderr, "g_lock_lock returned %s\n",
268 nt_errstr(status));
269 goto fail;
272 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
273 (struct timeval) { .tv_sec = 1 });
274 if (!NT_STATUS_EQUAL(status, NT_STATUS_WAS_LOCKED)) {
275 fprintf(stderr, "g_lock_lock returned %s, expected %s\n",
276 nt_errstr(status), nt_errstr(NT_STATUS_WAS_LOCKED));
277 goto fail;
280 state.lock_type = G_LOCK_READ;
281 state.ok = false;
283 status = g_lock_dump(ctx, lockname, lock3_parser, &state);
284 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
285 fprintf(stderr, "g_lock_dump returned %s\n",
286 nt_errstr(status));
287 goto fail;
289 if (!state.ok) {
290 goto fail;
293 status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
294 (struct timeval) { .tv_sec = 1 });
295 if (!NT_STATUS_IS_OK(status)) {
296 fprintf(stderr, "g_lock_lock returned %s\n",
297 nt_errstr(status));
298 goto fail;
301 state.lock_type = G_LOCK_WRITE;
302 state.ok = false;
304 status = g_lock_dump(ctx, lockname, lock3_parser, &state);
305 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
306 fprintf(stderr, "g_lock_dump returned %s\n",
307 nt_errstr(status));
308 goto fail;
310 if (!state.ok) {
311 goto fail;
315 ret = true;
316 fail:
317 TALLOC_FREE(ctx);
318 TALLOC_FREE(msg);
319 TALLOC_FREE(ev);
320 return ret;
323 static bool lock4_child(const char *lockname,
324 int ready_pipe, int exit_pipe)
326 struct tevent_context *ev = NULL;
327 struct messaging_context *msg = NULL;
328 struct g_lock_ctx *ctx = NULL;
329 NTSTATUS status;
330 ssize_t n;
331 bool ok;
333 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
334 if (!ok) {
335 return false;
338 status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
339 (struct timeval) { .tv_sec = 1 });
340 if (!NT_STATUS_IS_OK(status)) {
341 fprintf(stderr, "child: g_lock_lock returned %s\n",
342 nt_errstr(status));
343 return false;
346 n = sys_write(ready_pipe, &ok, sizeof(ok));
347 if (n != sizeof(ok)) {
348 fprintf(stderr, "child: write failed\n");
349 return false;
352 if (ok) {
353 n = sys_read(exit_pipe, &ok, sizeof(ok));
354 if (n != 0) {
355 fprintf(stderr, "child: read failed\n");
356 return false;
360 return true;
363 static void lock4_done(struct tevent_req *subreq)
365 int *done = tevent_req_callback_data_void(subreq);
366 NTSTATUS status;
368 status = g_lock_lock_recv(subreq);
369 TALLOC_FREE(subreq);
370 if (!NT_STATUS_IS_OK(status)) {
371 fprintf(stderr, "g_lock_lock_recv returned %s\n",
372 nt_errstr(status));
373 *done = -1;
374 return;
376 *done = 1;
379 static void lock4_waited(struct tevent_req *subreq)
381 int *exit_pipe = tevent_req_callback_data_void(subreq);
382 pid_t child;
383 int status;
384 bool ok;
386 printf("waited\n");
388 ok = tevent_wakeup_recv(subreq);
389 TALLOC_FREE(subreq);
390 if (!ok) {
391 fprintf(stderr, "tevent_wakeup_recv failed\n");
393 close(*exit_pipe);
395 child = wait(&status);
397 printf("child %d exited with %d\n", (int)child, status);
400 struct lock4_check_state {
401 struct server_id me;
402 bool ok;
405 static void lock4_check(const struct g_lock_rec *locks,
406 size_t num_locks,
407 const uint8_t *data,
408 size_t datalen,
409 void *private_data)
411 struct lock4_check_state *state = private_data;
413 if (num_locks != 1) {
414 fprintf(stderr, "num_locks=%zu\n", num_locks);
415 return;
418 if (!serverid_equal(&state->me, &locks[0].pid)) {
419 struct server_id_buf buf1, buf2;
420 fprintf(stderr, "me=%s, locker=%s\n",
421 server_id_str_buf(state->me, &buf1),
422 server_id_str_buf(locks[0].pid, &buf2));
423 return;
426 if (locks[0].lock_type != G_LOCK_WRITE) {
427 fprintf(stderr, "wrong lock type: %d\n",
428 (int)locks[0].lock_type);
429 return;
432 state->ok = true;
436 * Test a lock conflict
439 bool run_g_lock4(int dummy)
441 struct tevent_context *ev = NULL;
442 struct messaging_context *msg = NULL;
443 struct g_lock_ctx *ctx = NULL;
444 const char *lockname = "lock4";
445 pid_t child;
446 int ready_pipe[2];
447 int exit_pipe[2];
448 NTSTATUS status;
449 bool ret = false;
450 struct tevent_req *req;
451 bool ok;
452 int done;
454 if ((pipe(ready_pipe) != 0) || (pipe(exit_pipe) != 0)) {
455 perror("pipe failed");
456 return false;
459 child = fork();
461 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
462 if (!ok) {
463 goto fail;
466 if (child == -1) {
467 perror("fork failed");
468 return false;
471 if (child == 0) {
472 close(ready_pipe[0]);
473 close(exit_pipe[1]);
474 ok = lock4_child(lockname, ready_pipe[1], exit_pipe[0]);
475 exit(ok ? 0 : 1);
478 close(ready_pipe[1]);
479 close(exit_pipe[0]);
481 if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
482 perror("read failed");
483 return false;
486 if (!ok) {
487 fprintf(stderr, "child returned error\n");
488 return false;
491 status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
492 (struct timeval) { .tv_usec = 1 });
493 if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
494 fprintf(stderr, "g_lock_lock returned %s\n",
495 nt_errstr(status));
496 goto fail;
499 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
500 (struct timeval) { .tv_usec = 1 });
501 if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
502 fprintf(stderr, "g_lock_lock returned %s\n",
503 nt_errstr(status));
504 goto fail;
507 req = g_lock_lock_send(ev, ev, ctx, lockname, G_LOCK_WRITE);
508 if (req == NULL) {
509 fprintf(stderr, "g_lock_lock send failed\n");
510 goto fail;
512 tevent_req_set_callback(req, lock4_done, &done);
514 req = tevent_wakeup_send(ev, ev, timeval_current_ofs(1, 0));
515 if (req == NULL) {
516 fprintf(stderr, "tevent_wakeup_send failed\n");
517 goto fail;
519 tevent_req_set_callback(req, lock4_waited, &exit_pipe[1]);
521 done = 0;
523 while (done == 0) {
524 int tevent_ret = tevent_loop_once(ev);
525 if (tevent_ret != 0) {
526 perror("tevent_loop_once failed");
527 goto fail;
532 struct lock4_check_state state = {
533 .me = messaging_server_id(msg)
536 status = g_lock_dump(ctx, lockname, lock4_check, &state);
537 if (!NT_STATUS_IS_OK(status)) {
538 fprintf(stderr, "g_lock_dump failed: %s\n",
539 nt_errstr(status));
540 goto fail;
542 if (!state.ok) {
543 fprintf(stderr, "lock4_check failed\n");
544 goto fail;
548 ret = true;
549 fail:
550 TALLOC_FREE(ctx);
551 TALLOC_FREE(msg);
552 TALLOC_FREE(ev);
553 return ret;
556 struct lock5_parser_state {
557 size_t num_locks;
560 static void lock5_parser(const struct g_lock_rec *locks,
561 size_t num_locks,
562 const uint8_t *data,
563 size_t datalen,
564 void *private_data)
566 struct lock5_parser_state *state = private_data;
567 state->num_locks = num_locks;
571 * Test heuristic cleanup
574 bool run_g_lock5(int dummy)
576 struct tevent_context *ev = NULL;
577 struct messaging_context *msg = NULL;
578 struct g_lock_ctx *ctx = NULL;
579 const char *lockname = "lock5";
580 pid_t child;
581 int exit_pipe[2], ready_pipe[2];
582 NTSTATUS status;
583 size_t i, nprocs;
584 int ret;
585 bool ok;
586 ssize_t nread;
587 char c;
589 nprocs = 5;
591 if ((pipe(exit_pipe) != 0) || (pipe(ready_pipe) != 0)) {
592 perror("pipe failed");
593 return false;
596 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
597 if (!ok) {
598 fprintf(stderr, "get_g_lock_ctx failed");
599 return false;
602 for (i=0; i<nprocs; i++) {
604 child = fork();
606 if (child == -1) {
607 perror("fork failed");
608 return false;
611 if (child == 0) {
612 TALLOC_FREE(ctx);
614 status = reinit_after_fork(msg, ev, false, "");
616 close(ready_pipe[0]);
617 close(exit_pipe[1]);
619 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
620 if (!ok) {
621 fprintf(stderr, "get_g_lock_ctx failed");
622 exit(1);
624 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
625 (struct timeval) { .tv_sec = 1 });
626 if (!NT_STATUS_IS_OK(status)) {
627 fprintf(stderr,
628 "child g_lock_lock failed %s\n",
629 nt_errstr(status));
630 exit(1);
632 close(ready_pipe[1]);
633 nread = sys_read(exit_pipe[0], &c, sizeof(c));
634 if (nread != 0) {
635 fprintf(stderr, "sys_read returned %zu (%s)\n",
636 nread, strerror(errno));
637 exit(1);
639 exit(0);
643 close(ready_pipe[1]);
645 nread = sys_read(ready_pipe[0], &c, sizeof(c));
646 if (nread != 0) {
647 fprintf(stderr, "sys_read returned %zu (%s)\n",
648 nread, strerror(errno));
649 return false;
652 close(exit_pipe[1]);
654 for (i=0; i<nprocs; i++) {
655 int child_status;
656 ret = waitpid(-1, &child_status, 0);
657 if (ret == -1) {
658 perror("waitpid failed");
659 return false;
663 for (i=0; i<nprocs; i++) {
664 struct lock5_parser_state state;
666 status = g_lock_dump(ctx, lockname, lock5_parser, &state);
667 if (!NT_STATUS_IS_OK(status)) {
668 fprintf(stderr, "g_lock_dump returned %s\n",
669 nt_errstr(status));
670 return false;
673 if (state.num_locks != (nprocs - i)) {
674 fprintf(stderr, "nlocks=%zu, expected %zu\n",
675 state.num_locks, (nprocs-i));
676 return false;
679 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
680 (struct timeval) { .tv_sec = 1 });
681 if (!NT_STATUS_IS_OK(status)) {
682 fprintf(stderr, "g_lock_lock failed %s\n",
683 nt_errstr(status));
684 return false;
686 status = g_lock_unlock(ctx, lockname);
687 if (!NT_STATUS_IS_OK(status)) {
688 fprintf(stderr, "g_lock_unlock failed %s\n",
689 nt_errstr(status));
690 return false;
695 return true;
698 struct lock6_parser_state {
699 size_t num_locks;
702 static void lock6_parser(const struct g_lock_rec *locks,
703 size_t num_locks,
704 const uint8_t *data,
705 size_t datalen,
706 void *private_data)
708 struct lock6_parser_state *state = private_data;
709 state->num_locks = num_locks;
713 * Test cleanup with contention and stale locks
716 bool run_g_lock6(int dummy)
718 struct tevent_context *ev = NULL;
719 struct messaging_context *msg = NULL;
720 struct g_lock_ctx *ctx = NULL;
721 const char *lockname = "lock6";
722 pid_t child;
723 int exit_pipe[2], ready_pipe[2];
724 NTSTATUS status;
725 size_t i, nprocs;
726 int ret;
727 bool ok;
728 ssize_t nread;
729 char c;
731 if ((pipe(exit_pipe) != 0) || (pipe(ready_pipe) != 0)) {
732 perror("pipe failed");
733 return false;
736 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
737 if (!ok) {
738 fprintf(stderr, "get_g_lock_ctx failed");
739 return false;
742 nprocs = 2;
743 for (i=0; i<nprocs; i++) {
745 child = fork();
747 if (child == -1) {
748 perror("fork failed");
749 return false;
752 if (child == 0) {
753 TALLOC_FREE(ctx);
755 status = reinit_after_fork(msg, ev, false, "");
756 if (!NT_STATUS_IS_OK(status)) {
757 fprintf(stderr, "reinit_after_fork failed: %s\n",
758 nt_errstr(status));
759 exit(1);
762 close(ready_pipe[0]);
763 close(exit_pipe[1]);
765 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
766 if (!ok) {
767 fprintf(stderr, "get_g_lock_ctx failed");
768 exit(1);
770 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
771 (struct timeval) { .tv_sec = 1 });
772 if (!NT_STATUS_IS_OK(status)) {
773 fprintf(stderr,
774 "child g_lock_lock failed %s\n",
775 nt_errstr(status));
776 exit(1);
778 if (i == 0) {
779 exit(0);
781 close(ready_pipe[1]);
782 nread = sys_read(exit_pipe[0], &c, sizeof(c));
783 if (nread != 0) {
784 fprintf(stderr, "sys_read returned %zu (%s)\n",
785 nread, strerror(errno));
786 exit(1);
788 exit(0);
792 close(ready_pipe[1]);
794 nread = sys_read(ready_pipe[0], &c, sizeof(c));
795 if (nread != 0) {
796 fprintf(stderr, "sys_read returned %zd (%s)\n",
797 nread, strerror(errno));
798 return false;
802 int child_status;
803 ret = waitpid(-1, &child_status, 0);
804 if (ret == -1) {
805 perror("waitpid failed");
806 return false;
811 struct lock6_parser_state state;
813 status = g_lock_dump(ctx, lockname, lock6_parser, &state);
814 if (!NT_STATUS_IS_OK(status)) {
815 fprintf(stderr, "g_lock_dump returned %s\n",
816 nt_errstr(status));
817 return false;
820 if (state.num_locks != nprocs) {
821 fprintf(stderr, "nlocks=%zu, expected %zu\n",
822 state.num_locks, nprocs);
823 return false;
826 status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
827 (struct timeval) { .tv_sec = 1 });
828 if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
829 fprintf(stderr, "g_lock_lock should have failed with %s - %s\n",
830 nt_errstr(NT_STATUS_IO_TIMEOUT),
831 nt_errstr(status));
832 return false;
836 close(exit_pipe[1]);
839 int child_status;
840 ret = waitpid(-1, &child_status, 0);
841 if (ret == -1) {
842 perror("waitpid failed");
843 return false;
847 return true;
850 extern int torture_numops;
851 extern int torture_nprocs;
853 static struct timeval tp1, tp2;
855 static void start_timer(void)
857 gettimeofday(&tp1,NULL);
860 static double end_timer(void)
862 gettimeofday(&tp2,NULL);
863 return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) -
864 (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
868 * g_lock ping_pong
871 bool run_g_lock_ping_pong(int dummy)
873 struct tevent_context *ev = NULL;
874 struct messaging_context *msg = NULL;
875 struct g_lock_ctx *ctx = NULL;
876 fstring name;
877 NTSTATUS status;
878 int i = 0;
879 bool ret = false;
880 bool ok;
881 unsigned count = 0;
883 torture_nprocs = MAX(2, torture_nprocs);
885 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
886 if (!ok) {
887 goto fail;
890 start_timer();
892 snprintf(name, sizeof(name), "ping_pong_%d", i);
894 status = g_lock_lock(ctx, name, G_LOCK_WRITE,
895 (struct timeval) { .tv_sec = 60 });
896 if (!NT_STATUS_IS_OK(status)) {
897 fprintf(stderr, "g_lock_lock failed: %s\n",
898 nt_errstr(status));
899 goto fail;
902 for (i=0; i<torture_numops; i++) {
904 name[10] = '0' + ((i+1) % torture_nprocs);
906 status = g_lock_lock(ctx, name, G_LOCK_WRITE,
907 (struct timeval) { .tv_sec = 60 });
908 if (!NT_STATUS_IS_OK(status)) {
909 fprintf(stderr, "g_lock_lock failed: %s\n",
910 nt_errstr(status));
911 goto fail;
914 name[10] = '0' + ((i) % torture_nprocs);
916 status = g_lock_unlock(ctx, name);
917 if (!NT_STATUS_IS_OK(status)) {
918 fprintf(stderr, "g_lock_unlock failed: %s\n",
919 nt_errstr(status));
920 goto fail;
923 count++;
925 if (end_timer() > 1.0) {
926 printf("%8u locks/sec\r",
927 (unsigned)(2*count/end_timer()));
928 fflush(stdout);
929 start_timer();
930 count=0;
934 ret = true;
935 fail:
936 TALLOC_FREE(ctx);
937 TALLOC_FREE(msg);
938 TALLOC_FREE(ev);
939 return ret;