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()));