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"
29 static bool get_g_lock_ctx(TALLOC_CTX *mem_ctx,
30 struct tevent_context **ev,
31 struct messaging_context **msg,
32 struct g_lock_ctx **ctx)
34 *ev = server_event_context();
36 fprintf(stderr, "tevent_context_init failed\n");
39 *msg = server_messaging_context();
41 fprintf(stderr, "messaging_init failed\n");
45 *ctx = g_lock_ctx_init(*ev, *msg);
47 fprintf(stderr, "g_lock_ctx_init failed\n");
56 bool run_g_lock1(int dummy)
58 struct tevent_context *ev = NULL;
59 struct messaging_context *msg = NULL;
60 struct g_lock_ctx *ctx = NULL;
61 const char *lockname = "lock1";
66 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
71 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_READ,
72 (struct timeval) { .tv_sec = 1 });
73 if (!NT_STATUS_IS_OK(status)) {
74 fprintf(stderr, "g_lock_lock failed: %s\n",
79 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_READ,
80 (struct timeval) { .tv_sec = 1 });
81 if (!NT_STATUS_EQUAL(status, NT_STATUS_WAS_LOCKED)) {
82 fprintf(stderr, "Double lock got %s\n",
87 status = g_lock_unlock(ctx, string_term_tdb_data(lockname));
88 if (!NT_STATUS_IS_OK(status)) {
89 fprintf(stderr, "g_lock_unlock failed: %s\n",
94 status = g_lock_unlock(ctx, string_term_tdb_data(lockname));
95 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
96 fprintf(stderr, "g_lock_unlock returned: %s\n",
109 struct lock2_parser_state {
114 static void lock2_parser(const struct g_lock_rec *locks,
120 struct lock2_parser_state *state = private_data;
122 if (datalen != sizeof(uint8_t)) {
125 *state->rdata = *data;
130 * Test g_lock_write_data
133 bool run_g_lock2(int dummy)
135 struct tevent_context *ev = NULL;
136 struct messaging_context *msg = NULL;
137 struct g_lock_ctx *ctx = NULL;
138 const char *lockname = "lock2";
141 struct lock2_parser_state state = { .rdata = &rdata };
146 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
151 status = g_lock_write_data(ctx, string_term_tdb_data(lockname),
152 &data, sizeof(data));
153 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_LOCKED)) {
154 fprintf(stderr, "unlocked g_lock_write_data returned %s\n",
159 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_WRITE,
160 (struct timeval) { .tv_sec = 1 });
161 if (!NT_STATUS_IS_OK(status)) {
162 fprintf(stderr, "g_lock_lock returned %s\n",
167 status = g_lock_write_data(ctx, string_term_tdb_data(lockname),
168 &data, sizeof(data));
169 if (!NT_STATUS_IS_OK(status)) {
170 fprintf(stderr, "g_lock_write_data failed: %s\n",
175 status = g_lock_unlock(ctx, string_term_tdb_data(lockname));
176 if (!NT_STATUS_IS_OK(status)) {
177 fprintf(stderr, "g_lock_unlock failed: %s\n",
182 status = g_lock_dump(ctx, string_term_tdb_data(lockname),
183 lock2_parser, &state);
184 if (!NT_STATUS_IS_OK(status)) {
185 fprintf(stderr, "g_lock_dump failed: %s\n",
191 fprintf(stderr, "Could not parse data\n");
195 fprintf(stderr, "Returned %"PRIu8", expected %"PRIu8"\n",
208 struct lock3_parser_state {
209 struct server_id self;
210 enum g_lock_type lock_type;
214 static void lock3_parser(const struct g_lock_rec *locks,
220 struct lock3_parser_state *state = private_data;
223 fprintf(stderr, "datalen=%zu\n", datalen);
226 if (num_locks != 1) {
227 fprintf(stderr, "num_locks=%zu\n", num_locks);
230 if (locks[0].lock_type != state->lock_type) {
231 fprintf(stderr, "found type %d, expected %d\n",
232 (int)locks[0].lock_type, (int)state->lock_type);
235 if (!server_id_equal(&locks[0].pid, &state->self)) {
236 struct server_id_buf tmp1, tmp2;
237 fprintf(stderr, "found pid %s, expected %s\n",
238 server_id_str_buf(locks[0].pid, &tmp1),
239 server_id_str_buf(state->self, &tmp2));
247 * Test lock upgrade/downgrade
250 bool run_g_lock3(int dummy)
252 struct tevent_context *ev = NULL;
253 struct messaging_context *msg = NULL;
254 struct g_lock_ctx *ctx = NULL;
255 const char *lockname = "lock3";
256 struct lock3_parser_state state;
261 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
266 state.self = messaging_server_id(msg);
268 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_READ,
269 (struct timeval) { .tv_sec = 1 });
270 if (!NT_STATUS_IS_OK(status)) {
271 fprintf(stderr, "g_lock_lock returned %s\n",
276 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_READ,
277 (struct timeval) { .tv_sec = 1 });
278 if (!NT_STATUS_EQUAL(status, NT_STATUS_WAS_LOCKED)) {
279 fprintf(stderr, "g_lock_lock returned %s, expected %s\n",
280 nt_errstr(status), nt_errstr(NT_STATUS_WAS_LOCKED));
284 state.lock_type = G_LOCK_READ;
287 status = g_lock_dump(ctx, string_term_tdb_data(lockname),
288 lock3_parser, &state);
289 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
290 fprintf(stderr, "g_lock_dump returned %s\n",
298 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_WRITE,
299 (struct timeval) { .tv_sec = 1 });
300 if (!NT_STATUS_IS_OK(status)) {
301 fprintf(stderr, "g_lock_lock returned %s\n",
306 state.lock_type = G_LOCK_WRITE;
309 status = g_lock_dump(ctx, string_term_tdb_data(lockname),
310 lock3_parser, &state);
311 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
312 fprintf(stderr, "g_lock_dump returned %s\n",
329 static bool lock4_child(const char *lockname,
330 int ready_pipe, int exit_pipe)
332 struct tevent_context *ev = NULL;
333 struct messaging_context *msg = NULL;
334 struct g_lock_ctx *ctx = NULL;
339 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
344 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_WRITE,
345 (struct timeval) { .tv_sec = 1 });
346 if (!NT_STATUS_IS_OK(status)) {
347 fprintf(stderr, "child: g_lock_lock returned %s\n",
352 n = sys_write(ready_pipe, &ok, sizeof(ok));
353 if (n != sizeof(ok)) {
354 fprintf(stderr, "child: write failed\n");
359 n = sys_read(exit_pipe, &ok, sizeof(ok));
361 fprintf(stderr, "child: read failed\n");
369 static void lock4_done(struct tevent_req *subreq)
371 int *done = tevent_req_callback_data_void(subreq);
374 status = g_lock_lock_recv(subreq);
376 if (!NT_STATUS_IS_OK(status)) {
377 fprintf(stderr, "g_lock_lock_recv returned %s\n",
385 static void lock4_waited(struct tevent_req *subreq)
387 int *exit_pipe = tevent_req_callback_data_void(subreq);
394 ok = tevent_wakeup_recv(subreq);
397 fprintf(stderr, "tevent_wakeup_recv failed\n");
401 child = wait(&status);
403 printf("child %d exited with %d\n", (int)child, status);
406 struct lock4_check_state {
411 static void lock4_check(const struct g_lock_rec *locks,
417 struct lock4_check_state *state = private_data;
419 if (num_locks != 1) {
420 fprintf(stderr, "num_locks=%zu\n", num_locks);
424 if (!serverid_equal(&state->me, &locks[0].pid)) {
425 struct server_id_buf buf1, buf2;
426 fprintf(stderr, "me=%s, locker=%s\n",
427 server_id_str_buf(state->me, &buf1),
428 server_id_str_buf(locks[0].pid, &buf2));
432 if (locks[0].lock_type != G_LOCK_WRITE) {
433 fprintf(stderr, "wrong lock type: %d\n",
434 (int)locks[0].lock_type);
442 * Test a lock conflict
445 bool run_g_lock4(int dummy)
447 struct tevent_context *ev = NULL;
448 struct messaging_context *msg = NULL;
449 struct g_lock_ctx *ctx = NULL;
450 const char *lockname = "lock4";
456 struct tevent_req *req;
460 if ((pipe(ready_pipe) != 0) || (pipe(exit_pipe) != 0)) {
461 perror("pipe failed");
467 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
473 perror("fork failed");
478 close(ready_pipe[0]);
480 ok = lock4_child(lockname, ready_pipe[1], exit_pipe[0]);
484 close(ready_pipe[1]);
487 if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
488 perror("read failed");
493 fprintf(stderr, "child returned error\n");
497 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_WRITE,
498 (struct timeval) { .tv_usec = 1 });
499 if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
500 fprintf(stderr, "g_lock_lock returned %s\n",
505 status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_READ,
506 (struct timeval) { .tv_usec = 1 });
507 if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
508 fprintf(stderr, "g_lock_lock returned %s\n",
513 req = g_lock_lock_send(ev, ev, ctx, string_term_tdb_data(lockname),
516 fprintf(stderr, "g_lock_lock send failed\n");
519 tevent_req_set_callback(req, lock4_done, &done);
521 req = tevent_wakeup_send(ev, ev, timeval_current_ofs(1, 0));
523 fprintf(stderr, "tevent_wakeup_send failed\n");
526 tevent_req_set_callback(req, lock4_waited, &exit_pipe[1]);
531 int tevent_ret = tevent_loop_once(ev);
532 if (tevent_ret != 0) {
533 perror("tevent_loop_once failed");
539 struct lock4_check_state state = {
540 .me = messaging_server_id(msg)
543 status = g_lock_dump(ctx, string_term_tdb_data(lockname),
544 lock4_check, &state);
545 if (!NT_STATUS_IS_OK(status)) {
546 fprintf(stderr, "g_lock_dump failed: %s\n",
551 fprintf(stderr, "lock4_check failed\n");
564 struct lock5_parser_state {
568 static void lock5_parser(const struct g_lock_rec *locks,
574 struct lock5_parser_state *state = private_data;
575 state->num_locks = num_locks;
579 * Test heuristic cleanup
582 bool run_g_lock5(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 = "lock5";
589 int exit_pipe[2], ready_pipe[2];
599 if ((pipe(exit_pipe) != 0) || (pipe(ready_pipe) != 0)) {
600 perror("pipe failed");
604 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
606 fprintf(stderr, "get_g_lock_ctx failed");
610 for (i=0; i<nprocs; i++) {
615 perror("fork failed");
622 status = reinit_after_fork(msg, ev, false, "");
624 close(ready_pipe[0]);
627 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
629 fprintf(stderr, "get_g_lock_ctx failed");
632 status = g_lock_lock(ctx,
633 string_term_tdb_data(lockname),
635 (struct timeval) { .tv_sec = 1 });
636 if (!NT_STATUS_IS_OK(status)) {
638 "child g_lock_lock failed %s\n",
642 close(ready_pipe[1]);
643 nread = sys_read(exit_pipe[0], &c, sizeof(c));
645 fprintf(stderr, "sys_read returned %zu (%s)\n",
646 nread, strerror(errno));
653 close(ready_pipe[1]);
655 nread = sys_read(ready_pipe[0], &c, sizeof(c));
657 fprintf(stderr, "sys_read returned %zu (%s)\n",
658 nread, strerror(errno));
664 for (i=0; i<nprocs; i++) {
666 ret = waitpid(-1, &child_status, 0);
668 perror("waitpid failed");
673 for (i=0; i<nprocs; i++) {
674 struct lock5_parser_state state;
676 status = g_lock_dump(ctx, string_term_tdb_data(lockname),
677 lock5_parser, &state);
678 if (!NT_STATUS_IS_OK(status)) {
679 fprintf(stderr, "g_lock_dump returned %s\n",
684 if (state.num_locks != (nprocs - i)) {
685 fprintf(stderr, "nlocks=%zu, expected %zu\n",
686 state.num_locks, (nprocs-i));
690 status = g_lock_lock(ctx, string_term_tdb_data(lockname),
692 (struct timeval) { .tv_sec = 1 });
693 if (!NT_STATUS_IS_OK(status)) {
694 fprintf(stderr, "g_lock_lock failed %s\n",
698 status = g_lock_unlock(ctx, string_term_tdb_data(lockname));
699 if (!NT_STATUS_IS_OK(status)) {
700 fprintf(stderr, "g_lock_unlock failed %s\n",
710 struct lock6_parser_state {
714 static void lock6_parser(const struct g_lock_rec *locks,
720 struct lock6_parser_state *state = private_data;
721 state->num_locks = num_locks;
725 * Test cleanup with contention and stale locks
728 bool run_g_lock6(int dummy)
730 struct tevent_context *ev = NULL;
731 struct messaging_context *msg = NULL;
732 struct g_lock_ctx *ctx = NULL;
733 TDB_DATA lockname = string_term_tdb_data("lock6");
735 int exit_pipe[2], ready_pipe[2];
743 if ((pipe(exit_pipe) != 0) || (pipe(ready_pipe) != 0)) {
744 perror("pipe failed");
748 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
750 fprintf(stderr, "get_g_lock_ctx failed");
755 * Wipe all stale locks -- in clustered mode there's no
758 status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
759 (struct timeval) { .tv_sec = 1 });
760 if (!NT_STATUS_IS_OK(status)) {
761 fprintf(stderr, "g_lock_lock failed: %s\n",
765 status = g_lock_unlock(ctx, lockname);
766 if (!NT_STATUS_IS_OK(status)) {
767 fprintf(stderr, "g_lock_unlock failed: %s\n",
773 for (i=0; i<nprocs; i++) {
778 perror("fork failed");
785 status = reinit_after_fork(msg, ev, false, "");
786 if (!NT_STATUS_IS_OK(status)) {
787 fprintf(stderr, "reinit_after_fork failed: %s\n",
792 close(ready_pipe[0]);
795 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
797 fprintf(stderr, "get_g_lock_ctx failed");
800 status = g_lock_lock(ctx,
803 (struct timeval) { .tv_sec = 1 });
804 if (!NT_STATUS_IS_OK(status)) {
806 "child g_lock_lock failed %s\n",
813 close(ready_pipe[1]);
814 nread = sys_read(exit_pipe[0], &c, sizeof(c));
816 fprintf(stderr, "sys_read returned %zu (%s)\n",
817 nread, strerror(errno));
824 close(ready_pipe[1]);
826 nread = sys_read(ready_pipe[0], &c, sizeof(c));
828 fprintf(stderr, "sys_read returned %zd (%s)\n",
829 nread, strerror(errno));
835 ret = waitpid(-1, &child_status, 0);
837 perror("waitpid failed");
843 struct lock6_parser_state state;
845 status = g_lock_dump(ctx, lockname, lock6_parser, &state);
846 if (!NT_STATUS_IS_OK(status)) {
847 fprintf(stderr, "g_lock_dump returned %s\n",
852 if (state.num_locks != nprocs) {
853 fprintf(stderr, "nlocks=%zu, expected %zu\n",
854 state.num_locks, nprocs);
858 status = g_lock_lock(ctx,
861 (struct timeval) { .tv_sec = 1 });
862 if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
863 fprintf(stderr, "g_lock_lock should have failed with %s - %s\n",
864 nt_errstr(NT_STATUS_IO_TIMEOUT),
869 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
870 (struct timeval) { .tv_sec = 1 });
871 if (!NT_STATUS_IS_OK(status)) {
872 fprintf(stderr, "g_lock_lock failed: %s\n",
882 ret = waitpid(-1, &child_status, 0);
884 perror("waitpid failed");
889 status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
890 (struct timeval) { .tv_sec = 1 });
891 if (!NT_STATUS_IS_OK(status)) {
892 fprintf(stderr, "g_lock_lock failed: %s\n",
900 extern int torture_numops;
901 extern int torture_nprocs;
903 static struct timeval tp1, tp2;
905 static void start_timer(void)
907 gettimeofday(&tp1,NULL);
910 static double end_timer(void)
912 gettimeofday(&tp2,NULL);
913 return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) -
914 (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
921 bool run_g_lock_ping_pong(int dummy)
923 struct tevent_context *ev = NULL;
924 struct messaging_context *msg = NULL;
925 struct g_lock_ctx *ctx = NULL;
933 torture_nprocs = MAX(2, torture_nprocs);
935 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
942 snprintf(name, sizeof(name), "ping_pong_%d", i);
944 status = g_lock_lock(ctx, string_term_tdb_data(name), G_LOCK_WRITE,
945 (struct timeval) { .tv_sec = 60 });
946 if (!NT_STATUS_IS_OK(status)) {
947 fprintf(stderr, "g_lock_lock failed: %s\n",
952 for (i=0; i<torture_numops; i++) {
954 name[10] = '0' + ((i+1) % torture_nprocs);
956 status = g_lock_lock(ctx, string_term_tdb_data(name),
958 (struct timeval) { .tv_sec = 60 });
959 if (!NT_STATUS_IS_OK(status)) {
960 fprintf(stderr, "g_lock_lock failed: %s\n",
965 name[10] = '0' + ((i) % torture_nprocs);
967 status = g_lock_unlock(ctx, string_term_tdb_data(name));
968 if (!NT_STATUS_IS_OK(status)) {
969 fprintf(stderr, "g_lock_unlock failed: %s\n",
976 if (end_timer() > 1.0) {
977 printf("%8u locks/sec\r",
978 (unsigned)(2*count/end_timer()));