wscript: Add check for --wrap linker flag
[vlendec/samba-autobuild/.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
28 static bool get_g_lock_ctx(TALLOC_CTX *mem_ctx,
29                            struct tevent_context **ev,
30                            struct messaging_context **msg,
31                            struct g_lock_ctx **ctx)
32 {
33         *ev = server_event_context();
34         if (*ev == NULL) {
35                 fprintf(stderr, "tevent_context_init failed\n");
36                 return false;
37         }
38         *msg = server_messaging_context();
39         if (*msg == NULL) {
40                 fprintf(stderr, "messaging_init failed\n");
41                 TALLOC_FREE(*ev);
42                 return false;
43         }
44         *ctx = g_lock_ctx_init(*ev, *msg);
45         if (*ctx == NULL) {
46                 fprintf(stderr, "g_lock_ctx_init failed\n");
47                 TALLOC_FREE(*msg);
48                 TALLOC_FREE(*ev);
49                 return false;
50         }
51
52         return true;
53 }
54
55 bool run_g_lock1(int dummy)
56 {
57         struct tevent_context *ev = NULL;
58         struct messaging_context *msg = NULL;
59         struct g_lock_ctx *ctx = NULL;
60         const char *lockname = "lock1";
61         NTSTATUS status;
62         bool ret = false;
63         bool ok;
64
65         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
66         if (!ok) {
67                 goto fail;
68         }
69
70         status = g_lock_lock(ctx, lockname, G_LOCK_READ,
71                              (struct timeval) { .tv_sec = 1 });
72         if (!NT_STATUS_IS_OK(status)) {
73                 fprintf(stderr, "g_lock_lock failed: %s\n",
74                         nt_errstr(status));
75                 goto fail;
76         }
77
78         status = g_lock_lock(ctx, lockname, G_LOCK_READ,
79                              (struct timeval) { .tv_sec = 1 });
80         if (!NT_STATUS_EQUAL(status, NT_STATUS_WAS_LOCKED)) {
81                 fprintf(stderr, "Double lock got %s\n",
82                         nt_errstr(status));
83                 goto fail;
84         }
85
86         status = g_lock_unlock(ctx, lockname);
87         if (!NT_STATUS_IS_OK(status)) {
88                 fprintf(stderr, "g_lock_unlock failed: %s\n",
89                         nt_errstr(status));
90                 goto fail;
91         }
92
93         status = g_lock_unlock(ctx, lockname);
94         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
95                 fprintf(stderr, "g_lock_unlock returned: %s\n",
96                         nt_errstr(status));
97                 goto fail;
98         }
99
100         ret = true;
101 fail:
102         TALLOC_FREE(ctx);
103         TALLOC_FREE(msg);
104         TALLOC_FREE(ev);
105         return ret;
106 }
107
108 struct lock2_parser_state {
109         uint8_t *rdata;
110         bool ok;
111 };
112
113 static void lock2_parser(const struct g_lock_rec *locks,
114                          size_t num_locks,
115                          const uint8_t *data,
116                          size_t datalen,
117                          void *private_data)
118 {
119         struct lock2_parser_state *state = private_data;
120
121         if (datalen != sizeof(uint8_t)) {
122                 return;
123         }
124         *state->rdata = *data;
125         state->ok = true;
126 }
127
128 /*
129  * Test g_lock_write_data
130  */
131
132 bool run_g_lock2(int dummy)
133 {
134         struct tevent_context *ev = NULL;
135         struct messaging_context *msg = NULL;
136         struct g_lock_ctx *ctx = NULL;
137         const char *lockname = "lock2";
138         uint8_t data = 42;
139         uint8_t rdata;
140         struct lock2_parser_state state = { .rdata = &rdata };
141         NTSTATUS status;
142         bool ret = false;
143         bool ok;
144
145         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
146         if (!ok) {
147                 goto fail;
148         }
149
150         status = g_lock_write_data(ctx, lockname, &data, sizeof(data));
151         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_LOCKED)) {
152                 fprintf(stderr, "unlocked g_lock_write_data returned %s\n",
153                         nt_errstr(status));
154                 goto fail;
155         }
156
157         status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
158                              (struct timeval) { .tv_sec = 1 });
159         if (!NT_STATUS_IS_OK(status)) {
160                 fprintf(stderr, "g_lock_lock returned %s\n",
161                         nt_errstr(status));
162                 goto fail;
163         }
164
165         status = g_lock_write_data(ctx, lockname, &data, sizeof(data));
166         if (!NT_STATUS_IS_OK(status)) {
167                 fprintf(stderr, "g_lock_write_data failed: %s\n",
168                         nt_errstr(status));
169                 goto fail;
170         }
171
172         status = g_lock_unlock(ctx, lockname);
173         if (!NT_STATUS_IS_OK(status)) {
174                 fprintf(stderr, "g_lock_unlock failed: %s\n",
175                         nt_errstr(status));
176                 goto fail;
177         }
178
179         status = g_lock_dump(ctx, lockname, lock2_parser, &state);
180         if (!NT_STATUS_IS_OK(status)) {
181                 fprintf(stderr, "g_lock_dump failed: %s\n",
182                         nt_errstr(status));
183                 goto fail;
184         }
185
186         if (!state.ok) {
187                 fprintf(stderr, "Could not parse data\n");
188                 goto fail;
189         }
190         if (rdata != data) {
191                 fprintf(stderr, "Returned %"PRIu8", expected %"PRIu8"\n",
192                         rdata, data);
193                 goto fail;
194         }
195
196         ret = true;
197 fail:
198         TALLOC_FREE(ctx);
199         TALLOC_FREE(msg);
200         TALLOC_FREE(ev);
201         return ret;
202 }
203
204 struct lock3_parser_state {
205         struct server_id self;
206         enum g_lock_type lock_type;
207         bool ok;
208 };
209
210 static void lock3_parser(const struct g_lock_rec *locks,
211                          size_t num_locks,
212                          const uint8_t *data,
213                          size_t datalen,
214                          void *private_data)
215 {
216         struct lock3_parser_state *state = private_data;
217
218         if (datalen != 0) {
219                 fprintf(stderr, "datalen=%zu\n", datalen);
220                 return;
221         }
222         if (num_locks != 1) {
223                 fprintf(stderr, "num_locks=%zu\n", num_locks);
224                 return;
225         }
226         if (locks[0].lock_type != state->lock_type) {
227                 fprintf(stderr, "found type %d, expected %d\n",
228                         (int)locks[0].lock_type, (int)state->lock_type);
229                 return;
230         }
231         if (!server_id_equal(&locks[0].pid, &state->self)) {
232                 struct server_id_buf tmp1, tmp2;
233                 fprintf(stderr, "found pid %s, expected %s\n",
234                         server_id_str_buf(locks[0].pid, &tmp1),
235                         server_id_str_buf(state->self, &tmp2));
236                 return;
237         }
238
239         state->ok = true;
240 }
241
242 /*
243  * Test lock upgrade/downgrade
244  */
245
246 bool run_g_lock3(int dummy)
247 {
248         struct tevent_context *ev = NULL;
249         struct messaging_context *msg = NULL;
250         struct g_lock_ctx *ctx = NULL;
251         const char *lockname = "lock3";
252         struct lock3_parser_state state;
253         NTSTATUS status;
254         bool ret = false;
255         bool ok;
256
257         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
258         if (!ok) {
259                 goto fail;
260         }
261
262         state.self = messaging_server_id(msg);
263
264         status = g_lock_lock(ctx, lockname, G_LOCK_READ,
265                              (struct timeval) { .tv_sec = 1 });
266         if (!NT_STATUS_IS_OK(status)) {
267                 fprintf(stderr, "g_lock_lock returned %s\n",
268                         nt_errstr(status));
269                 goto fail;
270         }
271
272         status = g_lock_lock(ctx, lockname, G_LOCK_READ,
273                              (struct timeval) { .tv_sec = 1 });
274         if (!NT_STATUS_EQUAL(status, NT_STATUS_WAS_LOCKED)) {
275                 fprintf(stderr, "g_lock_lock returned %s, expected %s\n",
276                         nt_errstr(status), nt_errstr(NT_STATUS_WAS_LOCKED));
277                 goto fail;
278         }
279
280         state.lock_type = G_LOCK_READ;
281         state.ok = false;
282
283         status = g_lock_dump(ctx, lockname, lock3_parser, &state);
284         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
285                 fprintf(stderr, "g_lock_dump returned %s\n",
286                         nt_errstr(status));
287                 goto fail;
288         }
289         if (!state.ok) {
290                 goto fail;
291         }
292
293         status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
294                              (struct timeval) { .tv_sec = 1 });
295         if (!NT_STATUS_IS_OK(status)) {
296                 fprintf(stderr, "g_lock_lock returned %s\n",
297                         nt_errstr(status));
298                 goto fail;
299         }
300
301         state.lock_type = G_LOCK_WRITE;
302         state.ok = false;
303
304         status = g_lock_dump(ctx, lockname, lock3_parser, &state);
305         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
306                 fprintf(stderr, "g_lock_dump returned %s\n",
307                         nt_errstr(status));
308                 goto fail;
309         }
310         if (!state.ok) {
311                 goto fail;
312         }
313
314
315         ret = true;
316 fail:
317         TALLOC_FREE(ctx);
318         TALLOC_FREE(msg);
319         TALLOC_FREE(ev);
320         return ret;
321 }
322
323 static bool lock4_child(const char *lockname,
324                         int ready_pipe, int exit_pipe)
325 {
326         struct tevent_context *ev = NULL;
327         struct messaging_context *msg = NULL;
328         struct g_lock_ctx *ctx = NULL;
329         NTSTATUS status;
330         ssize_t n;
331         bool ok;
332
333         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
334         if (!ok) {
335                 return false;
336         }
337
338         status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
339                              (struct timeval) { .tv_sec = 1 });
340         if (!NT_STATUS_IS_OK(status)) {
341                 fprintf(stderr, "child: g_lock_lock returned %s\n",
342                         nt_errstr(status));
343                 return false;
344         }
345
346         n = sys_write(ready_pipe, &ok, sizeof(ok));
347         if (n != sizeof(ok)) {
348                 fprintf(stderr, "child: write failed\n");
349                 return false;
350         }
351
352         if (ok) {
353                 n = sys_read(exit_pipe, &ok, sizeof(ok));
354                 if (n != 0) {
355                         fprintf(stderr, "child: read failed\n");
356                         return false;
357                 }
358         }
359
360         return true;
361 }
362
363 static void lock4_done(struct tevent_req *subreq)
364 {
365         int *done = tevent_req_callback_data_void(subreq);
366         NTSTATUS status;
367
368         status = g_lock_lock_recv(subreq);
369         TALLOC_FREE(subreq);
370         if (!NT_STATUS_IS_OK(status)) {
371                 fprintf(stderr, "g_lock_lock_recv returned %s\n",
372                         nt_errstr(status));
373                 *done = -1;
374                 return;
375         }
376         *done = 1;
377 }
378
379 static void lock4_waited(struct tevent_req *subreq)
380 {
381         int *exit_pipe = tevent_req_callback_data_void(subreq);
382         pid_t child;
383         int status;
384         bool ok;
385
386         printf("waited\n");
387
388         ok = tevent_wakeup_recv(subreq);
389         TALLOC_FREE(subreq);
390         if (!ok) {
391                 fprintf(stderr, "tevent_wakeup_recv failed\n");
392         }
393         close(*exit_pipe);
394
395         child = wait(&status);
396
397         printf("child %d exited with %d\n", (int)child, status);
398 }
399
400 struct lock4_check_state {
401         struct server_id me;
402         bool ok;
403 };
404
405 static void lock4_check(const struct g_lock_rec *locks,
406                         size_t num_locks,
407                         const uint8_t *data,
408                         size_t datalen,
409                         void *private_data)
410 {
411         struct lock4_check_state *state = private_data;
412
413         if (num_locks != 1) {
414                 fprintf(stderr, "num_locks=%zu\n", num_locks);
415                 return;
416         }
417
418         if (!serverid_equal(&state->me, &locks[0].pid)) {
419                 struct server_id_buf buf1, buf2;
420                 fprintf(stderr, "me=%s, locker=%s\n",
421                         server_id_str_buf(state->me, &buf1),
422                         server_id_str_buf(locks[0].pid, &buf2));
423                 return;
424         }
425
426         if (locks[0].lock_type != G_LOCK_WRITE) {
427                 fprintf(stderr, "wrong lock type: %d\n",
428                         (int)locks[0].lock_type);
429                 return;
430         }
431
432         state->ok = true;
433 }
434
435 /*
436  * Test a lock conflict
437  */
438
439 bool run_g_lock4(int dummy)
440 {
441         struct tevent_context *ev = NULL;
442         struct messaging_context *msg = NULL;
443         struct g_lock_ctx *ctx = NULL;
444         const char *lockname = "lock4";
445         pid_t child;
446         int ready_pipe[2];
447         int exit_pipe[2];
448         NTSTATUS status;
449         bool ret = false;
450         struct tevent_req *req;
451         bool ok;
452         int done;
453
454         if ((pipe(ready_pipe) != 0) || (pipe(exit_pipe) != 0)) {
455                 perror("pipe failed");
456                 return false;
457         }
458
459         child = fork();
460
461         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
462         if (!ok) {
463                 goto fail;
464         }
465
466         if (child == -1) {
467                 perror("fork failed");
468                 return false;
469         }
470
471         if (child == 0) {
472                 close(ready_pipe[0]);
473                 close(exit_pipe[1]);
474                 ok = lock4_child(lockname, ready_pipe[1], exit_pipe[0]);
475                 exit(ok ? 0 : 1);
476         }
477
478         close(ready_pipe[1]);
479         close(exit_pipe[0]);
480
481         if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
482                 perror("read failed");
483                 return false;
484         }
485
486         if (!ok) {
487                 fprintf(stderr, "child returned error\n");
488                 return false;
489         }
490
491         status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
492                              (struct timeval) { .tv_usec = 1 });
493         if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
494                 fprintf(stderr, "g_lock_lock returned %s\n",
495                         nt_errstr(status));
496                 goto fail;
497         }
498
499         status = g_lock_lock(ctx, lockname, G_LOCK_READ,
500                              (struct timeval) { .tv_usec = 1 });
501         if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
502                 fprintf(stderr, "g_lock_lock returned %s\n",
503                         nt_errstr(status));
504                 goto fail;
505         }
506
507         req = g_lock_lock_send(ev, ev, ctx, lockname, G_LOCK_WRITE);
508         if (req == NULL) {
509                 fprintf(stderr, "g_lock_lock send failed\n");
510                 goto fail;
511         }
512         tevent_req_set_callback(req, lock4_done, &done);
513
514         req = tevent_wakeup_send(ev, ev, timeval_current_ofs(1, 0));
515         if (req == NULL) {
516                 fprintf(stderr, "tevent_wakeup_send failed\n");
517                 goto fail;
518         }
519         tevent_req_set_callback(req, lock4_waited, &exit_pipe[1]);
520
521         done = 0;
522
523         while (done == 0) {
524                 int tevent_ret = tevent_loop_once(ev);
525                 if (tevent_ret != 0) {
526                         perror("tevent_loop_once failed");
527                         goto fail;
528                 }
529         }
530
531         {
532                 struct lock4_check_state state = {
533                         .me = messaging_server_id(msg)
534                 };
535
536                 status = g_lock_dump(ctx, lockname, lock4_check, &state);
537                 if (!NT_STATUS_IS_OK(status)) {
538                         fprintf(stderr, "g_lock_dump failed: %s\n",
539                                 nt_errstr(status));
540                         goto fail;
541                 }
542                 if (!state.ok) {
543                         fprintf(stderr, "lock4_check failed\n");
544                         goto fail;
545                 }
546         }
547
548         ret = true;
549 fail:
550         TALLOC_FREE(ctx);
551         TALLOC_FREE(msg);
552         TALLOC_FREE(ev);
553         return ret;
554 }
555
556 struct lock5_parser_state {
557         size_t num_locks;
558 };
559
560 static void lock5_parser(const struct g_lock_rec *locks,
561                          size_t num_locks,
562                          const uint8_t *data,
563                          size_t datalen,
564                          void *private_data)
565 {
566         struct lock5_parser_state *state = private_data;
567         state->num_locks = num_locks;
568 }
569
570 /*
571  * Test heuristic cleanup
572  */
573
574 bool run_g_lock5(int dummy)
575 {
576         struct tevent_context *ev = NULL;
577         struct messaging_context *msg = NULL;
578         struct g_lock_ctx *ctx = NULL;
579         const char *lockname = "lock5";
580         pid_t child;
581         int exit_pipe[2], ready_pipe[2];
582         NTSTATUS status;
583         size_t i, nprocs;
584         int ret;
585         bool ok;
586         ssize_t nread;
587         char c;
588
589         nprocs = 5;
590
591         if ((pipe(exit_pipe) != 0) || (pipe(ready_pipe) != 0)) {
592                 perror("pipe failed");
593                 return false;
594         }
595
596         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
597         if (!ok) {
598                 fprintf(stderr, "get_g_lock_ctx failed");
599                 return false;
600         }
601
602         for (i=0; i<nprocs; i++) {
603
604                 child = fork();
605
606                 if (child == -1) {
607                         perror("fork failed");
608                         return false;
609                 }
610
611                 if (child == 0) {
612                         TALLOC_FREE(ctx);
613
614                         status = reinit_after_fork(msg, ev, false, "");
615
616                         close(ready_pipe[0]);
617                         close(exit_pipe[1]);
618
619                         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
620                         if (!ok) {
621                                 fprintf(stderr, "get_g_lock_ctx failed");
622                                 exit(1);
623                         }
624                         status = g_lock_lock(ctx, lockname, G_LOCK_READ,
625                                              (struct timeval) { .tv_sec = 1 });
626                         if (!NT_STATUS_IS_OK(status)) {
627                                 fprintf(stderr,
628                                         "child g_lock_lock failed %s\n",
629                                         nt_errstr(status));
630                                 exit(1);
631                         }
632                         close(ready_pipe[1]);
633                         nread = sys_read(exit_pipe[0], &c, sizeof(c));
634                         if (nread != 0) {
635                                 fprintf(stderr, "sys_read returned %zu (%s)\n",
636                                         nread, strerror(errno));
637                                 exit(1);
638                         }
639                         exit(0);
640                 }
641         }
642
643         close(ready_pipe[1]);
644
645         nread = sys_read(ready_pipe[0], &c, sizeof(c));
646         if (nread != 0) {
647                 fprintf(stderr, "sys_read returned %zu (%s)\n",
648                         nread, strerror(errno));
649                 return false;
650         }
651
652         close(exit_pipe[1]);
653
654         for (i=0; i<nprocs; i++) {
655                 int child_status;
656                 ret = waitpid(-1, &child_status, 0);
657                 if (ret == -1) {
658                         perror("waitpid failed");
659                         return false;
660                 }
661         }
662
663         for (i=0; i<nprocs; i++) {
664                 struct lock5_parser_state state;
665
666                 status = g_lock_dump(ctx, lockname, lock5_parser, &state);
667                 if (!NT_STATUS_IS_OK(status)) {
668                         fprintf(stderr, "g_lock_dump returned %s\n",
669                                 nt_errstr(status));
670                         return false;
671                 }
672
673                 if (state.num_locks != (nprocs - i)) {
674                         fprintf(stderr, "nlocks=%zu, expected %zu\n",
675                                 state.num_locks, (nprocs-i));
676                         return false;
677                 }
678
679                 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
680                                      (struct timeval) { .tv_sec = 1 });
681                 if (!NT_STATUS_IS_OK(status)) {
682                         fprintf(stderr, "g_lock_lock failed %s\n",
683                                 nt_errstr(status));
684                         return false;
685                 }
686                 status = g_lock_unlock(ctx, lockname);
687                 if (!NT_STATUS_IS_OK(status)) {
688                         fprintf(stderr, "g_lock_unlock failed %s\n",
689                                 nt_errstr(status));
690                         return false;
691                 }
692         }
693
694
695         return true;
696 }
697
698 extern int torture_numops;
699 extern int torture_nprocs;
700
701 static struct timeval tp1, tp2;
702
703 static void start_timer(void)
704 {
705         gettimeofday(&tp1,NULL);
706 }
707
708 static double end_timer(void)
709 {
710         gettimeofday(&tp2,NULL);
711         return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) -
712                 (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
713 }
714
715 /*
716  * g_lock ping_pong
717  */
718
719 bool run_g_lock_ping_pong(int dummy)
720 {
721         struct tevent_context *ev = NULL;
722         struct messaging_context *msg = NULL;
723         struct g_lock_ctx *ctx = NULL;
724         fstring name;
725         NTSTATUS status;
726         int i = 0;
727         bool ret = false;
728         bool ok;
729         unsigned count = 0;
730
731         torture_nprocs = MAX(2, torture_nprocs);
732
733         ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
734         if (!ok) {
735                 goto fail;
736         }
737
738         start_timer();
739
740         snprintf(name, sizeof(name), "ping_pong_%d", i);
741
742         status = g_lock_lock(ctx, name, G_LOCK_WRITE,
743                              (struct timeval) { .tv_sec = 60 });
744         if (!NT_STATUS_IS_OK(status)) {
745                 fprintf(stderr, "g_lock_lock failed: %s\n",
746                         nt_errstr(status));
747                 goto fail;
748         }
749
750         for (i=0; i<torture_numops; i++) {
751
752                 name[10] = '0' + ((i+1) % torture_nprocs);
753
754                 status = g_lock_lock(ctx, name, G_LOCK_WRITE,
755                                      (struct timeval) { .tv_sec = 60 });
756                 if (!NT_STATUS_IS_OK(status)) {
757                         fprintf(stderr, "g_lock_lock failed: %s\n",
758                                 nt_errstr(status));
759                         goto fail;
760                 }
761
762                 name[10] = '0' + ((i) % torture_nprocs);
763
764                 status = g_lock_unlock(ctx, name);
765                 if (!NT_STATUS_IS_OK(status)) {
766                         fprintf(stderr, "g_lock_unlock failed: %s\n",
767                                 nt_errstr(status));
768                         goto fail;
769                 }
770
771                 count++;
772
773                 if (end_timer() > 1.0) {
774                         printf("%8u locks/sec\r",
775                                (unsigned)(2*count/end_timer()));
776                         fflush(stdout);
777                         start_timer();
778                         count=0;
779                 }
780         }
781
782         ret = true;
783 fail:
784         TALLOC_FREE(ctx);
785         TALLOC_FREE(msg);
786         TALLOC_FREE(ev);
787         return ret;
788 }