Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Scalability test for notifies
4 : Copyright (C) Volker Lendecke 2012
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 "libsmb/libsmb.h"
23 : #include "lib/util/tevent_ntstatus.h"
24 : #include "libcli/security/security.h"
25 : #include "lib/tevent_barrier.h"
26 :
27 : extern int torture_nprocs, torture_numops;
28 :
29 : struct wait_for_one_notify_state {
30 : struct tevent_context *ev;
31 : struct cli_state *cli;
32 : uint16_t dnum;
33 : uint32_t filter;
34 : bool recursive;
35 : unsigned *num_notifies;
36 : };
37 :
38 : static void wait_for_one_notify_opened(struct tevent_req *subreq);
39 : static void wait_for_one_notify_chkpath_done(struct tevent_req *subreq);
40 : static void wait_for_one_notify_done(struct tevent_req *subreq);
41 : static void wait_for_one_notify_closed(struct tevent_req *subreq);
42 :
43 0 : static struct tevent_req *wait_for_one_notify_send(TALLOC_CTX *mem_ctx,
44 : struct tevent_context *ev,
45 : struct cli_state *cli,
46 : const char *path,
47 : uint32_t filter,
48 : bool recursive,
49 : unsigned *num_notifies)
50 : {
51 0 : struct tevent_req *req, *subreq;
52 0 : struct wait_for_one_notify_state *state;
53 :
54 0 : req = tevent_req_create(mem_ctx, &state,
55 : struct wait_for_one_notify_state);
56 0 : if (req == NULL) {
57 0 : return NULL;
58 : }
59 0 : state->ev = ev;
60 0 : state->cli = cli;
61 0 : state->filter = filter;
62 0 : state->recursive = recursive;
63 0 : state->num_notifies = num_notifies;
64 :
65 0 : subreq = cli_ntcreate_send(
66 0 : state, state->ev, state->cli, path, 0,
67 : MAXIMUM_ALLOWED_ACCESS,
68 : 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
69 : FILE_OPEN, FILE_DIRECTORY_FILE,
70 : SMB2_IMPERSONATION_IMPERSONATION, 0);
71 0 : if (tevent_req_nomem(subreq, req)) {
72 0 : return tevent_req_post(req, ev);
73 : }
74 0 : tevent_req_set_callback(subreq, wait_for_one_notify_opened, req);
75 0 : return req;
76 : }
77 :
78 0 : static void wait_for_one_notify_opened(struct tevent_req *subreq)
79 : {
80 0 : struct tevent_req *req = tevent_req_callback_data(
81 : subreq, struct tevent_req);
82 0 : struct wait_for_one_notify_state *state = tevent_req_data(
83 : req, struct wait_for_one_notify_state);
84 0 : NTSTATUS status;
85 :
86 0 : status = cli_ntcreate_recv(subreq, &state->dnum, NULL);
87 0 : TALLOC_FREE(subreq);
88 0 : if (tevent_req_nterror(req, status)) {
89 0 : return;
90 : }
91 0 : subreq = cli_notify_send(state, state->ev, state->cli, state->dnum,
92 0 : 0xffff, state->filter, state->recursive);
93 0 : if (tevent_req_nomem(subreq, req)) {
94 0 : return;
95 : }
96 0 : tevent_req_set_callback(subreq, wait_for_one_notify_done, req);
97 :
98 : /*
99 : * To make sure the notify received at the server, we do another no-op
100 : * that is replied to.
101 : */
102 0 : subreq = cli_chkpath_send(state, state->ev, state->cli, "\\");
103 0 : if (tevent_req_nomem(subreq, req)) {
104 0 : return;
105 : }
106 0 : tevent_req_set_callback(subreq, wait_for_one_notify_chkpath_done, req);
107 : }
108 :
109 0 : static void wait_for_one_notify_chkpath_done(struct tevent_req *subreq)
110 : {
111 0 : struct tevent_req *req = tevent_req_callback_data(
112 : subreq, struct tevent_req);
113 0 : struct wait_for_one_notify_state *state = tevent_req_data(
114 : req, struct wait_for_one_notify_state);
115 0 : NTSTATUS status;
116 :
117 0 : status = cli_chkpath_recv(subreq);
118 0 : TALLOC_FREE(subreq);
119 0 : if (tevent_req_nterror(req, status)) {
120 0 : return;
121 : }
122 0 : *state->num_notifies += 1;
123 : }
124 :
125 0 : static void wait_for_one_notify_done(struct tevent_req *subreq)
126 : {
127 0 : struct tevent_req *req = tevent_req_callback_data(
128 : subreq, struct tevent_req);
129 0 : struct wait_for_one_notify_state *state = tevent_req_data(
130 : req, struct wait_for_one_notify_state);
131 0 : uint32_t num_changes;
132 0 : struct notify_change *changes;
133 0 : NTSTATUS status;
134 :
135 0 : status = cli_notify_recv(subreq, state, &num_changes, &changes);
136 0 : TALLOC_FREE(subreq);
137 0 : if (tevent_req_nterror(req, status)) {
138 0 : return;
139 : }
140 0 : subreq = cli_close_send(state, state->ev, state->cli, state->dnum, 0);
141 0 : if (tevent_req_nomem(subreq, req)) {
142 0 : return;
143 : }
144 0 : tevent_req_set_callback(subreq, wait_for_one_notify_closed, req);
145 : }
146 :
147 0 : static void wait_for_one_notify_closed(struct tevent_req *subreq)
148 : {
149 0 : struct tevent_req *req = tevent_req_callback_data(
150 : subreq, struct tevent_req);
151 0 : struct wait_for_one_notify_state *state = tevent_req_data(
152 : req, struct wait_for_one_notify_state);
153 0 : NTSTATUS status;
154 :
155 0 : status = cli_close_recv(subreq);
156 0 : TALLOC_FREE(subreq);
157 0 : if (tevent_req_nterror(req, status)) {
158 0 : return;
159 : }
160 0 : *state->num_notifies -= 1;
161 0 : tevent_req_done(req);
162 : }
163 :
164 0 : static NTSTATUS wait_for_one_notify_recv(struct tevent_req *req)
165 : {
166 0 : return tevent_req_simple_recv_ntstatus(req);
167 : }
168 :
169 : static void notify_bench2_done(struct tevent_req *req);
170 :
171 0 : bool run_notify_bench2(int dummy)
172 : {
173 0 : struct cli_state *cli;
174 0 : struct cli_state **clis;
175 0 : struct tevent_context *ev;
176 0 : unsigned num_notifies = 0;
177 0 : NTSTATUS status;
178 0 : int i;
179 :
180 0 : if (!torture_open_connection(&cli, 0)) {
181 0 : return false;
182 : }
183 :
184 0 : printf("starting notify bench 2 test\n");
185 :
186 0 : cli_rmdir(cli, "\\notify.dir\\subdir");
187 0 : cli_rmdir(cli, "\\notify.dir");
188 :
189 0 : status = cli_mkdir(cli, "\\notify.dir");
190 0 : if (!NT_STATUS_IS_OK(status)) {
191 0 : printf("mkdir failed : %s\n", nt_errstr(status));
192 0 : return false;
193 : }
194 :
195 0 : clis = talloc_array(talloc_tos(), struct cli_state *, torture_nprocs);
196 0 : if (clis == NULL) {
197 0 : printf("talloc failed\n");
198 0 : return false;
199 : }
200 :
201 0 : ev = samba_tevent_context_init(talloc_tos());
202 0 : if (ev == NULL) {
203 0 : printf("tevent_context_create failed\n");
204 0 : return false;
205 : }
206 :
207 0 : for (i=0; i<torture_nprocs; i++) {
208 0 : int j;
209 0 : if (!torture_open_connection(&clis[i], i)) {
210 0 : return false;
211 : }
212 :
213 0 : for (j=0; j<torture_numops; j++) {
214 0 : struct tevent_req *req;
215 0 : req = wait_for_one_notify_send(
216 0 : talloc_tos(), ev, clis[i], "\\notify.dir",
217 : FILE_NOTIFY_CHANGE_ALL, true,
218 : &num_notifies);
219 0 : if (req == NULL) {
220 0 : printf("wait_for_one_notify_send failed\n");
221 0 : return false;
222 : }
223 0 : tevent_req_set_callback(req, notify_bench2_done, NULL);
224 : }
225 : }
226 :
227 0 : while (num_notifies < (unsigned)(torture_nprocs * torture_numops)) {
228 0 : int ret;
229 0 : ret = tevent_loop_once(ev);
230 0 : if (ret != 0) {
231 0 : printf("tevent_loop_once failed: %s\n",
232 0 : strerror(errno));
233 0 : return false;
234 : }
235 : }
236 :
237 0 : cli_mkdir(cli, "\\notify.dir\\subdir");
238 :
239 0 : while (num_notifies > 0) {
240 0 : int ret;
241 0 : ret = tevent_loop_once(ev);
242 0 : if (ret != 0) {
243 0 : printf("tevent_loop_once failed: %s\n",
244 0 : strerror(errno));
245 0 : return false;
246 : }
247 : }
248 :
249 0 : return true;
250 : }
251 :
252 0 : static void notify_bench2_done(struct tevent_req *req)
253 : {
254 0 : NTSTATUS status;
255 :
256 0 : status = wait_for_one_notify_recv(req);
257 0 : TALLOC_FREE(req);
258 0 : if (!NT_STATUS_IS_OK(status)) {
259 0 : printf("wait_for_one_notify returned %s\n",
260 : nt_errstr(status));
261 : }
262 0 : }
263 :
264 : /*
265 : * This test creates a subdirectory. It then waits on a barrier before the
266 : * notify is sent. Then it creates the notify. It then waits for another
267 : * barrier, so that all of the notifies have gone through. It then creates
268 : * another subdirectory, which will trigger notifications to be sent. When the
269 : * notifies have been received, it waits once more before everything is
270 : * cleaned up.
271 : */
272 :
273 : struct notify_bench3_state {
274 : struct tevent_context *ev;
275 : struct cli_state *cli;
276 : const char *dir;
277 : uint16_t dnum;
278 : const char *subdir_path;
279 : uint16_t subdir_dnum;
280 : int wait_timeout;
281 : struct tevent_barrier *small;
282 : struct tevent_barrier *large;
283 : };
284 :
285 : static void notify_bench3_mkdir1_done(struct tevent_req *subreq);
286 : static void notify_bench3_before_notify(struct tevent_req *subreq);
287 : static void notify_bench3_chkpath_done(struct tevent_req *subreq);
288 : static void notify_bench3_before_mkdir2(struct tevent_req *subreq);
289 : static void notify_bench3_notify_done(struct tevent_req *subreq);
290 : static void notify_bench3_notifies_done(struct tevent_req *subreq);
291 : static void notify_bench3_mksubdir_done(struct tevent_req *subreq);
292 : static void notify_bench3_before_close_subdir(struct tevent_req *subreq);
293 : static void notify_bench3_close_subdir_done(struct tevent_req *subreq);
294 : static void notify_bench3_deleted_subdir(struct tevent_req *subreq);
295 : static void notify_bench3_deleted_subdirs(struct tevent_req *subreq);
296 : static void notify_bench3_del_on_close_set(struct tevent_req *subreq);
297 : static void notify_bench3_closed(struct tevent_req *subreq);
298 :
299 0 : static struct tevent_req *notify_bench3_send(
300 : TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
301 : const char *dir, const char *subdir_path,
302 : struct tevent_barrier *small, struct tevent_barrier *large)
303 : {
304 0 : struct tevent_req *req, *subreq;
305 0 : struct notify_bench3_state *state;
306 :
307 0 : req = tevent_req_create(mem_ctx, &state, struct notify_bench3_state);
308 0 : if (req == NULL) {
309 0 : return NULL;
310 : }
311 0 : state->ev = ev;
312 0 : state->cli = cli;
313 0 : state->dir = dir;
314 0 : state->subdir_path = subdir_path;
315 0 : state->small = small;
316 0 : state->large = large;
317 :
318 0 : subreq = cli_ntcreate_send(
319 0 : state, state->ev, state->cli, state->dir, 0,
320 : MAXIMUM_ALLOWED_ACCESS, 0,
321 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
322 : FILE_OPEN_IF, FILE_DIRECTORY_FILE,
323 : SMB2_IMPERSONATION_IMPERSONATION, 0);
324 0 : if (tevent_req_nomem(subreq, req)) {
325 0 : return tevent_req_post(req, ev);
326 : }
327 0 : tevent_req_set_callback(subreq, notify_bench3_mkdir1_done, req);
328 0 : return req;
329 : }
330 :
331 0 : static void notify_bench3_mkdir1_done(struct tevent_req *subreq)
332 : {
333 0 : struct tevent_req *req = tevent_req_callback_data(
334 : subreq, struct tevent_req);
335 0 : struct notify_bench3_state *state = tevent_req_data(
336 : req, struct notify_bench3_state);
337 0 : NTSTATUS status;
338 :
339 0 : status = cli_ntcreate_recv(subreq, &state->dnum, NULL);
340 0 : TALLOC_FREE(subreq);
341 0 : if (tevent_req_nterror(req, status)) {
342 0 : return;
343 : }
344 0 : subreq = tevent_barrier_wait_send(state, state->ev, state->small);
345 0 : if (tevent_req_nomem(subreq, req)) {
346 0 : return;
347 : }
348 0 : tevent_req_set_callback(subreq, notify_bench3_before_notify, req);
349 : }
350 :
351 0 : static void notify_bench3_before_notify(struct tevent_req *subreq)
352 : {
353 0 : struct tevent_req *req = tevent_req_callback_data(
354 : subreq, struct tevent_req);
355 0 : struct notify_bench3_state *state = tevent_req_data(
356 : req, struct notify_bench3_state);
357 0 : int ret;
358 :
359 0 : ret = tevent_barrier_wait_recv(subreq);
360 0 : TALLOC_FREE(subreq);
361 0 : if (ret != 0) {
362 0 : tevent_req_nterror(req, map_nt_error_from_unix(ret));
363 0 : return;
364 : }
365 0 : subreq = cli_notify_send(state, state->ev, state->cli, state->dnum,
366 : 0xffff, FILE_NOTIFY_CHANGE_ALL, true);
367 0 : if (tevent_req_nomem(subreq, req)) {
368 0 : return;
369 : }
370 0 : tevent_req_set_callback(subreq, notify_bench3_notify_done, req);
371 :
372 : /*
373 : * To make sure the notify received at the server, we do another no-op
374 : * that is replied to.
375 : */
376 0 : subreq = cli_chkpath_send(state, state->ev, state->cli, "\\");
377 0 : if (tevent_req_nomem(subreq, req)) {
378 0 : return;
379 : }
380 0 : tevent_req_set_callback(subreq, notify_bench3_chkpath_done, req);
381 : }
382 :
383 0 : static void notify_bench3_notify_done(struct tevent_req *subreq)
384 : {
385 0 : struct tevent_req *req = tevent_req_callback_data(
386 : subreq, struct tevent_req);
387 0 : struct notify_bench3_state *state = tevent_req_data(
388 : req, struct notify_bench3_state);
389 0 : uint32_t num_changes;
390 0 : struct notify_change *changes;
391 0 : NTSTATUS status;
392 :
393 0 : status = cli_notify_recv(subreq, state, &num_changes, &changes);
394 0 : TALLOC_FREE(subreq);
395 0 : if (tevent_req_nterror(req, status)) {
396 0 : return;
397 : }
398 0 : subreq = tevent_barrier_wait_send(state, state->ev, state->large);
399 0 : if (tevent_req_nomem(subreq, req)) {
400 0 : return;
401 : }
402 0 : tevent_req_set_callback(subreq, notify_bench3_notifies_done, req);
403 : }
404 :
405 0 : static void notify_bench3_notifies_done(struct tevent_req *subreq)
406 : {
407 0 : struct tevent_req *req = tevent_req_callback_data(
408 : subreq, struct tevent_req);
409 0 : int ret;
410 :
411 0 : ret = tevent_barrier_wait_recv(subreq);
412 0 : TALLOC_FREE(subreq);
413 0 : if (ret != 0) {
414 0 : tevent_req_nterror(req, map_nt_error_from_unix(ret));
415 0 : return;
416 : }
417 : }
418 :
419 0 : static void notify_bench3_chkpath_done(struct tevent_req *subreq)
420 : {
421 0 : struct tevent_req *req = tevent_req_callback_data(
422 : subreq, struct tevent_req);
423 0 : struct notify_bench3_state *state = tevent_req_data(
424 : req, struct notify_bench3_state);
425 0 : NTSTATUS status;
426 :
427 0 : status = cli_chkpath_recv(subreq);
428 0 : TALLOC_FREE(subreq);
429 0 : if (tevent_req_nterror(req, status)) {
430 0 : return;
431 : }
432 0 : if (state->subdir_path == NULL) {
433 0 : return;
434 : }
435 0 : subreq = tevent_barrier_wait_send(state, state->ev, state->small);
436 0 : if (tevent_req_nomem(subreq, req)) {
437 0 : return;
438 : }
439 0 : tevent_req_set_callback(subreq, notify_bench3_before_mkdir2, req);
440 : }
441 :
442 0 : static void notify_bench3_before_mkdir2(struct tevent_req *subreq)
443 : {
444 0 : struct tevent_req *req = tevent_req_callback_data(
445 : subreq, struct tevent_req);
446 0 : struct notify_bench3_state *state = tevent_req_data(
447 : req, struct notify_bench3_state);
448 0 : int ret;
449 :
450 0 : ret = tevent_barrier_wait_recv(subreq);
451 0 : TALLOC_FREE(subreq);
452 0 : if (ret != 0) {
453 0 : tevent_req_nterror(req, map_nt_error_from_unix(ret));
454 0 : return;
455 : }
456 0 : subreq = cli_ntcreate_send(
457 : state, state->ev, state->cli, state->subdir_path, 0,
458 : MAXIMUM_ALLOWED_ACCESS, 0,
459 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
460 : FILE_CREATE,
461 : FILE_DIRECTORY_FILE,
462 : SMB2_IMPERSONATION_IMPERSONATION, 0);
463 0 : if (tevent_req_nomem(subreq, req)) {
464 0 : return;
465 : }
466 0 : tevent_req_set_callback(subreq, notify_bench3_mksubdir_done, req);
467 : }
468 :
469 0 : static void notify_bench3_mksubdir_done(struct tevent_req *subreq)
470 : {
471 0 : struct tevent_req *req = tevent_req_callback_data(
472 : subreq, struct tevent_req);
473 0 : struct notify_bench3_state *state = tevent_req_data(
474 : req, struct notify_bench3_state);
475 0 : NTSTATUS status;
476 :
477 0 : status = cli_ntcreate_recv(subreq, &state->subdir_dnum, NULL);
478 0 : TALLOC_FREE(subreq);
479 0 : if (tevent_req_nterror(req, status)) {
480 0 : return;
481 : }
482 0 : subreq = tevent_barrier_wait_send(state, state->ev, state->large);
483 0 : if (tevent_req_nomem(subreq, req)) {
484 0 : return;
485 : }
486 0 : tevent_req_set_callback(subreq, notify_bench3_before_close_subdir,
487 : req);
488 : }
489 :
490 0 : static void notify_bench3_before_close_subdir(struct tevent_req *subreq)
491 : {
492 0 : struct tevent_req *req = tevent_req_callback_data(
493 : subreq, struct tevent_req);
494 0 : struct notify_bench3_state *state = tevent_req_data(
495 : req, struct notify_bench3_state);
496 0 : int ret;
497 :
498 0 : ret = tevent_barrier_wait_recv(subreq);
499 0 : TALLOC_FREE(subreq);
500 0 : if (ret != 0) {
501 0 : tevent_req_nterror(req, map_nt_error_from_unix(ret));
502 0 : return;
503 : }
504 0 : subreq = cli_close_send(state,
505 : state->ev,
506 : state->cli,
507 0 : state->subdir_dnum,
508 : 0);
509 0 : if (tevent_req_nomem(subreq, req)) {
510 0 : return;
511 : }
512 0 : tevent_req_set_callback(subreq, notify_bench3_close_subdir_done, req);
513 : }
514 :
515 0 : static void notify_bench3_close_subdir_done(struct tevent_req *subreq)
516 : {
517 0 : struct tevent_req *req = tevent_req_callback_data(
518 : subreq, struct tevent_req);
519 0 : struct notify_bench3_state *state = tevent_req_data(
520 : req, struct notify_bench3_state);
521 0 : NTSTATUS status;
522 :
523 0 : status = cli_close_recv(subreq);
524 0 : TALLOC_FREE(subreq);
525 0 : if (tevent_req_nterror(req, status)) {
526 0 : return;
527 : }
528 0 : subreq = cli_rmdir_send(state, state->ev, state->cli,
529 : state->subdir_path);
530 0 : if (tevent_req_nomem(subreq, req)) {
531 0 : return;
532 : }
533 0 : tevent_req_set_callback(subreq, notify_bench3_deleted_subdir, req);
534 : }
535 :
536 0 : static void notify_bench3_deleted_subdir(struct tevent_req *subreq)
537 : {
538 0 : struct tevent_req *req = tevent_req_callback_data(
539 : subreq, struct tevent_req);
540 0 : struct notify_bench3_state *state = tevent_req_data(
541 : req, struct notify_bench3_state);
542 0 : NTSTATUS status;
543 :
544 0 : status = cli_rmdir_recv(subreq);
545 0 : TALLOC_FREE(subreq);
546 0 : if (tevent_req_nterror(req, status)) {
547 0 : return;
548 : }
549 0 : subreq = tevent_barrier_wait_send(state, state->ev, state->small);
550 0 : if (tevent_req_nomem(subreq, req)) {
551 0 : return;
552 : }
553 0 : tevent_req_set_callback(subreq, notify_bench3_deleted_subdirs, req);
554 : }
555 :
556 0 : static void notify_bench3_deleted_subdirs(struct tevent_req *subreq)
557 : {
558 0 : struct tevent_req *req = tevent_req_callback_data(
559 : subreq, struct tevent_req);
560 0 : struct notify_bench3_state *state = tevent_req_data(
561 : req, struct notify_bench3_state);
562 0 : int ret;
563 :
564 0 : ret = tevent_barrier_wait_recv(subreq);
565 0 : TALLOC_FREE(subreq);
566 0 : if (ret != 0) {
567 0 : tevent_req_nterror(req, map_nt_error_from_unix(ret));
568 0 : return;
569 : }
570 0 : subreq = cli_nt_delete_on_close_send(state, state->ev, state->cli,
571 0 : state->dnum, true);
572 0 : if (tevent_req_nomem(subreq, req)) {
573 0 : return;
574 : }
575 0 : tevent_req_set_callback(subreq, notify_bench3_del_on_close_set, req);
576 : }
577 :
578 0 : static void notify_bench3_del_on_close_set(struct tevent_req *subreq)
579 : {
580 0 : struct tevent_req *req = tevent_req_callback_data(
581 : subreq, struct tevent_req);
582 0 : struct notify_bench3_state *state = tevent_req_data(
583 : req, struct notify_bench3_state);
584 0 : NTSTATUS status;
585 :
586 0 : status = cli_nt_delete_on_close_recv(subreq);
587 0 : TALLOC_FREE(subreq);
588 0 : if (tevent_req_nterror(req, status)) {
589 0 : return;
590 : }
591 :
592 0 : subreq = cli_close_send(state, state->ev, state->cli, state->dnum, 0);
593 0 : if (tevent_req_nomem(subreq, req)) {
594 0 : return;
595 : }
596 0 : tevent_req_set_callback(subreq, notify_bench3_closed, req);
597 : }
598 :
599 0 : static void notify_bench3_closed(struct tevent_req *subreq)
600 : {
601 0 : struct tevent_req *req = tevent_req_callback_data(
602 : subreq, struct tevent_req);
603 0 : NTSTATUS status;
604 :
605 0 : status = cli_close_recv(subreq);
606 0 : TALLOC_FREE(subreq);
607 0 : if (tevent_req_nterror(req, status)) {
608 0 : return;
609 : }
610 0 : tevent_req_done(req);
611 : }
612 :
613 0 : static NTSTATUS notify_bench3_recv(struct tevent_req *req)
614 : {
615 0 : return tevent_req_simple_recv_ntstatus(req);
616 : }
617 :
618 0 : static void notify_bench3_done(struct tevent_req *req)
619 : {
620 0 : unsigned *num_done = (unsigned *)tevent_req_callback_data_void(req);
621 0 : NTSTATUS status;
622 :
623 0 : status = notify_bench3_recv(req);
624 0 : TALLOC_FREE(req);
625 0 : if (!NT_STATUS_IS_OK(status)) {
626 0 : d_printf("notify_bench3 returned %s\n", nt_errstr(status));
627 : }
628 0 : *num_done += 1;
629 0 : }
630 :
631 0 : static void notify_bench3_barrier_cb(void *private_data)
632 : {
633 0 : struct timeval *ts = (struct timeval *)private_data;
634 0 : struct timeval now;
635 :
636 0 : GetTimeOfDay(&now);
637 0 : printf("barrier triggered: %f\n", timeval_elapsed2(ts, &now));
638 0 : GetTimeOfDay(ts);
639 0 : }
640 :
641 0 : bool run_notify_bench3(int dummy)
642 : {
643 0 : struct cli_state **clis;
644 0 : struct tevent_context *ev;
645 0 : struct tevent_barrier *small;
646 0 : struct tevent_barrier *large;
647 0 : int i;
648 0 : unsigned num_done = 0;
649 0 : struct timeval ts, now;
650 :
651 0 : clis = talloc_array(talloc_tos(), struct cli_state *, torture_nprocs);
652 0 : if (clis == NULL) {
653 0 : printf("talloc failed\n");
654 0 : return false;
655 : }
656 :
657 0 : GetTimeOfDay(&ts);
658 :
659 0 : small = tevent_barrier_init(
660 0 : talloc_tos(), torture_nprocs * torture_numops,
661 : notify_bench3_barrier_cb, &ts);
662 0 : if (small == NULL) {
663 0 : return false;
664 : }
665 :
666 0 : large = tevent_barrier_init(
667 0 : talloc_tos(), 2 * torture_nprocs * torture_numops,
668 : notify_bench3_barrier_cb, &ts);
669 0 : if (large == NULL) {
670 0 : return false;
671 : }
672 :
673 0 : ev = samba_tevent_context_init(talloc_tos());
674 0 : if (ev == NULL) {
675 0 : printf("tevent_context_create failed\n");
676 0 : return false;
677 : }
678 :
679 0 : for (i=0; i<torture_nprocs; i++) {
680 0 : if (!torture_open_connection(&clis[i], i)) {
681 0 : return false;
682 : }
683 : }
684 :
685 0 : for (i=0; i<torture_nprocs; i++) {
686 : int j;
687 0 : for (j=0; j<torture_numops; j++) {
688 0 : int idx = i * torture_numops + j;
689 0 : struct tevent_req *req;
690 0 : char *dirname, *subdirname;
691 :
692 0 : dirname = talloc_asprintf(
693 0 : talloc_tos(), "\\dir%.8d", idx);
694 0 : if (dirname == NULL) {
695 0 : return false;
696 : }
697 0 : subdirname = talloc_asprintf(
698 0 : talloc_tos(), "\\dir%.8d\\subdir",
699 0 : (idx + torture_numops + 1) %
700 0 : (torture_nprocs * torture_numops));
701 0 : if (subdirname == NULL) {
702 0 : return false;
703 : }
704 :
705 0 : req = notify_bench3_send(
706 0 : talloc_tos(), ev, clis[i], dirname,
707 : subdirname, small, large);
708 0 : if (req == NULL) {
709 0 : return false;
710 : }
711 0 : tevent_req_set_callback(req, notify_bench3_done,
712 : &num_done);
713 : }
714 : }
715 :
716 0 : while (num_done < (unsigned)(torture_nprocs * torture_numops)) {
717 0 : int ret;
718 0 : ret = tevent_loop_once(ev);
719 0 : if (ret != 0) {
720 0 : printf("tevent_loop_once failed: %s\n",
721 0 : strerror(errno));
722 0 : return false;
723 : }
724 : }
725 :
726 0 : GetTimeOfDay(&now);
727 0 : printf("turndow: %f\n", timeval_elapsed2(&ts, &now));
728 0 : TALLOC_FREE(small);
729 0 : TALLOC_FREE(large);
730 0 : return true;
731 : }
|