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 });
75 if (!NT_STATUS_IS_OK(status
)) {
76 fprintf(stderr
, "g_lock_lock failed: %s\n",
81 status
= g_lock_lock(ctx
, string_term_tdb_data(lockname
), G_LOCK_WRITE
,
82 (struct timeval
) { .tv_sec
= 1 });
83 if (!NT_STATUS_EQUAL(status
, NT_STATUS_WAS_LOCKED
)) {
84 fprintf(stderr
, "Double lock got %s\n",
89 status
= g_lock_unlock(ctx
, string_term_tdb_data(lockname
));
90 if (!NT_STATUS_IS_OK(status
)) {
91 fprintf(stderr
, "g_lock_unlock failed: %s\n",
96 status
= g_lock_unlock(ctx
, string_term_tdb_data(lockname
));
97 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
98 fprintf(stderr
, "g_lock_unlock returned: %s\n",
111 struct lock2_parser_state
{
116 static void lock2_parser(struct server_id exclusive
,
118 const struct server_id
*shared
,
123 struct lock2_parser_state
*state
= private_data
;
125 if (datalen
!= sizeof(uint8_t)) {
128 *state
->rdata
= *data
;
133 * Test g_lock_write_data
136 bool run_g_lock2(int dummy
)
138 struct tevent_context
*ev
= NULL
;
139 struct messaging_context
*msg
= NULL
;
140 struct g_lock_ctx
*ctx
= NULL
;
141 const char *lockname
= "lock2";
144 struct lock2_parser_state state
= { .rdata
= &rdata
};
149 ok
= get_g_lock_ctx(talloc_tos(), &ev
, &msg
, &ctx
);
154 status
= g_lock_write_data(ctx
, string_term_tdb_data(lockname
),
155 &data
, sizeof(data
));
156 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_LOCKED
)) {
157 fprintf(stderr
, "unlocked g_lock_write_data returned %s\n",
162 status
= g_lock_lock(ctx
, string_term_tdb_data(lockname
), G_LOCK_WRITE
,
163 (struct timeval
) { .tv_sec
= 1 });
164 if (!NT_STATUS_IS_OK(status
)) {
165 fprintf(stderr
, "g_lock_lock returned %s\n",
170 status
= g_lock_write_data(ctx
, string_term_tdb_data(lockname
),
171 &data
, sizeof(data
));
172 if (!NT_STATUS_IS_OK(status
)) {
173 fprintf(stderr
, "g_lock_write_data failed: %s\n",
178 status
= g_lock_unlock(ctx
, string_term_tdb_data(lockname
));
179 if (!NT_STATUS_IS_OK(status
)) {
180 fprintf(stderr
, "g_lock_unlock failed: %s\n",
185 status
= g_lock_dump(ctx
, string_term_tdb_data(lockname
),
186 lock2_parser
, &state
);
187 if (!NT_STATUS_IS_OK(status
)) {
188 fprintf(stderr
, "g_lock_dump failed: %s\n",
194 fprintf(stderr
, "Could not parse data\n");
198 fprintf(stderr
, "Returned %"PRIu8
", expected %"PRIu8
"\n",
211 struct lock3_parser_state
{
212 struct server_id self
;
213 enum g_lock_type lock_type
;
217 static void lock3_parser(struct server_id exclusive
,
219 const struct server_id
*shared
,
224 struct lock3_parser_state
*state
= private_data
;
225 size_t num_locks
= num_shared
+ ((exclusive
.pid
!= 0) ? 1 : 0);
226 const struct server_id
*pid
;
229 fprintf(stderr
, "datalen=%zu\n", datalen
);
232 if (num_locks
!= 1) {
233 fprintf(stderr
, "num_locks=%zu\n", num_locks
);
237 if (state
->lock_type
== G_LOCK_WRITE
) {
238 if (exclusive
.pid
== 0) {
239 fprintf(stderr
, "Found READ, expected WRITE\n");
243 if (exclusive
.pid
!= 0) {
244 fprintf(stderr
, "Found WRITE, expected READ\n");
249 pid
= (exclusive
.pid
!= 0) ? &exclusive
: &shared
[0];
251 if (!server_id_equal(pid
, &state
->self
)) {
252 struct server_id_buf tmp1
, tmp2
;
253 fprintf(stderr
, "found pid %s, expected %s\n",
254 server_id_str_buf(*pid
, &tmp1
),
255 server_id_str_buf(state
->self
, &tmp2
));
263 * Test lock upgrade/downgrade
266 bool run_g_lock3(int dummy
)
268 struct tevent_context
*ev
= NULL
;
269 struct messaging_context
*msg
= NULL
;
270 struct g_lock_ctx
*ctx
= NULL
;
271 const char *lockname
= "lock3";
272 struct lock3_parser_state state
;
277 ok
= get_g_lock_ctx(talloc_tos(), &ev
, &msg
, &ctx
);
282 state
.self
= messaging_server_id(msg
);
284 status
= g_lock_lock(ctx
, string_term_tdb_data(lockname
), G_LOCK_READ
,
285 (struct timeval
) { .tv_sec
= 1 });
286 if (!NT_STATUS_IS_OK(status
)) {
287 fprintf(stderr
, "g_lock_lock returned %s\n",
292 state
.lock_type
= G_LOCK_READ
;
295 status
= g_lock_dump(ctx
, string_term_tdb_data(lockname
),
296 lock3_parser
, &state
);
297 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
298 fprintf(stderr
, "g_lock_dump returned %s\n",
306 status
= g_lock_lock(ctx
, string_term_tdb_data(lockname
), G_LOCK_UPGRADE
,
307 (struct timeval
) { .tv_sec
= 1 });
308 if (!NT_STATUS_IS_OK(status
)) {
309 fprintf(stderr
, "g_lock_lock returned %s\n",
314 state
.lock_type
= G_LOCK_WRITE
;
317 status
= g_lock_dump(ctx
, string_term_tdb_data(lockname
),
318 lock3_parser
, &state
);
319 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
320 fprintf(stderr
, "g_lock_dump returned %s\n",
337 static bool lock4_child(const char *lockname
,
338 enum g_lock_type lock_type
,
342 struct tevent_context
*ev
= NULL
;
343 struct messaging_context
*msg
= NULL
;
344 struct g_lock_ctx
*ctx
= NULL
;
349 ok
= get_g_lock_ctx(talloc_tos(), &ev
, &msg
, &ctx
);
354 status
= g_lock_lock(
356 string_term_tdb_data(lockname
),
358 (struct timeval
) { .tv_sec
= 1 });
359 if (!NT_STATUS_IS_OK(status
)) {
360 fprintf(stderr
, "child: g_lock_lock returned %s\n",
365 n
= sys_write(ready_pipe
, &ok
, sizeof(ok
));
366 if (n
!= sizeof(ok
)) {
367 fprintf(stderr
, "child: write failed\n");
372 n
= sys_read(exit_pipe
, &ok
, sizeof(ok
));
374 fprintf(stderr
, "child: read failed\n");
382 static void lock4_done(struct tevent_req
*subreq
)
384 int *done
= tevent_req_callback_data_void(subreq
);
387 status
= g_lock_lock_recv(subreq
);
389 if (!NT_STATUS_IS_OK(status
)) {
390 fprintf(stderr
, "g_lock_lock_recv returned %s\n",
398 static void lock4_waited(struct tevent_req
*subreq
)
400 int *exit_pipe
= tevent_req_callback_data_void(subreq
);
407 ok
= tevent_wakeup_recv(subreq
);
410 fprintf(stderr
, "tevent_wakeup_recv failed\n");
414 child
= wait(&status
);
416 printf("child %d exited with %d\n", (int)child
, status
);
419 struct lock4_check_state
{
424 static void lock4_check(struct server_id exclusive
,
426 const struct server_id
*shared
,
431 struct lock4_check_state
*state
= private_data
;
432 size_t num_locks
= num_shared
+ ((exclusive
.pid
!= 0) ? 1 : 0);
434 if (num_locks
!= 1) {
435 fprintf(stderr
, "num_locks=%zu\n", num_locks
);
439 if (exclusive
.pid
== 0) {
440 fprintf(stderr
, "Wrong lock type, not WRITE\n");
444 if (!server_id_equal(&state
->me
, &exclusive
)) {
445 struct server_id_buf buf1
, buf2
;
446 fprintf(stderr
, "me=%s, locker=%s\n",
447 server_id_str_buf(state
->me
, &buf1
),
448 server_id_str_buf(exclusive
, &buf2
));
456 * Test a lock conflict: Contend with a WRITE lock
459 bool run_g_lock4(int dummy
)
461 struct tevent_context
*ev
= NULL
;
462 struct messaging_context
*msg
= NULL
;
463 struct g_lock_ctx
*ctx
= NULL
;
464 const char *lockname
= "lock4";
465 TDB_DATA key
= string_term_tdb_data(lockname
);
471 struct tevent_req
*req
;
475 if ((pipe(ready_pipe
) != 0) || (pipe(exit_pipe
) != 0)) {
476 perror("pipe failed");
482 ok
= get_g_lock_ctx(talloc_tos(), &ev
, &msg
, &ctx
);
488 perror("fork failed");
493 close(ready_pipe
[0]);
496 lockname
, G_LOCK_WRITE
, ready_pipe
[1], exit_pipe
[0]);
500 close(ready_pipe
[1]);
503 if (sys_read(ready_pipe
[0], &ok
, sizeof(ok
)) != sizeof(ok
)) {
504 perror("read failed");
509 fprintf(stderr
, "child returned error\n");
513 status
= g_lock_lock(
514 ctx
, key
, G_LOCK_WRITE
, (struct timeval
) { .tv_usec
= 1 });
515 if (!NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
)) {
516 fprintf(stderr
, "g_lock_lock returned %s\n",
521 status
= g_lock_lock(
522 ctx
, key
, G_LOCK_READ
, (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 req
= g_lock_lock_send(ev
, ev
, ctx
, key
, G_LOCK_WRITE
);
531 fprintf(stderr
, "g_lock_lock send failed\n");
534 tevent_req_set_callback(req
, lock4_done
, &done
);
536 req
= tevent_wakeup_send(ev
, ev
, timeval_current_ofs(1, 0));
538 fprintf(stderr
, "tevent_wakeup_send failed\n");
541 tevent_req_set_callback(req
, lock4_waited
, &exit_pipe
[1]);
546 int tevent_ret
= tevent_loop_once(ev
);
547 if (tevent_ret
!= 0) {
548 perror("tevent_loop_once failed");
554 struct lock4_check_state state
= {
555 .me
= messaging_server_id(msg
)
558 status
= g_lock_dump(ctx
, key
, lock4_check
, &state
);
559 if (!NT_STATUS_IS_OK(status
)) {
560 fprintf(stderr
, "g_lock_dump failed: %s\n",
565 fprintf(stderr
, "lock4_check failed\n");
579 * Test a lock conflict: Contend with a READ lock
582 bool run_g_lock4a(int dummy
)
584 struct tevent_context
*ev
= NULL
;
585 struct messaging_context
*msg
= NULL
;
586 struct g_lock_ctx
*ctx
= NULL
;
587 const char *lockname
= "lock4a";
588 TDB_DATA key
= string_term_tdb_data(lockname
);
594 struct tevent_req
*req
;
598 if ((pipe(ready_pipe
) != 0) || (pipe(exit_pipe
) != 0)) {
599 perror("pipe failed");
605 ok
= get_g_lock_ctx(talloc_tos(), &ev
, &msg
, &ctx
);
611 perror("fork failed");
616 close(ready_pipe
[0]);
619 lockname
, G_LOCK_READ
, ready_pipe
[1], exit_pipe
[0]);
623 close(ready_pipe
[1]);
626 if (sys_read(ready_pipe
[0], &ok
, sizeof(ok
)) != sizeof(ok
)) {
627 perror("read failed");
632 fprintf(stderr
, "child returned error\n");
636 status
= g_lock_lock(
637 ctx
, key
, G_LOCK_WRITE
, (struct timeval
) { .tv_usec
= 1 });
638 if (!NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
)) {
639 fprintf(stderr
, "g_lock_lock returned %s\n",
644 status
= g_lock_lock(
645 ctx
, key
, G_LOCK_READ
, (struct timeval
) { .tv_usec
= 1 });
646 if (!NT_STATUS_IS_OK(status
)) {
647 fprintf(stderr
, "g_lock_lock returned %s\n",
652 status
= g_lock_unlock(ctx
, key
);
653 if (!NT_STATUS_IS_OK(status
)) {
655 "g_lock_unlock returned %s\n",
660 req
= g_lock_lock_send(ev
, ev
, ctx
, key
, G_LOCK_WRITE
);
662 fprintf(stderr
, "g_lock_lock send failed\n");
665 tevent_req_set_callback(req
, lock4_done
, &done
);
667 req
= tevent_wakeup_send(ev
, ev
, timeval_current_ofs(1, 0));
669 fprintf(stderr
, "tevent_wakeup_send failed\n");
672 tevent_req_set_callback(req
, lock4_waited
, &exit_pipe
[1]);
677 int tevent_ret
= tevent_loop_once(ev
);
678 if (tevent_ret
!= 0) {
679 perror("tevent_loop_once failed");
685 struct lock4_check_state state
= {
686 .me
= messaging_server_id(msg
)
689 status
= g_lock_dump(ctx
, key
, lock4_check
, &state
);
690 if (!NT_STATUS_IS_OK(status
)) {
691 fprintf(stderr
, "g_lock_dump failed: %s\n",
696 fprintf(stderr
, "lock4_check failed\n");
709 struct lock5_parser_state
{
713 static void lock5_parser(struct server_id exclusive
,
715 const struct server_id
*shared
,
720 struct lock5_parser_state
*state
= private_data
;
721 state
->num_locks
= num_shared
+ ((exclusive
.pid
!= 0) ? 1 : 0);
725 * Test heuristic cleanup
728 bool run_g_lock5(int dummy
)
730 struct tevent_context
*ev
= NULL
;
731 struct messaging_context
*msg
= NULL
;
732 struct g_lock_ctx
*ctx
= NULL
;
733 const char *lockname
= "lock5";
735 int exit_pipe
[2], ready_pipe
[2];
745 if ((pipe(exit_pipe
) != 0) || (pipe(ready_pipe
) != 0)) {
746 perror("pipe failed");
750 ok
= get_g_lock_ctx(talloc_tos(), &ev
, &msg
, &ctx
);
752 fprintf(stderr
, "get_g_lock_ctx failed");
756 for (i
=0; i
<nprocs
; i
++) {
761 perror("fork failed");
768 status
= reinit_after_fork(msg
, ev
, false, "");
770 close(ready_pipe
[0]);
773 ok
= get_g_lock_ctx(talloc_tos(), &ev
, &msg
, &ctx
);
775 fprintf(stderr
, "get_g_lock_ctx failed");
778 status
= g_lock_lock(ctx
,
779 string_term_tdb_data(lockname
),
781 (struct timeval
) { .tv_sec
= 1 });
782 if (!NT_STATUS_IS_OK(status
)) {
784 "child g_lock_lock failed %s\n",
788 close(ready_pipe
[1]);
789 nread
= sys_read(exit_pipe
[0], &c
, sizeof(c
));
791 fprintf(stderr
, "sys_read returned %zu (%s)\n",
792 nread
, strerror(errno
));
799 close(ready_pipe
[1]);
801 nread
= sys_read(ready_pipe
[0], &c
, sizeof(c
));
803 fprintf(stderr
, "sys_read returned %zu (%s)\n",
804 nread
, strerror(errno
));
810 for (i
=0; i
<nprocs
; i
++) {
812 ret
= waitpid(-1, &child_status
, 0);
814 perror("waitpid failed");
819 for (i
=0; i
<nprocs
; i
++) {
820 struct lock5_parser_state state
;
822 status
= g_lock_dump(ctx
, string_term_tdb_data(lockname
),
823 lock5_parser
, &state
);
824 if (!NT_STATUS_IS_OK(status
)) {
825 fprintf(stderr
, "g_lock_dump returned %s\n",
830 if (state
.num_locks
!= (nprocs
- i
)) {
831 fprintf(stderr
, "nlocks=%zu, expected %zu\n",
832 state
.num_locks
, (nprocs
-i
));
836 status
= g_lock_lock(ctx
, string_term_tdb_data(lockname
),
838 (struct timeval
) { .tv_sec
= 1 });
839 if (!NT_STATUS_IS_OK(status
)) {
840 fprintf(stderr
, "g_lock_lock failed %s\n",
844 status
= g_lock_unlock(ctx
, string_term_tdb_data(lockname
));
845 if (!NT_STATUS_IS_OK(status
)) {
846 fprintf(stderr
, "g_lock_unlock failed %s\n",
856 struct lock6_parser_state
{
860 static void lock6_parser(struct server_id exclusive
,
862 const struct server_id
*shared
,
867 struct lock6_parser_state
*state
= private_data
;
868 state
->num_locks
= num_shared
+ ((exclusive
.pid
!= 0) ? 1 : 0);
872 * Test cleanup with contention and stale locks
875 bool run_g_lock6(int dummy
)
877 struct tevent_context
*ev
= NULL
;
878 struct messaging_context
*msg
= NULL
;
879 struct g_lock_ctx
*ctx
= NULL
;
880 TDB_DATA lockname
= string_term_tdb_data("lock6");
882 int exit_pipe
[2], ready_pipe
[2];
890 if ((pipe(exit_pipe
) != 0) || (pipe(ready_pipe
) != 0)) {
891 perror("pipe failed");
895 ok
= get_g_lock_ctx(talloc_tos(), &ev
, &msg
, &ctx
);
897 fprintf(stderr
, "get_g_lock_ctx failed");
902 * Wipe all stale locks -- in clustered mode there's no
905 status
= g_lock_lock(ctx
, lockname
, G_LOCK_WRITE
,
906 (struct timeval
) { .tv_sec
= 1 });
907 if (!NT_STATUS_IS_OK(status
)) {
908 fprintf(stderr
, "g_lock_lock failed: %s\n",
912 status
= g_lock_unlock(ctx
, lockname
);
913 if (!NT_STATUS_IS_OK(status
)) {
914 fprintf(stderr
, "g_lock_unlock failed: %s\n",
920 for (i
=0; i
<nprocs
; i
++) {
925 perror("fork failed");
932 status
= reinit_after_fork(msg
, ev
, false, "");
933 if (!NT_STATUS_IS_OK(status
)) {
934 fprintf(stderr
, "reinit_after_fork failed: %s\n",
939 close(ready_pipe
[0]);
942 ok
= get_g_lock_ctx(talloc_tos(), &ev
, &msg
, &ctx
);
944 fprintf(stderr
, "get_g_lock_ctx failed");
947 status
= g_lock_lock(ctx
,
950 (struct timeval
) { .tv_sec
= 1 });
951 if (!NT_STATUS_IS_OK(status
)) {
953 "child g_lock_lock failed %s\n",
960 close(ready_pipe
[1]);
961 nread
= sys_read(exit_pipe
[0], &c
, sizeof(c
));
963 fprintf(stderr
, "sys_read returned %zu (%s)\n",
964 nread
, strerror(errno
));
971 close(ready_pipe
[1]);
973 nread
= sys_read(ready_pipe
[0], &c
, sizeof(c
));
975 fprintf(stderr
, "sys_read returned %zd (%s)\n",
976 nread
, strerror(errno
));
982 ret
= waitpid(-1, &child_status
, 0);
984 perror("waitpid failed");
990 struct lock6_parser_state state
;
992 status
= g_lock_dump(ctx
, lockname
, lock6_parser
, &state
);
993 if (!NT_STATUS_IS_OK(status
)) {
994 fprintf(stderr
, "g_lock_dump returned %s\n",
999 if (state
.num_locks
!= nprocs
) {
1000 fprintf(stderr
, "nlocks=%zu, expected %zu\n",
1001 state
.num_locks
, nprocs
);
1005 status
= g_lock_lock(ctx
,
1008 (struct timeval
) { .tv_sec
= 1 });
1009 if (!NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
)) {
1010 fprintf(stderr
, "g_lock_lock should have failed with %s - %s\n",
1011 nt_errstr(NT_STATUS_IO_TIMEOUT
),
1016 status
= g_lock_lock(ctx
, lockname
, G_LOCK_READ
,
1017 (struct timeval
) { .tv_sec
= 1 });
1018 if (!NT_STATUS_IS_OK(status
)) {
1019 fprintf(stderr
, "g_lock_lock failed: %s\n",
1025 close(exit_pipe
[1]);
1029 ret
= waitpid(-1, &child_status
, 0);
1031 perror("waitpid failed");
1036 status
= g_lock_lock(ctx
, lockname
, G_LOCK_UPGRADE
,
1037 (struct timeval
) { .tv_sec
= 1 });
1038 if (!NT_STATUS_IS_OK(status
)) {
1039 fprintf(stderr
, "g_lock_lock failed: %s\n",
1048 * Test upgrade deadlock
1051 bool run_g_lock7(int dummy
)
1053 struct tevent_context
*ev
= NULL
;
1054 struct messaging_context
*msg
= NULL
;
1055 struct g_lock_ctx
*ctx
= NULL
;
1056 const char *lockname
= "lock7";
1057 TDB_DATA key
= string_term_tdb_data(lockname
);
1066 if ((pipe(ready_pipe
) != 0) || (pipe(down_pipe
) != 0)) {
1067 perror("pipe failed");
1073 ok
= get_g_lock_ctx(talloc_tos(), &ev
, &msg
, &ctx
);
1079 perror("fork failed");
1084 struct tevent_req
*req
= NULL
;
1086 close(ready_pipe
[0]);
1088 close(down_pipe
[1]);
1091 status
= reinit_after_fork(msg
, ev
, false, "");
1092 if (!NT_STATUS_IS_OK(status
)) {
1094 "reinit_after_fork failed: %s\n",
1099 printf("%d: locking READ\n", (int)getpid());
1101 status
= g_lock_lock(
1105 (struct timeval
) { .tv_usec
= 1 });
1106 if (!NT_STATUS_IS_OK(status
)) {
1108 "g_lock_lock(READ) failed: %s\n",
1115 n
= sys_write(ready_pipe
[1], &ok
, sizeof(ok
));
1116 if (n
!= sizeof(ok
)) {
1118 "sys_write failed: %s\n",
1123 n
= sys_read(down_pipe
[0], &ok
, sizeof(ok
));
1124 if (n
!= sizeof(ok
)) {
1126 "sys_read failed: %s\n",
1131 printf("%d: starting UPGRADE\n", (int)getpid());
1133 req
= g_lock_lock_send(
1140 fprintf(stderr
, "g_lock_lock_send(UPGRADE) failed\n");
1144 n
= sys_write(ready_pipe
[1], &ok
, sizeof(ok
));
1145 if (n
!= sizeof(ok
)) {
1147 "sys_write failed: %s\n",
1155 close(ready_pipe
[1]);
1156 close(down_pipe
[0]);
1158 if (sys_read(ready_pipe
[0], &ok
, sizeof(ok
)) != sizeof(ok
)) {
1159 perror("read failed");
1163 fprintf(stderr
, "child returned error\n");
1167 status
= g_lock_lock(
1171 (struct timeval
) { .tv_usec
= 1 });
1172 if (!NT_STATUS_IS_OK(status
)) {
1174 "g_lock_lock(READ) failed: %s\n",
1179 n
= sys_write(down_pipe
[1], &ok
, sizeof(ok
));
1180 if (n
!= sizeof(ok
)) {
1182 "sys_write failed: %s\n",
1187 if (sys_read(ready_pipe
[0], &ok
, sizeof(ok
)) != sizeof(ok
)) {
1188 perror("read failed");
1192 status
= g_lock_lock(
1196 (struct timeval
) { .tv_sec
= 10 });
1197 if (!NT_STATUS_EQUAL(status
, NT_STATUS_POSSIBLE_DEADLOCK
)) {
1199 "g_lock_lock returned %s\n",
1212 bool run_g_lock8(int dummy
)
1214 struct tevent_context
*ev
= NULL
;
1215 struct messaging_context
*msg
= NULL
;
1216 struct g_lock_ctx
*ctx
= NULL
;
1217 struct tevent_req
*req
= NULL
;
1218 TDB_DATA lockname
= string_term_tdb_data("lock8");
1222 ok
= get_g_lock_ctx(talloc_tos(), &ev
, &msg
, &ctx
);
1224 fprintf(stderr
, "get_g_lock_ctx failed");
1228 req
= g_lock_watch_data_send(
1229 ev
, ev
, ctx
, lockname
, (struct server_id
) { .pid
= 0 });
1231 fprintf(stderr
, "get_g_lock_ctx failed");
1235 status
= g_lock_lock(
1239 (struct timeval
) { .tv_sec
= 999 });
1240 if (!NT_STATUS_IS_OK(status
)) {
1242 "g_lock_lock failed: %s\n",
1247 status
= g_lock_write_data(
1248 ctx
, lockname
, lockname
.dptr
, lockname
.dsize
);
1249 if (!NT_STATUS_IS_OK(status
)) {
1251 "g_lock_write_data failed: %s\n",
1256 status
= g_lock_write_data(ctx
, lockname
, NULL
, 0);
1257 if (!NT_STATUS_IS_OK(status
)) {
1259 "g_lock_write_data failed: %s\n",
1264 status
= g_lock_unlock(ctx
, lockname
);
1265 if (!NT_STATUS_IS_OK(status
)) {
1267 "g_lock_unlock failed: %s\n",
1272 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
1274 fprintf(stderr
, "tevent_req_poll_ntstatus failed\n");
1277 if (!NT_STATUS_IS_OK(status
)) {
1279 "tevent_req_poll_ntstatus failed: %s\n",
1287 extern int torture_numops
;
1288 extern int torture_nprocs
;
1290 static struct timeval tp1
, tp2
;
1292 static void start_timer(void)
1294 gettimeofday(&tp1
,NULL
);
1297 static double end_timer(void)
1299 gettimeofday(&tp2
,NULL
);
1300 return (tp2
.tv_sec
+ (tp2
.tv_usec
*1.0e-6)) -
1301 (tp1
.tv_sec
+ (tp1
.tv_usec
*1.0e-6));
1308 bool run_g_lock_ping_pong(int dummy
)
1310 struct tevent_context
*ev
= NULL
;
1311 struct messaging_context
*msg
= NULL
;
1312 struct g_lock_ctx
*ctx
= NULL
;
1320 torture_nprocs
= MAX(2, torture_nprocs
);
1322 ok
= get_g_lock_ctx(talloc_tos(), &ev
, &msg
, &ctx
);
1329 snprintf(name
, sizeof(name
), "ping_pong_%d", i
);
1331 status
= g_lock_lock(ctx
, string_term_tdb_data(name
), G_LOCK_WRITE
,
1332 (struct timeval
) { .tv_sec
= 60 });
1333 if (!NT_STATUS_IS_OK(status
)) {
1334 fprintf(stderr
, "g_lock_lock failed: %s\n",
1339 for (i
=0; i
<torture_numops
; i
++) {
1341 name
[10] = '0' + ((i
+1) % torture_nprocs
);
1343 status
= g_lock_lock(ctx
, string_term_tdb_data(name
),
1345 (struct timeval
) { .tv_sec
= 60 });
1346 if (!NT_STATUS_IS_OK(status
)) {
1347 fprintf(stderr
, "g_lock_lock failed: %s\n",
1352 name
[10] = '0' + ((i
) % torture_nprocs
);
1354 status
= g_lock_unlock(ctx
, string_term_tdb_data(name
));
1355 if (!NT_STATUS_IS_OK(status
)) {
1356 fprintf(stderr
, "g_lock_unlock failed: %s\n",
1363 if (end_timer() > 1.0) {
1364 printf("%8u locks/sec\r",
1365 (unsigned)(2*count
/end_timer()));