]> git.samba.org - samba.git/commitdiff
s4/torture: Allow receiving of oplock break requests in any order
authorSteven Danneman <steven.danneman@isilon.com>
Fri, 25 Sep 2009 23:44:51 +0000 (16:44 -0700)
committerSteven Danneman <steven.danneman@isilon.com>
Wed, 30 Sep 2009 02:04:36 +0000 (19:04 -0700)
Previously, the oplock torture tests, being single threaded, required
the server to return oplock break requests, and other SMB packets
in a specific order for us to verify "correctness".

Of course, in several cases the protocol allows the break packets,
especially breaks to levelII to come back in any order.  With tevent
we're now able to wait for oplock breaks in the middle of a torture
test.

I've added a helper to do this, and modified all oplock tests to allow
returning of oplock breaks in any order.

source4/torture/raw/oplock.c

index 581b8cdc00515547a7c5cbe782acdf5bbfccc5d6..6070a0a6ee7a8dc91ca24c41dc0ddd3e4fbc113a 100644 (file)
@@ -204,6 +204,60 @@ static bool open_connection_no_level2_oplocks(struct torture_context *tctx,
        return true;
 }
 
+/*
+   Timer handler function notifies the registering function that time is up
+*/
+static void timeout_cb(struct tevent_context *ev,
+                      struct tevent_timer *te,
+                      struct timeval current_time,
+                      void *private_data)
+{
+       bool *timesup = (bool *)private_data;
+       *timesup = true;
+       return;
+}
+
+/*
+   Wait a short period of time to receive a single oplock break request
+*/
+static void torture_wait_for_oplock_break(struct torture_context *tctx)
+{
+       TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+       struct tevent_timer *te = NULL;
+       struct timeval ne;
+       bool timesup = false;
+       int old_count = break_info.count;
+
+       /* Wait .1 seconds for an oplock break */
+       ne = tevent_timeval_current_ofs(0, 100000);
+
+       if ((te = event_add_timed(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup))
+           == NULL)
+       {
+               torture_comment(tctx, "Failed to wait for an oplock break. "
+                                     "test results may not be accurate.");
+               goto done;
+       }
+
+       while (!timesup && break_info.count < old_count + 1) {
+               if (event_loop_once(tctx->ev) != 0) {
+                       torture_comment(tctx, "Failed to wait for an oplock "
+                                             "break. test results may not be "
+                                             "accurate.");
+                       goto done;
+               }
+       }
+
+done:
+       /* We don't know if the timed event fired and was freed, we received
+        * our oplock break, or some other event triggered the loop.  Thus,
+        * we create a tmp_ctx to be able to safely free/remove the timed
+        * event in all 3 cases. */
+       talloc_free(tmp_ctx);
+
+       return;
+}
+
 static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 {
        const char *fname = BASEDIR "\\test_exclusive1.dat";
@@ -249,6 +303,7 @@ static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbc
        torture_comment(tctx, "a 2nd open should not cause a break\n");
        status = smb_raw_open(cli2->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
 
@@ -257,6 +312,7 @@ static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbc
        unl.unlink.in.attrib = 0;
        status = smb_raw_unlink(cli2->tree, &unl);
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
 
@@ -318,6 +374,7 @@ static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbc
        status = smb_raw_open(cli2->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum2 = io.ntcreatex.out.file.fnum;
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum);
@@ -331,6 +388,7 @@ static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbc
        unl.unlink.in.attrib = 0;
        status = smb_raw_unlink(cli2->tree, &unl);
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
 
@@ -342,10 +400,11 @@ static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbc
        unl.unlink.in.attrib = 0;
        status = smb_raw_unlink(cli2->tree, &unl);
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
 
-       torture_comment(tctx, "close 1st handle\n");
+       torture_comment(tctx, "close 2nd handle\n");
        smbcli_close(cli2->tree, fnum2);
 
        torture_comment(tctx, "unlink it\n");
@@ -353,6 +412,7 @@ static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbc
        unl.unlink.in.attrib = 0;
        status = smb_raw_unlink(cli2->tree, &unl);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
 
@@ -415,6 +475,7 @@ static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbc
        status = smb_raw_setpathinfo(cli2->tree, &sfi);
 
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
@@ -479,6 +540,7 @@ static bool test_raw_oplock_exclusive4(struct torture_context *tctx, struct smbc
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum2 = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
 
@@ -550,6 +612,7 @@ static bool test_raw_oplock_exclusive5(struct torture_context *tctx, struct smbc
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum2 = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.failures, 0);
 
@@ -620,6 +683,7 @@ static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbc
        status = smb_raw_rename(cli2->tree, &rn);
 
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
 
@@ -685,6 +749,7 @@ static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_s
        status = smb_raw_unlink(cli2->tree, &unl);
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
@@ -695,13 +760,14 @@ static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_s
        status = smb_raw_unlink(cli2->tree, &unl);
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        torture_comment(tctx, "writing should generate a self break to none\n");
        smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
-       msleep(100);
-       smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
 
+       torture_wait_for_oplock_break(tctx);
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
@@ -767,6 +833,7 @@ static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_s
        status = smb_raw_unlink(cli2->tree, &unl);
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
@@ -777,13 +844,13 @@ static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_s
        status = smb_raw_unlink(cli2->tree, &unl);
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        torture_comment(tctx, "writing should not generate a break\n");
        smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
-       msleep(100);
-       smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        smbcli_close(cli1->tree, fnum);
@@ -845,6 +912,7 @@ static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_s
        status = smb_raw_unlink(cli2->tree, &unl);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum);
        CHECK_VAL(break_info.level, 1);
@@ -911,6 +979,7 @@ static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_s
        rd.read.in.remaining = 0;
        status = smb_raw_read(cli1->tree, &rd);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
 
@@ -973,6 +1042,7 @@ static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_s
        status = smb_raw_open(cli2->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum);
        CHECK_VAL(break_info.level, 1);
@@ -1004,6 +1074,7 @@ static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_s
        smbcli_unlink(cli1->tree, fname);
 
        smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
 
        /*
          base ntcreatex parms
@@ -1022,8 +1093,6 @@ static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_s
 
        torture_comment(tctx, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
-       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
 
        io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
        io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
@@ -1042,6 +1111,7 @@ static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_s
        fnum2 = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
 
+       //torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum);
        CHECK_VAL(break_info.level, 1);
@@ -1050,8 +1120,10 @@ static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_s
 
        torture_comment(tctx, "write should trigger a break to none on both\n");
        smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
-       msleep(100);
-       smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
+
+       /* We expect two breaks */
+       torture_wait_for_oplock_break(tctx);
+       torture_wait_for_oplock_break(tctx);
 
        CHECK_VAL(break_info.count, 2);
        CHECK_VAL(break_info.level, 0);
@@ -1060,7 +1132,6 @@ static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_s
        smbcli_close(cli1->tree, fnum);
        smbcli_close(cli2->tree, fnum2);
 
-
 done:
        smb_raw_exit(cli1->session);
        smb_raw_exit(cli2->session);
@@ -1124,11 +1195,12 @@ static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_s
        fnum = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum2);
        CHECK_VAL(break_info.level, 1);
        CHECK_VAL(break_info.failures, 0);
-       
+
        smbcli_close(cli2->tree, fnum);
 
 done:
@@ -1193,6 +1265,7 @@ static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_s
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum2 = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
 
@@ -1264,6 +1337,7 @@ static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_s
        status = smb_raw_open(cli2->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum2 = io.ntcreatex.out.file.fnum;
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum);
        CHECK_VAL(break_info.failures, 0);
@@ -1283,6 +1357,7 @@ static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_s
        status = smb_raw_open(cli2->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum2 = io.ntcreatex.out.file.fnum;
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
@@ -1292,11 +1367,9 @@ static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_s
        torture_comment(tctx, "write should trigger a break to none on both\n");
        smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
 
-       /* Now the oplock break request comes in. But right now we can't
-        * answer it. Do another write */
-
-       msleep(100);
-       smbcli_write(cli2->tree, fnum2, 0, &c, 1, 1);
+       /* We expect two breaks */
+       torture_wait_for_oplock_break(tctx);
+       torture_wait_for_oplock_break(tctx);
 
        CHECK_VAL(break_info.count, 2);
        CHECK_VAL(break_info.level, 0);
@@ -1354,6 +1427,7 @@ static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_
        status = smb_raw_open(cli1->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum = io.ntcreatex.out.file.fnum;
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
@@ -1371,6 +1445,7 @@ static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_
        status = smb_raw_open(cli2->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum2 = io.ntcreatex.out.file.fnum;
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
@@ -1388,22 +1463,7 @@ static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_
                CHECK_STATUS(tctx, status, NT_STATUS_OK);
        }
 
-       /* Now the oplock break request comes in. But right now we can't
-        * answer it. Do another write */
-
-       msleep(100);
-       
-       {
-               union smb_write wr;
-               wr.write.level = RAW_WRITE_WRITE;
-               wr.write.in.file.fnum = fnum;
-               wr.write.in.count = 1;
-               wr.write.in.offset = 0;
-               wr.write.in.remaining = 0;
-               wr.write.in.data = (const uint8_t *)"x";
-               status = smb_raw_write(cli1->tree, &wr);
-               CHECK_STATUS(tctx, status, NT_STATUS_OK);
-       }
+       torture_wait_for_oplock_break(tctx);
 
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum2);
@@ -1457,10 +1517,9 @@ static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_
        torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
 
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
 
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
-               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
                NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
        io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
        io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
@@ -1470,18 +1529,20 @@ static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_
        status = smb_raw_open(cli1->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum = io.ntcreatex.out.file.fnum;
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
-       
+
        ZERO_STRUCT(sfi);
        sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
        sfi.generic.in.file.path = fname;
        sfi.end_of_file_info.in.size = 100;
 
         status = smb_raw_setpathinfo(cli2->tree, &sfi);
-
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(break_info.level, 0);
@@ -1535,7 +1596,7 @@ static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_
        smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
 
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
-               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
                NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
        io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
        io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
@@ -1545,18 +1606,20 @@ static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_
        status = smb_raw_open(cli1->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum = io.ntcreatex.out.file.fnum;
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
-       
+
        ZERO_STRUCT(sfi);
        sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
        sfi.generic.in.file.path = fname;
        sfi.allocation_info.in.alloc_size = 65536 * 8;
 
         status = smb_raw_setpathinfo(cli2->tree, &sfi);
-
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(break_info.level, 0);
@@ -1605,8 +1668,6 @@ static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_
 
        torture_comment(tctx, "BATCH13: open with batch oplock\n");
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
-
 
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
                NTCREATEX_FLAGS_REQUEST_OPLOCK | 
@@ -1634,6 +1695,7 @@ static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_
        status = smb_raw_open(cli2->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum2 = io.ntcreatex.out.file.fnum;
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.failures, 0);
@@ -1682,7 +1744,6 @@ static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_
 
        torture_comment(tctx, "BATCH14: open with batch oplock\n");
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
 
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
                NTCREATEX_FLAGS_REQUEST_OPLOCK | 
@@ -1711,6 +1772,8 @@ static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum2 = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.failures, 0);
 
@@ -1760,7 +1823,6 @@ static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_
        torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
 
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
 
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
                NTCREATEX_FLAGS_REQUEST_OPLOCK |
@@ -1774,6 +1836,8 @@ static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_
        status = smb_raw_open(cli1->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum = io.ntcreatex.out.file.fnum;
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
@@ -1783,8 +1847,9 @@ static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_
        qfi.generic.in.file.path = fname;
 
        status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
-
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        smbcli_close(cli1->tree, fnum);
@@ -1831,8 +1896,6 @@ static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_
 
        torture_comment(tctx, "BATCH16: open with batch oplock\n");
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
-
 
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
                NTCREATEX_FLAGS_REQUEST_OPLOCK |
@@ -1861,6 +1924,8 @@ static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum2 = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.failures, 0);
 
@@ -1930,8 +1995,9 @@ static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_
 
        torture_comment(tctx, "trying rename while first file open\n");
        status = smb_raw_rename(cli2->tree, &rn);
-
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
@@ -2001,8 +2067,9 @@ static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_
        rn.ntrename.in.new_name = fname2;
        torture_comment(tctx, "trying rename while first file open\n");
        status = smb_raw_rename(cli2->tree, &rn);
-
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
@@ -2073,8 +2140,9 @@ static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_
        sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
 
         status = smb_raw_setpathinfo(cli2->tree, &sfi);
-
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        ZERO_STRUCT(qfi);
@@ -2095,6 +2163,8 @@ static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_
 
        status = smb_raw_setfileinfo(cli1->tree, &sfi);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        ZERO_STRUCT(qfi);
@@ -2177,6 +2247,8 @@ bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1,
         status = smb_raw_setpathinfo(cli2->tree, &sfi);
 
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        ZERO_STRUCT(qfi);
@@ -2197,6 +2269,8 @@ bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1,
 
        status = smb_raw_setfileinfo(cli1->tree, &sfi);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        ZERO_STRUCT(qfi);
@@ -2274,8 +2348,9 @@ bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1)
        rn.nttrans.in.new_name  = fname2+strlen(BASEDIR)+1;
 
         status = smb_raw_rename(cli1->tree, &rn);
-
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        /* w2k3 does nothing, it doesn't rename the file */
@@ -2400,8 +2475,9 @@ static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_
        sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
 
        status = smb_raw_setpathinfo(cli2->tree, &sfi);
-
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        ZERO_STRUCT(qfi);
@@ -2425,6 +2501,8 @@ static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        fnum2 = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
@@ -2439,6 +2517,8 @@ static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_
 
        status = smb_raw_setfileinfo(cli1->tree, &sfi);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.failures, 0);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
@@ -2526,6 +2606,7 @@ static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_
        status = smb_raw_echo(cli1->transport, &e);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        smbcli_close(cli1->tree, fnum);
@@ -2598,6 +2679,7 @@ static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_
        smbcli_oplock_handler(cli1->transport, oplock_handler_timeout, cli1->tree);
        status = smb_raw_open(cli1->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       torture_wait_for_oplock_break(tctx);
        te = (int)timeval_elapsed(&tv);
        CHECK_RANGE(te, timeout - 1, timeout + 15);
 
@@ -2614,6 +2696,7 @@ static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_
        status = smb_raw_open(cli1->tree, tctx, &io);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+       torture_wait_for_oplock_break(tctx);
        te = (int)timeval_elapsed(&tv);
        /* it should come in without delay */
        CHECK_RANGE(te+1, 0, timeout);
@@ -2647,11 +2730,13 @@ static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_
        /* cleanup */
        smbcli_unlink(cli1->tree, fname);
 
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
-
        ret = open_connection_no_level2_oplocks(tctx, &cli3);
        CHECK_VAL(ret, true);
 
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
+       smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
+
        /*
          base ntcreatex parms
        */
@@ -2669,9 +2754,6 @@ static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_
 
        torture_comment(tctx, "BATCH23: a open and ask for a batch oplock\n");
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
-       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
-       smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
 
        io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
        io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
@@ -2691,6 +2773,7 @@ static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_
        fnum3 = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
@@ -2704,6 +2787,7 @@ static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_
        fnum2 = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        smbcli_close(cli1->tree, fnum);
@@ -2734,11 +2818,13 @@ static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_
        /* cleanup */
        smbcli_unlink(cli1->tree, fname);
 
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
-
        ret = open_connection_no_level2_oplocks(tctx, &cli3);
        CHECK_VAL(ret, true);
 
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
+       smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
+
        /*
          base ntcreatex parms
        */
@@ -2756,9 +2842,6 @@ static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_
 
        torture_comment(tctx, "BATCH24: a open without level support and ask for a batch oplock\n");
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
-       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
-       smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
 
        io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
        io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
@@ -2778,6 +2861,7 @@ static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_
        fnum2 = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.fnum, fnum3);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
@@ -2850,8 +2934,9 @@ static bool test_raw_oplock_batch25(struct torture_context *tctx,
        sfi.setattr.in.write_time       = 0;
 
         status = smb_raw_setpathinfo(cli2->tree, &sfi);
-
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
 
        smbcli_close(cli1->tree, fnum);
@@ -2920,8 +3005,8 @@ static bool test_raw_oplock_stream1(struct torture_context *tctx,
        }
        smbcli_unlink(cli1->tree, fname_base);
 
-       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
        smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
 
        /* Setup generic open parameters. */
        io.generic.level = RAW_OPEN_NTCREATEX;
@@ -3006,6 +3091,7 @@ static bool test_raw_oplock_stream1(struct torture_context *tctx,
            BATCH_OPLOCK_RETURN);
        smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
 
@@ -3021,6 +3107,7 @@ static bool test_raw_oplock_stream1(struct torture_context *tctx,
            LEVEL_II_OPLOCK_RETURN);
        smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
        CHECK_VAL(break_info.failures, 0);
@@ -3162,8 +3249,6 @@ static bool test_raw_oplock_brl1(struct torture_context *tctx,
 
        torture_comment(tctx, "a 2nd open should give a break\n");
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
-                             cli1->tree);
 
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
        status = smb_raw_open(cli2->tree, tctx, &io);
@@ -3175,19 +3260,13 @@ static bool test_raw_oplock_brl1(struct torture_context *tctx,
        CHECK_VAL(break_info.fnum, fnum);
 
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
-                             cli1->tree);
 
-       torture_comment(tctx, "attempt BRL test\n");
+       torture_comment(tctx, "a self BRL acquisition should break to none\n");
 
        status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
 
-       /*
-        * Even though level 2 oplock breaks are asynchronous, with self
-        * contention we'll always break the oplock before the contending
-        * operation's response is sent.
-        */
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
        CHECK_VAL(break_info.fnum, fnum);
@@ -3198,6 +3277,7 @@ static bool test_raw_oplock_brl1(struct torture_context *tctx,
        status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
        CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.level, 0);
        CHECK_VAL(break_info.fnum, 0);
@@ -3280,10 +3360,8 @@ static bool test_raw_oplock_brl2(struct torture_context *tctx, struct smbcli_sta
                goto done;
        }
 
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
-                             cli1->tree);
-
-       torture_comment(tctx, "attempt BRL test\n");
+       torture_comment(tctx, "a self BRL acquisition should not break to "
+                       "none\n");
 
        status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
@@ -3294,6 +3372,7 @@ static bool test_raw_oplock_brl2(struct torture_context *tctx, struct smbcli_sta
        /* With one file handle open a BRL should not contend our oplock.
         * Thus, no oplock break will be received and the entire break_info
         * struct will be 0 */
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.fnum, 0);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.level, 0);
@@ -3375,8 +3454,6 @@ static bool test_raw_oplock_brl3(struct torture_context *tctx,
 
        torture_comment(tctx, "a 2nd open should give a break\n");
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
-                             cli1->tree);
 
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
        status = smb_raw_open(cli1->tree, tctx, &io);
@@ -3388,19 +3465,13 @@ static bool test_raw_oplock_brl3(struct torture_context *tctx,
        CHECK_VAL(break_info.fnum, fnum);
 
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
-                             cli1->tree);
 
-       torture_comment(tctx, "attempt BRL test\n");
+       torture_comment(tctx, "a self BRL acquisition should break to none\n");
 
        status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
        CHECK_STATUS(tctx, status, NT_STATUS_OK);
 
-       /*
-        * Even though level 2 oplock breaks are asynchrounous, with self
-        * contention we'll always break the oplock before the contending
-        * operation's response is sent.
-        */
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 1);
        CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
        CHECK_VAL(break_info.fnum, fnum);
@@ -3411,6 +3482,7 @@ static bool test_raw_oplock_brl3(struct torture_context *tctx,
        status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
        CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
 
+       torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.level, 0);
        CHECK_VAL(break_info.fnum, 0);
@@ -3423,7 +3495,6 @@ done:
        smb_raw_exit(cli1->session);
        smbcli_deltree(cli1->tree, BASEDIR);
        return ret;
-
 }
 
 /*