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