libsmb: Return symlink error struct from smb2cli_create_recv()
[samba.git] / source3 / torture / test_g_lock.c
1 /*
2  * Unix SMB/CIFS implementation.
3  * Test g_lock API
4  * Copyright (C) Volker Lendecke 2017
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
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"
27 #include "lib/util/util_tdb.h"
28 #include "lib/util/tevent_ntstatus.h"
29 #include "lib/global_contexts.h"
30
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)
35 {
36         *ev = global_event_context();
37         if (*ev == NULL) {
38                 fprintf(stderr, "tevent_context_init failed\n");
39                 return false;
40         }
41         *msg = global_messaging_context();
42         if (*msg == NULL) {
43                 fprintf(stderr, "messaging_init failed\n");
44                 TALLOC_FREE(*ev);
45                 return false;
46         }
47         *ctx = g_lock_ctx_init(*ev, *msg);
48         if (*ctx == NULL) {
49                 fprintf(stderr, "g_lock_ctx_init failed\n");
50                 TALLOC_FREE(*msg);
51                 TALLOC_FREE(*ev);
52                 return false;
53         }
54
55         return true;
56 }
57
58 bool run_g_lock1(int dummy)
59 {
60         struct tevent_context *ev = NULL;
61         struct messaging_context *msg = NULL;
62         struct g_lock_ctx *ctx = NULL;
63         const char *lockname = "lock1";
64         NTSTATUS status;
65         bool ret = false;
66         bool ok;
67
68         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
69         if (!ok) {
70                 goto fail;
71         }
72
73         status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_WRITE,
74                              (struct timeval) { .tv_sec = 1 },
75                              NULL, NULL);
76         if (!NT_STATUS_IS_OK(status)) {
77                 fprintf(stderr, "g_lock_lock failed: %s\n",
78                         nt_errstr(status));
79                 goto fail;
80         }
81
82         status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_WRITE,
83                              (struct timeval) { .tv_sec = 1 },
84                              NULL, NULL);
85         if (!NT_STATUS_EQUAL(status, NT_STATUS_WAS_LOCKED)) {
86                 fprintf(stderr, "Double lock got %s\n",
87                         nt_errstr(status));
88                 goto fail;
89         }
90
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",
94                         nt_errstr(status));
95                 goto fail;
96         }
97
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",
101                         nt_errstr(status));
102                 goto fail;
103         }
104
105         ret = true;
106 fail:
107         TALLOC_FREE(ctx);
108         TALLOC_FREE(msg);
109         TALLOC_FREE(ev);
110         return ret;
111 }
112
113 struct lock2_parser_state {
114         uint8_t *rdata;
115         bool ok;
116 };
117
118 static void lock2_parser(struct server_id exclusive,
119                          size_t num_shared,
120                          const struct server_id *shared,
121                          const uint8_t *data,
122                          size_t datalen,
123                          void *private_data)
124 {
125         struct lock2_parser_state *state = private_data;
126
127         if (datalen != sizeof(uint8_t)) {
128                 return;
129         }
130         *state->rdata = *data;
131         state->ok = true;
132 }
133
134 /*
135  * Test g_lock_write_data
136  */
137
138 bool run_g_lock2(int dummy)
139 {
140         struct tevent_context *ev = NULL;
141         struct messaging_context *msg = NULL;
142         struct g_lock_ctx *ctx = NULL;
143         const char *lockname = "lock2";
144         uint8_t data = 42;
145         uint8_t rdata;
146         struct lock2_parser_state state = { .rdata = &rdata };
147         NTSTATUS status;
148         bool ret = false;
149         bool ok;
150
151         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
152         if (!ok) {
153                 goto fail;
154         }
155
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",
160                         nt_errstr(status));
161                 goto fail;
162         }
163
164         status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_WRITE,
165                              (struct timeval) { .tv_sec = 1 },
166                              NULL, NULL);
167         if (!NT_STATUS_IS_OK(status)) {
168                 fprintf(stderr, "g_lock_lock returned %s\n",
169                         nt_errstr(status));
170                 goto fail;
171         }
172
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",
177                         nt_errstr(status));
178                 goto fail;
179         }
180
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",
184                         nt_errstr(status));
185                 goto fail;
186         }
187
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",
192                         nt_errstr(status));
193                 goto fail;
194         }
195
196         if (!state.ok) {
197                 fprintf(stderr, "Could not parse data\n");
198                 goto fail;
199         }
200         if (rdata != data) {
201                 fprintf(stderr, "Returned %"PRIu8", expected %"PRIu8"\n",
202                         rdata, data);
203                 goto fail;
204         }
205
206         ret = true;
207 fail:
208         TALLOC_FREE(ctx);
209         TALLOC_FREE(msg);
210         TALLOC_FREE(ev);
211         return ret;
212 }
213
214 struct lock3_parser_state {
215         struct server_id self;
216         enum g_lock_type lock_type;
217         bool ok;
218 };
219
220 static void lock3_parser(struct server_id exclusive,
221                          size_t num_shared,
222                          const struct server_id *shared,
223                          const uint8_t *data,
224                          size_t datalen,
225                          void *private_data)
226 {
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;
230
231         if (datalen != 0) {
232                 fprintf(stderr, "datalen=%zu\n", datalen);
233                 return;
234         }
235         if (num_locks != 1) {
236                 fprintf(stderr, "num_locks=%zu\n", num_locks);
237                 return;
238         }
239
240         if (state->lock_type == G_LOCK_WRITE) {
241                 if (exclusive.pid == 0) {
242                         fprintf(stderr, "Found READ, expected WRITE\n");
243                         return;
244                 }
245         } else {
246                 if (exclusive.pid != 0) {
247                         fprintf(stderr, "Found WRITE, expected READ\n");
248                         return;
249                 }
250         }
251
252         pid = (exclusive.pid != 0) ? &exclusive : &shared[0];
253
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));
259                 return;
260         }
261
262         state->ok = true;
263 }
264
265 /*
266  * Test lock upgrade/downgrade
267  */
268
269 bool run_g_lock3(int dummy)
270 {
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;
276         NTSTATUS status;
277         bool ret = false;
278         bool ok;
279
280         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
281         if (!ok) {
282                 goto fail;
283         }
284
285         state.self = messaging_server_id(msg);
286
287         status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_READ,
288                              (struct timeval) { .tv_sec = 1 },
289                              NULL, NULL);
290         if (!NT_STATUS_IS_OK(status)) {
291                 fprintf(stderr, "g_lock_lock returned %s\n",
292                         nt_errstr(status));
293                 goto fail;
294         }
295
296         state.lock_type = G_LOCK_READ;
297         state.ok = false;
298
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",
303                         nt_errstr(status));
304                 goto fail;
305         }
306         if (!state.ok) {
307                 goto fail;
308         }
309
310         status = g_lock_lock(ctx, string_term_tdb_data(lockname), G_LOCK_UPGRADE,
311                              (struct timeval) { .tv_sec = 1 },
312                              NULL, NULL);
313         if (!NT_STATUS_IS_OK(status)) {
314                 fprintf(stderr, "g_lock_lock returned %s\n",
315                         nt_errstr(status));
316                 goto fail;
317         }
318
319         state.lock_type = G_LOCK_WRITE;
320         state.ok = false;
321
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",
326                         nt_errstr(status));
327                 goto fail;
328         }
329         if (!state.ok) {
330                 goto fail;
331         }
332
333
334         ret = true;
335 fail:
336         TALLOC_FREE(ctx);
337         TALLOC_FREE(msg);
338         TALLOC_FREE(ev);
339         return ret;
340 }
341
342 static bool lock4_child(const char *lockname,
343                         enum g_lock_type lock_type,
344                         int ready_pipe,
345                         int exit_pipe)
346 {
347         struct tevent_context *ev = NULL;
348         struct messaging_context *msg = NULL;
349         struct g_lock_ctx *ctx = NULL;
350         NTSTATUS status;
351         ssize_t n;
352         bool ok;
353
354         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
355         if (!ok) {
356                 return false;
357         }
358
359         status = g_lock_lock(
360                 ctx,
361                 string_term_tdb_data(lockname),
362                 lock_type,
363                 (struct timeval) { .tv_sec = 1 },
364                 NULL,
365                 NULL);
366         if (!NT_STATUS_IS_OK(status)) {
367                 fprintf(stderr, "child: g_lock_lock returned %s\n",
368                         nt_errstr(status));
369                 return false;
370         }
371
372         n = sys_write(ready_pipe, &ok, sizeof(ok));
373         if (n != sizeof(ok)) {
374                 fprintf(stderr, "child: write failed\n");
375                 return false;
376         }
377
378         if (ok) {
379                 n = sys_read(exit_pipe, &ok, sizeof(ok));
380                 if (n != 0) {
381                         fprintf(stderr, "child: read failed\n");
382                         return false;
383                 }
384         }
385
386         return true;
387 }
388
389 static void lock4_done(struct tevent_req *subreq)
390 {
391         int *done = tevent_req_callback_data_void(subreq);
392         NTSTATUS status;
393
394         status = g_lock_lock_recv(subreq);
395         TALLOC_FREE(subreq);
396         if (!NT_STATUS_IS_OK(status)) {
397                 fprintf(stderr, "g_lock_lock_recv returned %s\n",
398                         nt_errstr(status));
399                 *done = -1;
400                 return;
401         }
402         *done = 1;
403 }
404
405 static void lock4_waited(struct tevent_req *subreq)
406 {
407         int *exit_pipe = tevent_req_callback_data_void(subreq);
408         pid_t child;
409         int status;
410         bool ok;
411
412         printf("waited\n");
413
414         ok = tevent_wakeup_recv(subreq);
415         TALLOC_FREE(subreq);
416         if (!ok) {
417                 fprintf(stderr, "tevent_wakeup_recv failed\n");
418         }
419         close(*exit_pipe);
420
421         child = wait(&status);
422
423         printf("child %d exited with %d\n", (int)child, status);
424 }
425
426 struct lock4_check_state {
427         struct server_id me;
428         bool ok;
429 };
430
431 static void lock4_check(struct server_id exclusive,
432                         size_t num_shared,
433                         const struct server_id *shared,
434                         const uint8_t *data,
435                         size_t datalen,
436                         void *private_data)
437 {
438         struct lock4_check_state *state = private_data;
439         size_t num_locks = num_shared + ((exclusive.pid != 0) ? 1 : 0);
440
441         if (num_locks != 1) {
442                 fprintf(stderr, "num_locks=%zu\n", num_locks);
443                 return;
444         }
445
446         if (exclusive.pid == 0) {
447                 fprintf(stderr, "Wrong lock type, not WRITE\n");
448                 return;
449         }
450
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));
456                 return;
457         }
458
459         state->ok = true;
460 }
461
462 /*
463  * Test a lock conflict: Contend with a WRITE lock
464  */
465
466 bool run_g_lock4(int dummy)
467 {
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);
473         pid_t child;
474         int ready_pipe[2];
475         int exit_pipe[2];
476         NTSTATUS status;
477         bool ret = false;
478         struct tevent_req *req;
479         bool ok;
480         int done;
481
482         if ((pipe(ready_pipe) != 0) || (pipe(exit_pipe) != 0)) {
483                 perror("pipe failed");
484                 return false;
485         }
486
487         child = fork();
488
489         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
490         if (!ok) {
491                 goto fail;
492         }
493
494         if (child == -1) {
495                 perror("fork failed");
496                 return false;
497         }
498
499         if (child == 0) {
500                 close(ready_pipe[0]);
501                 close(exit_pipe[1]);
502                 ok = lock4_child(
503                         lockname, G_LOCK_WRITE, ready_pipe[1], exit_pipe[0]);
504                 exit(ok ? 0 : 1);
505         }
506
507         close(ready_pipe[1]);
508         close(exit_pipe[0]);
509
510         if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
511                 perror("read failed");
512                 return false;
513         }
514
515         if (!ok) {
516                 fprintf(stderr, "child returned error\n");
517                 return false;
518         }
519
520         status = g_lock_lock(ctx, key, G_LOCK_WRITE,
521                              (struct timeval) { .tv_usec = 1 },
522                               NULL, NULL);
523         if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
524                 fprintf(stderr, "g_lock_lock returned %s\n",
525                         nt_errstr(status));
526                 goto fail;
527         }
528
529         status = g_lock_lock(ctx, key, G_LOCK_READ,
530                              (struct timeval) { .tv_usec = 1 },
531                              NULL, NULL);
532         if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
533                 fprintf(stderr, "g_lock_lock returned %s\n",
534                         nt_errstr(status));
535                 goto fail;
536         }
537
538         req = g_lock_lock_send(ev, ev, ctx, key, G_LOCK_WRITE, NULL, NULL);
539         if (req == NULL) {
540                 fprintf(stderr, "g_lock_lock send failed\n");
541                 goto fail;
542         }
543         tevent_req_set_callback(req, lock4_done, &done);
544
545         req = tevent_wakeup_send(ev, ev, timeval_current_ofs(1, 0));
546         if (req == NULL) {
547                 fprintf(stderr, "tevent_wakeup_send failed\n");
548                 goto fail;
549         }
550         tevent_req_set_callback(req, lock4_waited, &exit_pipe[1]);
551
552         done = 0;
553
554         while (done == 0) {
555                 int tevent_ret = tevent_loop_once(ev);
556                 if (tevent_ret != 0) {
557                         perror("tevent_loop_once failed");
558                         goto fail;
559                 }
560         }
561
562         {
563                 struct lock4_check_state state = {
564                         .me = messaging_server_id(msg)
565                 };
566
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",
570                                 nt_errstr(status));
571                         goto fail;
572                 }
573                 if (!state.ok) {
574                         fprintf(stderr, "lock4_check failed\n");
575                         goto fail;
576                 }
577         }
578
579         ret = true;
580 fail:
581         TALLOC_FREE(ctx);
582         TALLOC_FREE(msg);
583         TALLOC_FREE(ev);
584         return ret;
585 }
586
587 /*
588  * Test a lock conflict: Contend with a READ lock
589  */
590
591 bool run_g_lock4a(int dummy)
592 {
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);
598         pid_t child;
599         int ready_pipe[2];
600         int exit_pipe[2];
601         NTSTATUS status;
602         bool ret = false;
603         struct tevent_req *req;
604         bool ok;
605         int done;
606
607         if ((pipe(ready_pipe) != 0) || (pipe(exit_pipe) != 0)) {
608                 perror("pipe failed");
609                 return false;
610         }
611
612         child = fork();
613
614         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
615         if (!ok) {
616                 goto fail;
617         }
618
619         if (child == -1) {
620                 perror("fork failed");
621                 return false;
622         }
623
624         if (child == 0) {
625                 close(ready_pipe[0]);
626                 close(exit_pipe[1]);
627                 ok = lock4_child(
628                         lockname, G_LOCK_READ, ready_pipe[1], exit_pipe[0]);
629                 exit(ok ? 0 : 1);
630         }
631
632         close(ready_pipe[1]);
633         close(exit_pipe[0]);
634
635         if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
636                 perror("read failed");
637                 return false;
638         }
639
640         if (!ok) {
641                 fprintf(stderr, "child returned error\n");
642                 return false;
643         }
644
645         status = g_lock_lock(ctx, key, G_LOCK_WRITE,
646                              (struct timeval) { .tv_usec = 1 },
647                              NULL, NULL);
648         if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
649                 fprintf(stderr, "g_lock_lock returned %s\n",
650                         nt_errstr(status));
651                 goto fail;
652         }
653
654         status = g_lock_lock(ctx, key, G_LOCK_READ,
655                              (struct timeval) { .tv_usec = 1 },
656                              NULL, NULL);
657         if (!NT_STATUS_IS_OK(status)) {
658                 fprintf(stderr, "g_lock_lock returned %s\n",
659                         nt_errstr(status));
660                 goto fail;
661         }
662
663         status = g_lock_unlock(ctx, key);
664         if (!NT_STATUS_IS_OK(status)) {
665                 fprintf(stderr,
666                         "g_lock_unlock returned %s\n",
667                         nt_errstr(status));
668                 goto fail;
669         }
670
671         req = g_lock_lock_send(ev, ev, ctx, key, G_LOCK_WRITE, NULL, NULL);
672         if (req == NULL) {
673                 fprintf(stderr, "g_lock_lock send failed\n");
674                 goto fail;
675         }
676         tevent_req_set_callback(req, lock4_done, &done);
677
678         req = tevent_wakeup_send(ev, ev, timeval_current_ofs(1, 0));
679         if (req == NULL) {
680                 fprintf(stderr, "tevent_wakeup_send failed\n");
681                 goto fail;
682         }
683         tevent_req_set_callback(req, lock4_waited, &exit_pipe[1]);
684
685         done = 0;
686
687         while (done == 0) {
688                 int tevent_ret = tevent_loop_once(ev);
689                 if (tevent_ret != 0) {
690                         perror("tevent_loop_once failed");
691                         goto fail;
692                 }
693         }
694
695         {
696                 struct lock4_check_state state = {
697                         .me = messaging_server_id(msg)
698                 };
699
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",
703                                 nt_errstr(status));
704                         goto fail;
705                 }
706                 if (!state.ok) {
707                         fprintf(stderr, "lock4_check failed\n");
708                         goto fail;
709                 }
710         }
711
712         ret = true;
713 fail:
714         TALLOC_FREE(ctx);
715         TALLOC_FREE(msg);
716         TALLOC_FREE(ev);
717         return ret;
718 }
719
720 struct lock5_parser_state {
721         size_t num_locks;
722 };
723
724 static void lock5_parser(struct server_id exclusive,
725                          size_t num_shared,
726                          const struct server_id *shared,
727                          const uint8_t *data,
728                          size_t datalen,
729                          void *private_data)
730 {
731         struct lock5_parser_state *state = private_data;
732         state->num_locks = num_shared + ((exclusive.pid != 0) ? 1 : 0);
733 }
734
735 /*
736  * Test heuristic cleanup
737  */
738
739 bool run_g_lock5(int dummy)
740 {
741         struct tevent_context *ev = NULL;
742         struct messaging_context *msg = NULL;
743         struct g_lock_ctx *ctx = NULL;
744         const char *lockname = "lock5";
745         pid_t child;
746         int exit_pipe[2], ready_pipe[2];
747         NTSTATUS status;
748         size_t i, nprocs;
749         int ret;
750         bool ok;
751         ssize_t nread;
752         char c;
753
754         nprocs = 5;
755
756         if ((pipe(exit_pipe) != 0) || (pipe(ready_pipe) != 0)) {
757                 perror("pipe failed");
758                 return false;
759         }
760
761         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
762         if (!ok) {
763                 fprintf(stderr, "get_g_lock_ctx failed");
764                 return false;
765         }
766
767         for (i=0; i<nprocs; i++) {
768
769                 child = fork();
770
771                 if (child == -1) {
772                         perror("fork failed");
773                         return false;
774                 }
775
776                 if (child == 0) {
777                         TALLOC_FREE(ctx);
778
779                         status = reinit_after_fork(msg, ev, false, "");
780
781                         close(ready_pipe[0]);
782                         close(exit_pipe[1]);
783
784                         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
785                         if (!ok) {
786                                 fprintf(stderr, "get_g_lock_ctx failed");
787                                 exit(1);
788                         }
789                         status = g_lock_lock(ctx,
790                                              string_term_tdb_data(lockname),
791                                              G_LOCK_READ,
792                                              (struct timeval) { .tv_sec = 1 },
793                                              NULL, NULL);
794                         if (!NT_STATUS_IS_OK(status)) {
795                                 fprintf(stderr,
796                                         "child g_lock_lock failed %s\n",
797                                         nt_errstr(status));
798                                 exit(1);
799                         }
800                         close(ready_pipe[1]);
801                         nread = sys_read(exit_pipe[0], &c, sizeof(c));
802                         if (nread != 0) {
803                                 fprintf(stderr, "sys_read returned %zu (%s)\n",
804                                         nread, strerror(errno));
805                                 exit(1);
806                         }
807                         exit(0);
808                 }
809         }
810
811         close(ready_pipe[1]);
812
813         nread = sys_read(ready_pipe[0], &c, sizeof(c));
814         if (nread != 0) {
815                 fprintf(stderr, "sys_read returned %zu (%s)\n",
816                         nread, strerror(errno));
817                 return false;
818         }
819
820         close(exit_pipe[1]);
821
822         for (i=0; i<nprocs; i++) {
823                 int child_status;
824                 ret = waitpid(-1, &child_status, 0);
825                 if (ret == -1) {
826                         perror("waitpid failed");
827                         return false;
828                 }
829         }
830
831         for (i=0; i<nprocs; i++) {
832                 struct lock5_parser_state state;
833
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",
838                                 nt_errstr(status));
839                         return false;
840                 }
841
842                 if (state.num_locks != (nprocs - i)) {
843                         fprintf(stderr, "nlocks=%zu, expected %zu\n",
844                                 state.num_locks, (nprocs-i));
845                         return false;
846                 }
847
848                 status = g_lock_lock(ctx, string_term_tdb_data(lockname),
849                                      G_LOCK_READ,
850                                      (struct timeval) { .tv_sec = 1 },
851                                      NULL, NULL);
852                 if (!NT_STATUS_IS_OK(status)) {
853                         fprintf(stderr, "g_lock_lock failed %s\n",
854                                 nt_errstr(status));
855                         return false;
856                 }
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",
860                                 nt_errstr(status));
861                         return false;
862                 }
863         }
864
865
866         return true;
867 }
868
869 struct lock6_parser_state {
870         size_t num_locks;
871 };
872
873 static void lock6_parser(struct server_id exclusive,
874                          size_t num_shared,
875                          const struct server_id *shared,
876                          const uint8_t *data,
877                          size_t datalen,
878                          void *private_data)
879 {
880         struct lock6_parser_state *state = private_data;
881         state->num_locks = num_shared + ((exclusive.pid != 0) ? 1 : 0);
882 }
883
884 /*
885  * Test cleanup with contention and stale locks
886  */
887
888 bool run_g_lock6(int dummy)
889 {
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");
894         pid_t child;
895         int exit_pipe[2], ready_pipe[2];
896         NTSTATUS status;
897         size_t i, nprocs;
898         int ret;
899         bool ok;
900         ssize_t nread;
901         char c;
902
903         if ((pipe(exit_pipe) != 0) || (pipe(ready_pipe) != 0)) {
904                 perror("pipe failed");
905                 return false;
906         }
907
908         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
909         if (!ok) {
910                 fprintf(stderr, "get_g_lock_ctx failed");
911                 return false;
912         }
913
914         /*
915          * Wipe all stale locks -- in clustered mode there's no
916          * CLEAR_IF_FIRST
917          */
918         status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
919                              (struct timeval) { .tv_sec = 1 },
920                              NULL, NULL);
921         if (!NT_STATUS_IS_OK(status)) {
922                 fprintf(stderr, "g_lock_lock failed: %s\n",
923                         nt_errstr(status));
924                 return false;
925         }
926         status = g_lock_unlock(ctx, lockname);
927         if (!NT_STATUS_IS_OK(status)) {
928                 fprintf(stderr, "g_lock_unlock failed: %s\n",
929                         nt_errstr(status));
930                 return false;
931         }
932
933         nprocs = 2;
934         for (i=0; i<nprocs; i++) {
935
936                 child = fork();
937
938                 if (child == -1) {
939                         perror("fork failed");
940                         return false;
941                 }
942
943                 if (child == 0) {
944                         TALLOC_FREE(ctx);
945
946                         status = reinit_after_fork(msg, ev, false, "");
947                         if (!NT_STATUS_IS_OK(status)) {
948                                 fprintf(stderr, "reinit_after_fork failed: %s\n",
949                                         nt_errstr(status));
950                                 exit(1);
951                         }
952
953                         close(ready_pipe[0]);
954                         close(exit_pipe[1]);
955
956                         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
957                         if (!ok) {
958                                 fprintf(stderr, "get_g_lock_ctx failed");
959                                 exit(1);
960                         }
961                         status = g_lock_lock(ctx,
962                                              lockname,
963                                              G_LOCK_READ,
964                                              (struct timeval) { .tv_sec = 1 },
965                                              NULL, NULL);
966                         if (!NT_STATUS_IS_OK(status)) {
967                                 fprintf(stderr,
968                                         "child g_lock_lock failed %s\n",
969                                         nt_errstr(status));
970                                 exit(1);
971                         }
972                         if (i == 0) {
973                                 exit(0);
974                         }
975                         close(ready_pipe[1]);
976                         nread = sys_read(exit_pipe[0], &c, sizeof(c));
977                         if (nread != 0) {
978                                 fprintf(stderr, "sys_read returned %zu (%s)\n",
979                                         nread, strerror(errno));
980                                 exit(1);
981                         }
982                         exit(0);
983                 }
984         }
985
986         close(ready_pipe[1]);
987
988         nread = sys_read(ready_pipe[0], &c, sizeof(c));
989         if (nread != 0) {
990                 fprintf(stderr, "sys_read returned %zd (%s)\n",
991                         nread, strerror(errno));
992                 return false;
993         }
994
995         {
996                 int child_status;
997                 ret = waitpid(-1, &child_status, 0);
998                 if (ret == -1) {
999                         perror("waitpid failed");
1000                         return false;
1001                 }
1002         }
1003
1004         {
1005                 struct lock6_parser_state state;
1006
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",
1010                                 nt_errstr(status));
1011                         return false;
1012                 }
1013
1014                 if (state.num_locks != nprocs) {
1015                         fprintf(stderr, "nlocks=%zu, expected %zu\n",
1016                                 state.num_locks, nprocs);
1017                         return false;
1018                 }
1019
1020                 status = g_lock_lock(ctx,
1021                                      lockname,
1022                                      G_LOCK_WRITE,
1023                                      (struct timeval) { .tv_sec = 1 },
1024                                      NULL, NULL);
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),
1028                                 nt_errstr(status));
1029                         return false;
1030                 }
1031
1032                 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
1033                                      (struct timeval) { .tv_sec = 1 },
1034                                      NULL, NULL);
1035                 if (!NT_STATUS_IS_OK(status)) {
1036                         fprintf(stderr, "g_lock_lock failed: %s\n",
1037                                 nt_errstr(status));
1038                         return false;
1039                 }
1040         }
1041
1042         close(exit_pipe[1]);
1043
1044         {
1045                 int child_status;
1046                 ret = waitpid(-1, &child_status, 0);
1047                 if (ret == -1) {
1048                         perror("waitpid failed");
1049                         return false;
1050                 }
1051         }
1052
1053         status = g_lock_lock(ctx, lockname, G_LOCK_UPGRADE,
1054                              (struct timeval) { .tv_sec = 1 },
1055                              NULL, NULL);
1056         if (!NT_STATUS_IS_OK(status)) {
1057                 fprintf(stderr, "g_lock_lock failed: %s\n",
1058                         nt_errstr(status));
1059                 return false;
1060         }
1061
1062         return true;
1063 }
1064
1065 /*
1066  * Test upgrade deadlock
1067  */
1068
1069 bool run_g_lock7(int dummy)
1070 {
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);
1076         pid_t child;
1077         int ready_pipe[2];
1078         int down_pipe[2];
1079         ssize_t n;
1080         NTSTATUS status;
1081         bool ret = false;
1082         bool ok = true;
1083
1084         if ((pipe(ready_pipe) != 0) || (pipe(down_pipe) != 0)) {
1085                 perror("pipe failed");
1086                 return false;
1087         }
1088
1089         child = fork();
1090
1091         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
1092         if (!ok) {
1093                 goto fail;
1094         }
1095
1096         if (child == -1) {
1097                 perror("fork failed");
1098                 return false;
1099         }
1100
1101         if (child == 0) {
1102                 struct tevent_req *req = NULL;
1103
1104                 close(ready_pipe[0]);
1105                 ready_pipe[0] = -1;
1106                 close(down_pipe[1]);
1107                 down_pipe[1] = -1;
1108
1109                 status = reinit_after_fork(msg, ev, false, "");
1110                 if (!NT_STATUS_IS_OK(status)) {
1111                         fprintf(stderr,
1112                                 "reinit_after_fork failed: %s\n",
1113                                 nt_errstr(status));
1114                         exit(1);
1115                 }
1116
1117                 printf("%d: locking READ\n", (int)getpid());
1118
1119                 status = g_lock_lock(
1120                         ctx,
1121                         key,
1122                         G_LOCK_READ,
1123                         (struct timeval) { .tv_usec = 1 },
1124                         NULL, NULL);
1125                 if (!NT_STATUS_IS_OK(status)) {
1126                         fprintf(stderr,
1127                                 "g_lock_lock(READ) failed: %s\n",
1128                                 nt_errstr(status));
1129                         exit(1);
1130                 }
1131
1132                 ok = true;
1133
1134                 n = sys_write(ready_pipe[1], &ok, sizeof(ok));
1135                 if (n != sizeof(ok)) {
1136                         fprintf(stderr,
1137                                 "sys_write failed: %s\n",
1138                                 strerror(errno));
1139                         exit(1);
1140                 }
1141
1142                 n = sys_read(down_pipe[0], &ok, sizeof(ok));
1143                 if (n != sizeof(ok)) {
1144                         fprintf(stderr,
1145                                 "sys_read failed: %s\n",
1146                                 strerror(errno));
1147                         exit(1);
1148                 }
1149
1150                 printf("%d: starting UPGRADE\n", (int)getpid());
1151
1152                 req = g_lock_lock_send(
1153                         msg,
1154                         ev,
1155                         ctx,
1156                         key,
1157                         G_LOCK_UPGRADE,
1158                         NULL, NULL);
1159                 if (req == NULL) {
1160                         fprintf(stderr, "g_lock_lock_send(UPGRADE) failed\n");
1161                         exit(1);
1162                 }
1163
1164                 n = sys_write(ready_pipe[1], &ok, sizeof(ok));
1165                 if (n != sizeof(ok)) {
1166                         fprintf(stderr,
1167                                 "sys_write failed: %s\n",
1168                                 strerror(errno));
1169                         exit(1);
1170                 }
1171
1172                 exit(0);
1173         }
1174
1175         close(ready_pipe[1]);
1176         close(down_pipe[0]);
1177
1178         if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
1179                 perror("read failed");
1180                 return false;
1181         }
1182         if (!ok) {
1183                 fprintf(stderr, "child returned error\n");
1184                 return false;
1185         }
1186
1187         status = g_lock_lock(
1188                 ctx,
1189                 key,
1190                 G_LOCK_READ,
1191                 (struct timeval) { .tv_usec = 1 },
1192                 NULL, NULL);
1193         if (!NT_STATUS_IS_OK(status)) {
1194                 fprintf(stderr,
1195                         "g_lock_lock(READ) failed: %s\n",
1196                         nt_errstr(status));
1197                 goto fail;
1198         }
1199
1200         n = sys_write(down_pipe[1], &ok, sizeof(ok));
1201         if (n != sizeof(ok)) {
1202                 fprintf(stderr,
1203                         "sys_write failed: %s\n",
1204                         strerror(errno));
1205                 goto fail;
1206         }
1207
1208         if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
1209                 perror("read failed");
1210                 goto fail;
1211         }
1212
1213         status = g_lock_lock(
1214                 ctx,
1215                 key,
1216                 G_LOCK_UPGRADE,
1217                 (struct timeval) { .tv_sec = 10 },
1218                 NULL, NULL);
1219         if (!NT_STATUS_EQUAL(status, NT_STATUS_POSSIBLE_DEADLOCK)) {
1220                 fprintf(stderr,
1221                         "g_lock_lock returned %s\n",
1222                         nt_errstr(status));
1223                 goto fail;
1224         }
1225
1226         ret = true;
1227 fail:
1228         TALLOC_FREE(ctx);
1229         TALLOC_FREE(msg);
1230         TALLOC_FREE(ev);
1231         return ret;
1232 }
1233
1234 bool run_g_lock8(int dummy)
1235 {
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");
1241         NTSTATUS status;
1242         bool ok;
1243
1244         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
1245         if (!ok) {
1246                 fprintf(stderr, "get_g_lock_ctx failed");
1247                 return false;
1248         }
1249
1250         req = g_lock_watch_data_send(
1251                 ev, ev, ctx, lockname, (struct server_id) { .pid = 0 });
1252         if (req == NULL) {
1253                 fprintf(stderr, "get_g_lock_ctx failed");
1254                 return false;
1255         }
1256
1257         status = g_lock_lock(
1258                 ctx,
1259                 lockname,
1260                 G_LOCK_WRITE,
1261                 (struct timeval) { .tv_sec = 999 },
1262                 NULL, NULL);
1263         if (!NT_STATUS_IS_OK(status)) {
1264                 fprintf(stderr,
1265                         "g_lock_lock failed: %s\n",
1266                         nt_errstr(status));
1267                 return false;
1268         }
1269
1270         status = g_lock_write_data(
1271                 ctx, lockname, lockname.dptr, lockname.dsize);
1272         if (!NT_STATUS_IS_OK(status)) {
1273                 fprintf(stderr,
1274                         "g_lock_write_data failed: %s\n",
1275                         nt_errstr(status));
1276                 return false;
1277         }
1278
1279         status = g_lock_write_data(ctx, lockname, NULL, 0);
1280         if (!NT_STATUS_IS_OK(status)) {
1281                 fprintf(stderr,
1282                         "g_lock_write_data failed: %s\n",
1283                         nt_errstr(status));
1284                 return false;
1285         }
1286
1287         status = g_lock_unlock(ctx, lockname);
1288         if (!NT_STATUS_IS_OK(status)) {
1289                 fprintf(stderr,
1290                         "g_lock_unlock failed: %s\n",
1291                         nt_errstr(status));
1292                 return false;
1293         }
1294
1295         ok = tevent_req_poll_ntstatus(req, ev, &status);
1296         if (!ok) {
1297                 fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
1298                 return false;
1299         }
1300         if (!NT_STATUS_IS_OK(status)) {
1301                 fprintf(stderr,
1302                         "tevent_req_poll_ntstatus failed: %s\n",
1303                         nt_errstr(status));
1304                 return false;
1305         }
1306
1307         return true;
1308 }
1309
1310 extern int torture_numops;
1311 extern int torture_nprocs;
1312
1313 static struct timeval tp1, tp2;
1314
1315 static void start_timer(void)
1316 {
1317         gettimeofday(&tp1,NULL);
1318 }
1319
1320 static double end_timer(void)
1321 {
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));
1325 }
1326
1327 /*
1328  * g_lock ping_pong
1329  */
1330
1331 bool run_g_lock_ping_pong(int dummy)
1332 {
1333         struct tevent_context *ev = NULL;
1334         struct messaging_context *msg = NULL;
1335         struct g_lock_ctx *ctx = NULL;
1336         fstring name;
1337         NTSTATUS status;
1338         int i = 0;
1339         bool ret = false;
1340         bool ok;
1341         unsigned count = 0;
1342
1343         torture_nprocs = MAX(2, torture_nprocs);
1344
1345         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
1346         if (!ok) {
1347                 goto fail;
1348         }
1349
1350         start_timer();
1351
1352         snprintf(name, sizeof(name), "ping_pong_%d", i);
1353
1354         status = g_lock_lock(ctx, string_term_tdb_data(name), G_LOCK_WRITE,
1355                              (struct timeval) { .tv_sec = 60 },
1356                              NULL, NULL);
1357         if (!NT_STATUS_IS_OK(status)) {
1358                 fprintf(stderr, "g_lock_lock failed: %s\n",
1359                         nt_errstr(status));
1360                 goto fail;
1361         }
1362
1363         for (i=0; i<torture_numops; i++) {
1364
1365                 name[10] = '0' + ((i+1) % torture_nprocs);
1366
1367                 status = g_lock_lock(ctx, string_term_tdb_data(name),
1368                                      G_LOCK_WRITE,
1369                                      (struct timeval) { .tv_sec = 60 },
1370                                      NULL, NULL);
1371                 if (!NT_STATUS_IS_OK(status)) {
1372                         fprintf(stderr, "g_lock_lock failed: %s\n",
1373                                 nt_errstr(status));
1374                         goto fail;
1375                 }
1376
1377                 name[10] = '0' + ((i) % torture_nprocs);
1378
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",
1382                                 nt_errstr(status));
1383                         goto fail;
1384                 }
1385
1386                 count++;
1387
1388                 if (end_timer() > 1.0) {
1389                         printf("%8u locks/sec\r",
1390                                (unsigned)(2*count/end_timer()));
1391                         fflush(stdout);
1392                         start_timer();
1393                         count=0;
1394                 }
1395         }
1396
1397         ret = true;
1398 fail:
1399         TALLOC_FREE(ctx);
1400         TALLOC_FREE(msg);
1401         TALLOC_FREE(ev);
1402         return ret;
1403 }