The branch, master has been updated
       via  cdd232c torture: Extend the raw.oplock.level_ii_1 test
       via  76e7d8f smbd: Remove MSG_SMB_ASYNC_LEVEL2_BREAK
       via  d9a1d54 smbd: Use MSG_SMB_BREAK_REQUEST for async l2 breaks
       via  6c3b41c smbd: Fix breaking level2 on OVERWRITE create_disposition
       via  64e7340 torture: Add a test showing we have to break L2 at open time
       via  20669d4 smbd: Fix raw.batch.exclusive[59]
       via  ccc808e smbd: Remove unused "mid" from delay_for_oplock
       via  4c8bdf7 smbd: Don't send op_mid in a BREAK message
       via  de95b9d smbd: Simplify send_break_message
       via  cb27921 smbd: Remove unused "oplock_request" arg from 
send_break_message
       via  9d3e3a7 torture: Add oplock break to l2/none tests
       via  96faaf6 torture: Check break level in raw.oplock.exclusive5
       via  9890a6a smbd: validate oplock types even for internal and stat opens
       via  7b51e9f torture: Add reproducer for bug 10216
       via  f892bdb smbd: Fix bug 10216
      from  4e06c61 ldb: Fix CID 240798 Uninitialized pointer read

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit cdd232cc06a5652ad9f6800d5baf017632099cd8
Author: Volker Lendecke <v...@samba.org>
Date:   Wed Oct 16 21:34:15 2013 +0200

    torture: Extend the raw.oplock.level_ii_1 test
    
    smbd broke to none twice. Make sure this won't happen again :-)
    
    This used to happen before the MSG_SMB_BREAK_RESPONSE merge. In
    process_oplock_break_message we did not call remove_oplock, which would
    have prevented this.
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <me...@samba.org>
    Autobuild-Date(master): Wed Oct 23 14:06:13 CEST 2013 on sn-devel-104

commit 76e7d8f97fd14f3ef796eb49f441e6eb56e9a238
Author: Volker Lendecke <v...@samba.org>
Date:   Tue Oct 22 11:37:45 2013 +0000

    smbd: Remove MSG_SMB_ASYNC_LEVEL2_BREAK
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit d9a1d54b7916462da5ee7b1ec8208f629d12f2df
Author: Volker Lendecke <v...@samba.org>
Date:   Tue Oct 22 11:33:42 2013 +0000

    smbd: Use MSG_SMB_BREAK_REQUEST for async l2 breaks
    
    Now that we transmit the level we want to break to via the msg.op_type
    we can unify MSG_SMB_BREAK_REQUEST and MSG_SMB_ASYNC_LEVEL2_BREAK and
    thus simplify the code a bit.
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 6c3b41cfc24fca4a1786604102d1163d2fc0a20c
Author: Volker Lendecke <v...@samba.org>
Date:   Wed Oct 16 21:21:56 2013 +0200

    smbd: Fix breaking level2 on OVERWRITE create_disposition
    
    This is shown by the new raw.oplock.level_ii_1 test
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 64e734019f5d0691017a592e78e6cac793875e4a
Author: Volker Lendecke <v...@samba.org>
Date:   Tue Oct 15 15:22:06 2013 +0000

    torture: Add a test showing we have to break L2 at open time
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 20669d4a75386eef4fdcea07fb99812c4e09de13
Author: Volker Lendecke <v...@samba.org>
Date:   Thu Sep 26 16:15:31 2013 -0700

    smbd: Fix raw.batch.exclusive[59]
    
    The level we have to break to depend on the breakers create_disposition:
    If we overwrite, we have to break to none.
    
    This patch overloads the "op_type" field in the break message we send
    across to the smbd holding the oplock with the oplock level we want to
    break to. Because it depends on the create_disposition in the breaking
    open, only the breaker can make that decision. We might want to use
    a different mechanism for this in the future, but for now using the
    op_type field seems acceptable to me.
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit ccc808e0d72be5933ae2449ee8ee56262e631b72
Author: Volker Lendecke <v...@samba.org>
Date:   Thu Sep 26 15:49:54 2013 -0700

    smbd: Remove unused "mid" from delay_for_oplock
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 4c8bdf7878e7b1b85be356680c5c9a12be6d7244
Author: Volker Lendecke <v...@samba.org>
Date:   Thu Sep 26 15:48:42 2013 -0700

    smbd: Don't send op_mid in a BREAK message
    
    The callee doesn't use this anyway
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit de95b9d11d7044a0d592f75f24ad0e67e595e97c
Author: Volker Lendecke <v...@samba.org>
Date:   Thu Sep 26 15:35:05 2013 -0700

    smbd: Simplify send_break_message
    
    We don't need an fsp here
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit cb279212744345a5a77e60401cb19d151b978ea8
Author: Volker Lendecke <v...@samba.org>
Date:   Thu Sep 26 15:31:12 2013 -0700

    smbd: Remove unused "oplock_request" arg from send_break_message
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 9d3e3a736cad0d1f22f71f108231bae1bd2ece19
Author: Volker Lendecke <v...@samba.org>
Date:   Wed Sep 25 16:02:20 2013 -0700

    torture: Add oplock break to l2/none tests
    
    The level we have to break to depends on the create disposition of the
    second opener. If it's overwriting, break to none. If it's not, break
    to level2.
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 96faaf6c1ed818fc0aadcb478e9f8b20568d7547
Author: Volker Lendecke <v...@samba.org>
Date:   Wed Sep 25 15:33:42 2013 -0700

    torture: Check break level in raw.oplock.exclusive5
    
    This is what Windows does in this case, we don't survive that. We break
    to LEVEL2 here. Fixes and more precise test to follow.
    
    We don't survive this anymore. Re-enable later.
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 9890a6a36df98bae501845764a9579c9c75c5188
Author: Volker Lendecke <v...@samba.org>
Date:   Tue Oct 15 12:41:11 2013 +0000

    smbd: validate oplock types even for internal and stat opens
    
    There's no reason why we should not do this. This has turned into a pure
    internal consistency check that should apply fine every time.
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 7b51e9f8d3db208027cab44ca8c17129a9e86929
Author: Volker Lendecke <v...@samba.org>
Date:   Fri Oct 18 13:11:38 2013 +0000

    torture: Add reproducer for bug 10216
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit f892bdb2047c86e53f875e8f2c58858d2dacc363
Author: Volker Lendecke <v...@samba.org>
Date:   Fri Oct 18 15:12:35 2013 +0000

    smbd: Fix bug 10216
    
    While refactoring find_oplock_types to validate_oplock_types I forgot
    that stat opens will end up in locking.tdb. So even with a batch oplock
    around we can have more than one entry. This means the consistency check
    in validate_oplock_types was wrong and too strict.
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

-----------------------------------------------------------------------

Summary of changes:
 selftest/knownfail               |    4 +
 source3/librpc/idl/messaging.idl |    2 +-
 source3/smbd/open.c              |  103 +++++++++++------
 source3/smbd/oplock.c            |  106 +++---------------
 source4/torture/raw/oplock.c     |  228 ++++++++++++++++++++++++++++++++++++++
 source4/torture/smb2/oplock.c    |   83 ++++++++++++++
 6 files changed, 400 insertions(+), 126 deletions(-)


Changeset truncated at 500 lines:

diff --git a/selftest/knownfail b/selftest/knownfail
index 1653cea..ab6d45f 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -140,6 +140,9 @@
 ^samba4.raw.sfileinfo.*.end-of-file\(.*\)$ # bug 6962
 ^samba4.raw.oplock.*.batch22 # bug 6963
 ^samba4.raw.oplock.*.doc1
+^samba4.raw.oplock.*.exclusive5
+^samba4.raw.oplock.*.exclusive9
+^samba4.raw.oplock.*.level_ii_1
 ^samba4.raw.lock.*.zerobyteread # bug 6974
 ^samba4.smb2.lock.*.zerobyteread # bug 6974
 ^samba4.raw.streams.*.delete
@@ -159,6 +162,7 @@
 ^samba4.smb2.oplock.exclusive2\(.*\)$ # samba 4 oplocks are a mess
 ^samba4.smb2.oplock.exclusive5\(.*\)$ # samba 4 oplocks are a mess
 ^samba4.smb2.oplock.exclusive6\(.*\)$ # samba 4 oplocks are a mess
+^samba4.smb2.oplock.exclusive9\(.*\)$
 ^samba4.smb2.oplock.brl3\(.*\)$ # samba 4 oplocks are a mess
 ^samba4.smb2.oplock.levelii500\(.*\)$ # samba 4 oplocks are a mess
 ^samba4.smb2.oplock.brl1\(.*\)$ # samba 4 oplocks are a mess
diff --git a/source3/librpc/idl/messaging.idl b/source3/librpc/idl/messaging.idl
index 9d16570..39532f0 100644
--- a/source3/librpc/idl/messaging.idl
+++ b/source3/librpc/idl/messaging.idl
@@ -67,7 +67,7 @@ interface messaging
                MSG_SMB_UNLOCK                  = 0x0305,
                MSG_SMB_BREAK_REQUEST           = 0x0306,
                /* MSG_SMB_BREAK_RESPONSE       = 0x0307,  Obsoleted */
-               MSG_SMB_ASYNC_LEVEL2_BREAK      = 0x0308,
+               /* MSG_SMB_ASYNC_LEVEL2_BREAK   = 0x0308,  Obsoleted */
                /* MSG_SMB_OPEN_RETRY           = 0x0309,  Obsoleted */
                MSG_SMB_KERNEL_BREAK            = 0x030A,
                MSG_SMB_FILE_RENAME             = 0x030B,
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index fa52fcc..c33a4cf 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1167,22 +1167,23 @@ static NTSTATUS open_mode_check(connection_struct *conn,
  * our client.
  */
 
-static NTSTATUS send_break_message(files_struct *fsp,
-                                       struct share_mode_entry *exclusive,
-                                       uint64_t mid,
-                                       int oplock_request)
+static NTSTATUS send_break_message(struct messaging_context *msg_ctx,
+                                  const struct share_mode_entry *exclusive,
+                                  uint16_t break_to)
 {
        NTSTATUS status;
        char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
 
        DEBUG(10, ("Sending break request to PID %s\n",
                   procid_str_static(&exclusive->pid)));
-       exclusive->op_mid = mid;
 
        /* Create the message. */
        share_mode_entry_to_message(msg, exclusive);
 
-       status = messaging_send_buf(fsp->conn->sconn->msg_ctx, exclusive->pid,
+       /* Overload entry->op_type */
+       SSVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET, break_to);
+
+       status = messaging_send_buf(msg_ctx, exclusive->pid,
                                    MSG_SMB_BREAK_REQUEST,
                                    (uint8 *)msg, sizeof(msg));
        if (!NT_STATUS_IS_OK(status)) {
@@ -1194,33 +1195,19 @@ static NTSTATUS send_break_message(files_struct *fsp,
 }
 
 /*
- * Return share_mode_entry pointers for :
- * 1). Batch oplock entry.
- * 2). Batch or exclusive oplock entry (may be identical to #1).
- * bool have_level2_oplock
- * bool have_no_oplock.
  * Do internal consistency checks on the share mode for a file.
  */
 
-static bool validate_oplock_types(files_struct *fsp,
-                                 int oplock_request,
-                                 struct share_mode_lock *lck)
+static bool validate_oplock_types(struct share_mode_lock *lck)
 {
        struct share_mode_data *d = lck->data;
        bool batch = false;
        bool ex_or_batch = false;
        bool level2 = false;
        bool no_oplock = false;
+       uint32_t num_non_stat_opens = 0;
        uint32_t i;
 
-       /* Ignore stat or internal opens, as is done in
-               delay_for_batch_oplocks() and
-               delay_for_exclusive_oplocks().
-        */
-       if ((oplock_request & INTERNAL_OPEN_ONLY) || 
is_stat_open(fsp->access_mask)) {
-               return true;
-       }
-
        for (i=0; i<d->num_share_modes; i++) {
                struct share_mode_entry *e = &d->share_modes[i];
 
@@ -1235,6 +1222,8 @@ static bool validate_oplock_types(files_struct *fsp,
                        continue;
                }
 
+               num_non_stat_opens += 1;
+
                if (BATCH_OPLOCK_TYPE(e->op_type)) {
                        /* batch - can only be one. */
                        if (share_mode_stale_pid(d, i)) {
@@ -1294,7 +1283,7 @@ static bool validate_oplock_types(files_struct *fsp,
 
        remove_stale_share_mode_entries(d);
 
-       if ((batch || ex_or_batch) && (d->num_share_modes != 1)) {
+       if ((batch || ex_or_batch) && (num_non_stat_opens != 1)) {
                DEBUG(1, ("got batch (%d) or ex (%d) non-exclusively (%d)\n",
                          (int)batch, (int)ex_or_batch,
                          (int)d->num_share_modes));
@@ -1305,24 +1294,46 @@ static bool validate_oplock_types(files_struct *fsp,
 }
 
 static bool delay_for_oplock(files_struct *fsp,
-                            uint64_t mid,
                             int oplock_request,
                             struct share_mode_lock *lck,
-                            bool have_sharing_violation)
+                            bool have_sharing_violation,
+                            uint32_t create_disposition)
 {
        struct share_mode_data *d = lck->data;
        struct share_mode_entry *entry;
+       uint32_t num_non_stat_opens = 0;
+       uint32_t i;
+       uint16_t break_to;
 
        if ((oplock_request & INTERNAL_OPEN_ONLY) || 
is_stat_open(fsp->access_mask)) {
                return false;
        }
-       if (lck->data->num_share_modes != 1) {
+       for (i=0; i<d->num_share_modes; i++) {
+               struct share_mode_entry *e = &d->share_modes[i];
+               if (e->op_type == NO_OPLOCK && is_stat_open(e->access_mask)) {
+                       continue;
+               }
+               num_non_stat_opens += 1;
+
+               /*
+                * We found the a non-stat open, which in the exclusive/batch
+                * case will be inspected further down.
+                */
+               entry = e;
+       }
+       if (num_non_stat_opens == 0) {
+               /*
+                * Nothing to wait for around
+                */
+               return false;
+       }
+       if (num_non_stat_opens != 1) {
                /*
-                * More than one. There can't be any exclusive or batch left.
+                * More than one open around. There can't be any exclusive or
+                * batch left, this is all level2.
                 */
                return false;
        }
-       entry = &d->share_modes[0];
 
        if (server_id_is_disconnected(&entry->pid)) {
                /*
@@ -1337,11 +1348,21 @@ static bool delay_for_oplock(files_struct *fsp,
                return false;
        }
 
+       switch (create_disposition) {
+       case FILE_SUPERSEDE:
+       case FILE_OVERWRITE_IF:
+               break_to = NO_OPLOCK;
+               break;
+       default:
+               break_to = LEVEL_II_OPLOCK;
+               break;
+       }
+
        if (have_sharing_violation && (entry->op_type & BATCH_OPLOCK)) {
                if (share_mode_stale_pid(d, 0)) {
                        return false;
                }
-               send_break_message(fsp, entry, mid, oplock_request);
+               send_break_message(fsp->conn->sconn->msg_ctx, entry, break_to);
                return true;
        }
        if (have_sharing_violation) {
@@ -1351,6 +1372,17 @@ static bool delay_for_oplock(files_struct *fsp,
                 */
                return false;
        }
+       if (LEVEL_II_OPLOCK_TYPE(entry->op_type) &&
+           (break_to == NO_OPLOCK)) {
+               if (share_mode_stale_pid(d, 0)) {
+                       return false;
+               }
+               DEBUG(10, ("Asynchronously breaking level2 oplock for "
+                          "create_disposition=%u\n",
+                          (unsigned)create_disposition));
+               send_break_message(fsp->conn->sconn->msg_ctx, entry, break_to);
+               return false;
+       }
        if (!EXCLUSIVE_OPLOCK_TYPE(entry->op_type)) {
                /*
                 * No break for NO_OPLOCK or LEVEL2_OPLOCK oplocks
@@ -1361,7 +1393,7 @@ static bool delay_for_oplock(files_struct *fsp,
                return false;
        }
 
-       send_break_message(fsp, entry, mid, oplock_request);
+       send_break_message(fsp->conn->sconn->msg_ctx, entry, break_to);
        return true;
 }
 
@@ -2334,11 +2366,11 @@ static NTSTATUS open_file_ntcreate(connection_struct 
*conn,
                        return NT_STATUS_SHARING_VIOLATION;
                }
 
-               if (!validate_oplock_types(fsp, 0, lck)) {
+               if (!validate_oplock_types(lck)) {
                        smb_panic("validate_oplock_types failed");
                }
 
-               if (delay_for_oplock(fsp, req->mid, 0, lck, false)) {
+               if (delay_for_oplock(fsp, 0, lck, false, create_disposition)) {
                        schedule_defer_open(lck, request_time, req);
                        TALLOC_FREE(lck);
                        DEBUG(10, ("Sent oplock break request to kernel "
@@ -2422,7 +2454,7 @@ static NTSTATUS open_file_ntcreate(connection_struct 
*conn,
        }
 
        /* Get the types we need to examine. */
-       if (!validate_oplock_types(fsp, oplock_request, lck)) {
+       if (!validate_oplock_types(lck)) {
                smb_panic("validate_oplock_types failed");
        }
 
@@ -2449,8 +2481,9 @@ static NTSTATUS open_file_ntcreate(connection_struct 
*conn,
 
        if ((req != NULL) &&
            delay_for_oplock(
-                   fsp, req->mid, oplock_request, lck,
-                   NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION))) {
+                   fsp, oplock_request, lck,
+                   NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION),
+                   create_disposition)) {
                schedule_defer_open(lck, request_time, req);
                TALLOC_FREE(lck);
                fd_close(fsp);
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index e2880c5..d30aa4b 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -410,88 +410,6 @@ static void send_break_message_smb1(files_struct *fsp, int 
level)
 }
 
 /*******************************************************************
- This handles the case of a write triggering a break to none
- message on a level2 oplock.
- When we get this message we may be in any of two states :
- NO_OPLOCK, LEVEL_II. We only send a message to
- the client for LEVEL2.
-*******************************************************************/
-
-static void process_oplock_async_level2_break_message(struct messaging_context 
*msg_ctx,
-                                                     void *private_data,
-                                                     uint32_t msg_type,
-                                                     struct server_id src,
-                                                     DATA_BLOB *data)
-{
-       struct share_mode_entry msg;
-       files_struct *fsp;
-       struct smbd_server_connection *sconn =
-               talloc_get_type_abort(private_data,
-               struct smbd_server_connection);
-       struct server_id self = messaging_server_id(sconn->msg_ctx);
-
-       if (data->data == NULL) {
-               DEBUG(0, ("Got NULL buffer\n"));
-               return;
-       }
-
-       if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
-               DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
-               return;
-       }
-
-       /* De-linearize incoming message. */
-       message_to_share_mode_entry(&msg, (char *)data->data);
-
-       DEBUG(10, ("Got oplock async level 2 break message from pid %s: "
-                  "%s/%llu\n", server_id_str(talloc_tos(), &src),
-                  file_id_string_tos(&msg.id),
-                  (unsigned long long)msg.share_file_id));
-
-       fsp = initial_break_processing(sconn, msg.id, msg.share_file_id);
-
-       if (fsp == NULL) {
-               /* We hit a race here. Break messages are sent, and before we
-                * get to process this message, we have closed the file. 
-                * No need to reply as this is an async message. */
-               DEBUG(3, ("process_oplock_async_level2_break_message: Did not 
find fsp, ignoring\n"));
-               return;
-       }
-
-
-       if (fsp->oplock_type == NO_OPLOCK) {
-               /* We already got a "break to none" message and we've handled
-                * it.  just ignore. */
-               DEBUG(3, ("process_oplock_async_level2_break_message: already "
-                         "broken to none, ignoring.\n"));
-               return;
-       }
-
-       /* Ensure we're really at level2 state. */
-       SMB_ASSERT(fsp->oplock_type == LEVEL_II_OPLOCK);
-
-       DEBUG(10,("process_oplock_async_level2_break_message: sending break "
-                 "to none message for %s, file %s\n", fsp_fnum_dbg(fsp),
-                 fsp_str_dbg(fsp)));
-
-       /* Need to wait before sending a break
-          message if we sent ourselves this message. */
-       if (serverid_equal(&self, &src)) {
-               wait_before_sending_break();
-       }
-
-       /* Now send a break to none message to our client. */
-       if (sconn->using_smb2) {
-               send_break_message_smb2(fsp, OPLOCKLEVEL_NONE);
-       } else {
-               send_break_message_smb1(fsp, OPLOCKLEVEL_NONE);
-       }
-
-       /* Async level2 request, don't send a reply, just remove the oplock. */
-       remove_oplock(fsp);
-}
-
-/*******************************************************************
  This handles the generic oplock break message from another smbd.
 *******************************************************************/
 
@@ -510,6 +428,7 @@ static void process_oplock_break_message(struct 
messaging_context *msg_ctx,
                struct smbd_server_connection);
        struct server_id self = messaging_server_id(sconn->msg_ctx);
        struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
+       uint16_t break_to;
 
        if (data->data == NULL) {
                DEBUG(0, ("Got NULL buffer\n"));
@@ -523,9 +442,10 @@ static void process_oplock_break_message(struct 
messaging_context *msg_ctx,
 
        /* De-linearize incoming message. */
        message_to_share_mode_entry(&msg, (char *)data->data);
+       break_to = msg.op_type;
 
-       DEBUG(10, ("Got oplock break message from pid %s: %s/%llu\n",
-                  server_id_str(talloc_tos(), &src),
+       DEBUG(10, ("Got oplock break to %u message from pid %s: %s/%llu\n",
+                  (unsigned)break_to, server_id_str(talloc_tos(), &src),
                   file_id_string_tos(&msg.id),
                   (unsigned long long)msg.share_file_id));
 
@@ -545,8 +465,7 @@ static void process_oplock_break_message(struct 
messaging_context *msg_ctx,
                return;
        }
 
-       if (EXCLUSIVE_OPLOCK_TYPE(msg.op_type) &&
-           !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
+       if (break_to == fsp->oplock_type) {
                DEBUG(3, ("Already downgraded oplock on %s: %s\n",
                          file_id_string_tos(&fsp->file_id),
                          fsp_str_dbg(fsp)));
@@ -556,6 +475,7 @@ static void process_oplock_break_message(struct 
messaging_context *msg_ctx,
        use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) && koplocks;
 
        if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) &&
+           (break_to != NO_OPLOCK) &&
            !(use_kernel && !(koplocks->flags & KOPLOCKS_LEVEL2_SUPPORTED)) &&
            lp_level2_oplocks(SNUM(fsp->conn))) {
                break_to_level2 = True;
@@ -575,8 +495,14 @@ static void process_oplock_break_message(struct 
messaging_context *msg_ctx,
                        OPLOCKLEVEL_II : OPLOCKLEVEL_NONE);
        }
 
+       if ((fsp->oplock_type == LEVEL_II_OPLOCK) && (break_to == NO_OPLOCK)) {
+               /*
+                * This is an async break without a reply and thus no timeout
+                */
+               remove_oplock(fsp);
+               return;
+       }
        fsp->sent_oplock_break = break_to_level2 ? 
LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
-
        add_oplock_timeout_handler(fsp);
 }
 
@@ -765,9 +691,11 @@ static void do_break_to_none(struct tevent_context *ctx,
                }
 
                share_mode_entry_to_message(msg, share_entry);
+               /* Overload entry->op_type */
+               SSVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET, NO_OPLOCK);
 
                messaging_send_buf(state->sconn->msg_ctx, share_entry->pid,
-                                  MSG_SMB_ASYNC_LEVEL2_BREAK,
+                                  MSG_SMB_BREAK_REQUEST,
                                   (uint8 *)msg, sizeof(msg));
        }
 
@@ -860,8 +788,6 @@ bool init_oplocks(struct smbd_server_connection *sconn)
 
        messaging_register(sconn->msg_ctx, sconn, MSG_SMB_BREAK_REQUEST,
                           process_oplock_break_message);
-       messaging_register(sconn->msg_ctx, sconn, MSG_SMB_ASYNC_LEVEL2_BREAK,
-                          process_oplock_async_level2_break_message);
        messaging_register(sconn->msg_ctx, sconn, MSG_SMB_KERNEL_BREAK,
                           process_kernel_oplock_break);
        return true;
diff --git a/source4/torture/raw/oplock.c b/source4/torture/raw/oplock.c
index 34e270d..a4f6a05 100644
--- a/source4/torture/raw/oplock.c
+++ b/source4/torture/raw/oplock.c
@@ -556,6 +556,18 @@ static bool test_raw_oplock_exclusive4(struct 
torture_context *tctx, struct smbc
        CHECK_VAL(break_info.count, 0);
        CHECK_VAL(break_info.failures, 0);
 
+       /*
+        * Open another non-stat open. This reproduces bug 10216. Make sure it
+        * won't happen again...
+        */
+       io.ntcreatex.in.flags = 0;
+       io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
+       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);
+
        smbcli_close(cli1->tree, fnum);
        smbcli_close(cli2->tree, fnum2);
 
@@ -626,6 +638,7 @@ static bool test_raw_oplock_exclusive5(struct 
torture_context *tctx, struct smbc
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
        torture_wait_for_oplock_break(tctx);
        CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
        CHECK_VAL(break_info.failures, 0);
 
        smbcli_close(cli1->tree, fnum);
@@ -958,6 +971,217 @@ done:
        return ret;
 }
 
+static bool test_raw_oplock_exclusive9(struct torture_context *tctx,
+                                      struct smbcli_state *cli1,
+                                      struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_exclusive9.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0;
+       int i;
+
+       struct {
+               uint32_t create_disposition;
+               uint32_t break_level;
+       } levels[] = {
+               { NTCREATEX_DISP_SUPERSEDE, OPLOCK_BREAK_TO_NONE },
+               { NTCREATEX_DISP_OPEN, OPLOCK_BREAK_TO_LEVEL_II },
+               { NTCREATEX_DISP_OVERWRITE_IF, OPLOCK_BREAK_TO_NONE },
+               { NTCREATEX_DISP_OPEN_IF, OPLOCK_BREAK_TO_LEVEL_II },
+       };
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       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,
+                             cli1->tree);
+
+       /*
+         base ntcreatex parms


-- 
Samba Shared Repository

Reply via email to