smbd: Simplify open_file_ntcreate
authorVolker Lendecke <vl@samba.org>
Thu, 26 Sep 2013 22:20:36 +0000 (15:20 -0700)
committerMichael Adam <obnox@samba.org>
Wed, 16 Oct 2013 00:51:53 +0000 (02:51 +0200)
Only one call to delay_for_oplocks left. Metze showed me the new logic:
BATCH is broken if we have a sharing violation. Exclusive is broken
otherwise. That's it.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
Autobuild-User(master): Michael Adam <obnox@samba.org>
Autobuild-Date(master): Wed Oct 16 02:51:53 CEST 2013 on sn-devel-104

source3/smbd/open.c

index aaa42b34a865a8af8c67a591a8d19151ece09aae..fa52fccc088595ef56beb612db3d0452a2acd9df 100644 (file)
@@ -1308,21 +1308,21 @@ static bool delay_for_oplock(files_struct *fsp,
                             uint64_t mid,
                             int oplock_request,
                             struct share_mode_lock *lck,
-                            int delay_for_type)
+                            bool have_sharing_violation)
 {
+       struct share_mode_data *d = lck->data;
        struct share_mode_entry *entry;
 
        if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) {
                return false;
        }
        if (lck->data->num_share_modes != 1) {
+               /*
+                * More than one. There can't be any exclusive or batch left.
+                */
                return false;
        }
-       entry = &lck->data->share_modes[0];
-
-       if (!(entry->op_type & delay_for_type)) {
-               return false;
-       }
+       entry = &d->share_modes[0];
 
        if (server_id_is_disconnected(&entry->pid)) {
                /*
@@ -1337,6 +1337,30 @@ static bool delay_for_oplock(files_struct *fsp,
                return false;
        }
 
+       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);
+               return true;
+       }
+       if (have_sharing_violation) {
+               /*
+                * Non-batch exclusive is not broken if we have a sharing
+                * violation
+                */
+               return false;
+       }
+       if (!EXCLUSIVE_OPLOCK_TYPE(entry->op_type)) {
+               /*
+                * No break for NO_OPLOCK or LEVEL2_OPLOCK oplocks
+                */
+               return false;
+       }
+       if (share_mode_stale_pid(d, 0)) {
+               return false;
+       }
+
        send_break_message(fsp, entry, mid, oplock_request);
        return true;
 }
@@ -2314,8 +2338,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                        smb_panic("validate_oplock_types failed");
                }
 
-               if (delay_for_oplock(fsp, req->mid, 0, lck,
-                                    BATCH_OPLOCK|EXCLUSIVE_OPLOCK)) {
+               if (delay_for_oplock(fsp, req->mid, 0, lck, false)) {
                        schedule_defer_open(lck, request_time, req);
                        TALLOC_FREE(lck);
                        DEBUG(10, ("Sent oplock break request to kernel "
@@ -2409,20 +2432,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                return NT_STATUS_DELETE_PENDING;
        }
 
-       /* First pass - send break only on batch oplocks. */
-       if ((req != NULL) &&
-           delay_for_oplock(fsp, req->mid, oplock_request, lck,
-                            BATCH_OPLOCK)) {
-               schedule_defer_open(lck, request_time, req);
-               TALLOC_FREE(lck);
-               fd_close(fsp);
-               return NT_STATUS_SHARING_VIOLATION;
-       }
-
        status = open_mode_check(conn, lck,
                                 access_mask, share_access);
 
-
        if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
            (lck->data->num_share_modes > 0)) {
                /*
@@ -2435,19 +2447,14 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                file_existed = true;
        }
 
-       if (NT_STATUS_IS_OK(status)) {
-               /* We might be going to allow this open. Check oplock
-                * status again. */
-               /* Second pass - send break for both batch or
-                * exclusive oplocks. */
-               if ((req != NULL) &&
-                   delay_for_oplock(fsp, req->mid, oplock_request, lck,
-                                    BATCH_OPLOCK|EXCLUSIVE_OPLOCK)) {
-                       schedule_defer_open(lck, request_time, req);
-                       TALLOC_FREE(lck);
-                       fd_close(fsp);
-                       return NT_STATUS_SHARING_VIOLATION;
-               }
+       if ((req != NULL) &&
+           delay_for_oplock(
+                   fsp, req->mid, oplock_request, lck,
+                   NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION))) {
+               schedule_defer_open(lck, request_time, req);
+               TALLOC_FREE(lck);
+               fd_close(fsp);
+               return NT_STATUS_SHARING_VIOLATION;
        }
 
        if (!NT_STATUS_IS_OK(status)) {