vfs3: Pass "lease" through SMB_VFS_CREATE_FILE
[metze/samba/wip.git] / source3 / smbd / open.c
index e33c4abcc1df51c90109343e272d5b655eab28b2..4157280b084f49dfed9ef65c5ec4fa629a823b67 100644 (file)
 #include "../libcli/security/security.h"
 #include "../librpc/gen_ndr/ndr_security.h"
 #include "../librpc/gen_ndr/open_files.h"
+#include "../librpc/gen_ndr/idmap.h"
+#include "../librpc/gen_ndr/ioctl.h"
+#include "passdb/lookup_sid.h"
 #include "auth.h"
 #include "serverid.h"
 #include "messages.h"
+#include "source3/lib/dbwrap/dbwrap_watch.h"
 
 extern const struct generic_mapping file_generic_mapping;
 
@@ -73,6 +77,7 @@ NTSTATUS smbd_check_access_rights(struct connection_struct *conn,
        struct security_descriptor *sd = NULL;
        uint32_t rejected_share_access;
        uint32_t rejected_mask = access_mask;
+       uint32_t do_not_check_mask = 0;
 
        rejected_share_access = access_mask & ~(conn->share_access);
 
@@ -115,7 +120,7 @@ NTSTATUS smbd_check_access_rights(struct connection_struct *conn,
        status = SMB_VFS_GET_NT_ACL(conn, smb_fname->base_name,
                        (SECINFO_OWNER |
                        SECINFO_GROUP |
-                       SECINFO_DACL),&sd);
+                        SECINFO_DACL), talloc_tos(), &sd);
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10, ("smbd_check_access_rights: Could not get acl "
@@ -131,13 +136,32 @@ NTSTATUS smbd_check_access_rights(struct connection_struct *conn,
        }
 
        /*
-        * Never test FILE_READ_ATTRIBUTES. se_file_access_check() also takes care of
+        * If we can access the path to this file, by
+        * default we have FILE_READ_ATTRIBUTES from the
+        * containing directory. See the section:
+        * "Algorithm to Check Access to an Existing File"
+        * in MS-FSA.pdf.
+        *
+        * se_file_access_check() also takes care of
         * owner WRITE_DAC and READ_CONTROL.
         */
+       do_not_check_mask = FILE_READ_ATTRIBUTES;
+
+       /*
+        * Samba 3.6 and earlier granted execute access even
+        * if the ACL did not contain execute rights.
+        * Samba 4.0 is more correct and checks it.
+        * The compatibilty mode allows to skip this check
+        * to smoothen upgrades.
+        */
+       if (lp_acl_allow_execute_always(SNUM(conn))) {
+               do_not_check_mask |= FILE_EXECUTE;
+       }
+
        status = se_file_access_check(sd,
                                get_current_nttok(conn),
                                use_privs,
-                               (access_mask & ~FILE_READ_ATTRIBUTES),
+                               (access_mask & ~do_not_check_mask),
                                &rejected_mask);
 
        DEBUG(10,("smbd_check_access_rights: file %s requesting "
@@ -237,6 +261,7 @@ static NTSTATUS check_parent_access(struct connection_struct *conn,
        status = SMB_VFS_GET_NT_ACL(conn,
                                parent_dir,
                                SECINFO_DACL,
+                                   talloc_tos(),
                                &parent_sd);
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -248,7 +273,13 @@ static NTSTATUS check_parent_access(struct connection_struct *conn,
        }
 
        /*
-        * Never test FILE_READ_ATTRIBUTES. se_file_access_check() also takes care of
+        * If we can access the path to this file, by
+        * default we have FILE_READ_ATTRIBUTES from the
+        * containing directory. See the section:
+        * "Algorithm to Check Access to an Existing File"
+        * in MS-FSA.pdf.
+        *
+        * se_file_access_check() also takes care of
         * owner WRITE_DAC and READ_CONTROL.
         */
        status = se_file_access_check(parent_sd,
@@ -271,6 +302,46 @@ static NTSTATUS check_parent_access(struct connection_struct *conn,
        return NT_STATUS_OK;
 }
 
+/****************************************************************************
+ Ensure when opening a base file for a stream open that we have permissions
+ to do so given the access mask on the base file.
+****************************************************************************/
+
+static NTSTATUS check_base_file_access(struct connection_struct *conn,
+                               struct smb_filename *smb_fname,
+                               uint32_t access_mask)
+{
+       NTSTATUS status;
+
+       status = smbd_calculate_access_mask(conn, smb_fname,
+                                       false,
+                                       access_mask,
+                                       &access_mask);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("smbd_calculate_access_mask "
+                       "on file %s returned %s\n",
+                       smb_fname_str_dbg(smb_fname),
+                       nt_errstr(status)));
+               return status;
+       }
+
+       if (access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) {
+               uint32_t dosattrs;
+               if (!CAN_WRITE(conn)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+               dosattrs = dos_mode(conn, smb_fname);
+               if (IS_DOS_READONLY(dosattrs)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       }
+
+       return smbd_check_access_rights(conn,
+                                       smb_fname,
+                                       false,
+                                       access_mask);
+}
+
 /****************************************************************************
  fd support routines - attempt to do a dos_open.
 ****************************************************************************/
@@ -289,7 +360,7 @@ NTSTATUS fd_open(struct connection_struct *conn,
         * client should be doing this.
         */
 
-       if (fsp->posix_open || !lp_symlinks(SNUM(conn))) {
+       if (fsp->posix_open || !lp_follow_symlinks(SNUM(conn))) {
                flags |= O_NOFOLLOW;
        }
 #endif
@@ -372,13 +443,12 @@ void change_file_owner_to_parent(connection_struct *conn,
                                        const char *inherit_from_dir,
                                        files_struct *fsp)
 {
-       struct smb_filename *smb_fname_parent = NULL;
-       NTSTATUS status;
+       struct smb_filename *smb_fname_parent;
        int ret;
 
-       status = create_synthetic_smb_fname(talloc_tos(), inherit_from_dir,
-                                           NULL, NULL, &smb_fname_parent);
-       if (!NT_STATUS_IS_OK(status)) {
+       smb_fname_parent = synthetic_smb_fname(talloc_tos(), inherit_from_dir,
+                                              NULL, NULL);
+       if (smb_fname_parent == NULL) {
                return;
        }
 
@@ -427,17 +497,17 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
                                       const char *fname,
                                       SMB_STRUCT_STAT *psbuf)
 {
-       struct smb_filename *smb_fname_parent = NULL;
+       struct smb_filename *smb_fname_parent;
        struct smb_filename *smb_fname_cwd = NULL;
        char *saved_dir = NULL;
        TALLOC_CTX *ctx = talloc_tos();
        NTSTATUS status = NT_STATUS_OK;
        int ret;
 
-       status = create_synthetic_smb_fname(ctx, inherit_from_dir, NULL, NULL,
-                                           &smb_fname_parent);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
+       smb_fname_parent = synthetic_smb_fname(ctx, inherit_from_dir,
+                                              NULL, NULL);
+       if (smb_fname_parent == NULL) {
+               return NT_STATUS_NO_MEMORY;
        }
 
        ret = SMB_VFS_STAT(conn, smb_fname_parent);
@@ -475,10 +545,10 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
                goto chdir;
        }
 
-       status = create_synthetic_smb_fname(ctx, ".", NULL, NULL,
-                                           &smb_fname_cwd);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
+       smb_fname_cwd = synthetic_smb_fname(ctx, ".", NULL, NULL);
+       if (smb_fname_cwd == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto chdir;
        }
 
        ret = SMB_VFS_STAT(conn, smb_fname_cwd);
@@ -678,7 +748,8 @@ static NTSTATUS open_file(files_struct *fsp,
                        DEBUG(3,("Permission denied opening %s\n",
                                 smb_fname_str_dbg(smb_fname)));
                        return NT_STATUS_ACCESS_DENIED;
-               } else if(flags & O_CREAT) {
+               }
+               if (flags & O_CREAT) {
                        /* We don't want to write - but we must make sure that
                           O_CREAT doesn't create the file if we have write
                           access into the directory.
@@ -769,8 +840,11 @@ static NTSTATUS open_file(files_struct *fsp,
                        }
                }
 
-               /* Actually do the open */
-               status = fd_open_atomic(conn, fsp, local_flags,
+               /*
+                * Actually do the open - if O_TRUNC is needed handle it
+                * below under the share mode lock.
+                */
+               status = fd_open_atomic(conn, fsp, local_flags & ~O_TRUNC,
                                unx_mode, p_file_created);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
@@ -800,7 +874,7 @@ static NTSTATUS open_file(files_struct *fsp,
                           in the stat struct in fsp->fsp_name. */
 
                        /* Inherit the ACL if required */
-                       if (lp_inherit_perms(SNUM(conn))) {
+                       if (lp_inherit_permissions(SNUM(conn))) {
                                inherit_access_posix_acl(conn, parent_dir,
                                                         smb_fname->base_name,
                                                         unx_mode);
@@ -1009,13 +1083,9 @@ static void validate_my_share_entries(struct smbd_server_connection *sconn,
                return;
        }
 
-       if (is_deferred_open_entry(share_entry) &&
-           !open_was_deferred(sconn, share_entry->op_mid)) {
-               char *str = talloc_asprintf(talloc_tos(),
-                       "Got a deferred entry without a request: "
-                       "PANIC: %s\n",
-                       share_mode_str(talloc_tos(), num, share_entry));
-               smb_panic(str);
+       if (share_entry->share_file_id == 0) {
+               /* INTERNAL_OPEN_ONLY */
+               return;
        }
 
        if (!is_valid_share_mode_entry(share_entry)) {
@@ -1031,17 +1101,6 @@ static void validate_my_share_entries(struct smbd_server_connection *sconn,
                          "share entry with an open file\n");
        }
 
-       if (is_deferred_open_entry(share_entry)) {
-               goto panic;
-       }
-
-       if ((share_entry->op_type == NO_OPLOCK) &&
-           (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK)) {
-               /* Someone has already written to it, but I haven't yet
-                * noticed */
-               return;
-       }
-
        if (((uint16)fsp->oplock_type) != share_entry->op_type) {
                goto panic;
        }
@@ -1075,19 +1134,36 @@ bool is_stat_open(uint32 access_mask)
                ((access_mask & ~stat_open_bits) == 0));
 }
 
+static bool has_delete_on_close(struct share_mode_lock *lck,
+                               uint32_t name_hash)
+{
+       struct share_mode_data *d = lck->data;
+       uint32_t i;
+
+       if (d->num_share_modes == 0) {
+               return false;
+       }
+       if (!is_delete_on_close_set(lck, name_hash)) {
+               return false;
+       }
+       for (i=0; i<d->num_share_modes; i++) {
+               if (!share_mode_stale_pid(d, i)) {
+                       return true;
+               }
+       }
+       return false;
+}
+
 /****************************************************************************
  Deal with share modes
- Invarient: Share mode must be locked on entry and exit.
+ Invariant: Share mode must be locked on entry and exit.
  Returns -1 on error, or number of share modes on success (may be zero).
 ****************************************************************************/
 
 static NTSTATUS open_mode_check(connection_struct *conn,
                                struct share_mode_lock *lck,
-                               uint32_t name_hash,
                                uint32 access_mask,
-                               uint32 share_access,
-                               uint32 create_options,
-                               bool *file_existed)
+                               uint32 share_access)
 {
        int i;
 
@@ -1095,25 +1171,6 @@ static NTSTATUS open_mode_check(connection_struct *conn,
                return NT_STATUS_OK;
        }
 
-       /* A delete on close prohibits everything */
-
-       if (is_delete_on_close_set(lck, name_hash)) {
-               /*
-                * Check the delete on close token
-                * is valid. It could have been left
-                * after a server crash.
-                */
-               for(i = 0; i < lck->data->num_share_modes; i++) {
-                       if (!share_mode_stale_pid(lck->data, i)) {
-
-                               *file_existed = true;
-
-                               return NT_STATUS_DELETE_PENDING;
-                       }
-               }
-               return NT_STATUS_OK;
-       }
-
        if (is_stat_open(access_mask)) {
                /* Stat open that doesn't trigger oplock breaks or share mode
                 * checks... ! JRA. */
@@ -1147,16 +1204,10 @@ static NTSTATUS open_mode_check(connection_struct *conn,
                                continue;
                        }
 
-                       *file_existed = true;
-
                        return NT_STATUS_SHARING_VIOLATION;
                }
        }
 
-       if (lck->data->num_share_modes != 0) {
-               *file_existed = true;
-       }
-
        return NT_STATUS_OK;
 }
 
@@ -1165,33 +1216,25 @@ 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);
 
-       /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We
-          don't want this set in the share mode struct pointed to by lck. */
-
-       if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) {
-               SSVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET,
-                       exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE);
-       }
+       /* Overload entry->op_type */
+       SSVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET, break_to);
 
-       status = messaging_send_buf(fsp->conn->sconn->msg_ctx, exclusive->pid,
+       status = messaging_send_buf(msg_ctx, exclusive->pid,
                                    MSG_SMB_BREAK_REQUEST,
-                                   (uint8 *)msg,
-                                   MSG_SMB_SHARE_MODE_ENTRY_SIZE);
+                                   (uint8 *)msg, sizeof(msg));
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(3, ("Could not send oplock break message: %s\n",
                          nt_errstr(status)));
@@ -1201,113 +1244,147 @@ 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 void find_oplock_types(files_struct *fsp,
-                               int oplock_request,
-                               const struct share_mode_lock *lck,
-                               struct share_mode_entry **pp_batch,
-                               struct share_mode_entry **pp_ex_or_batch,
-                               bool *got_level2,
-                               bool *got_no_oplock)
+static bool validate_oplock_types(struct share_mode_lock *lck)
 {
-       int i;
-
-       *pp_batch = NULL;
-       *pp_ex_or_batch = NULL;
-       *got_level2 = false;
-       *got_no_oplock = false;
-
-       /* 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;
-       }
-
-       for (i=0; i<lck->data->num_share_modes; i++) {
-               if (!is_valid_share_mode_entry(&lck->data->share_modes[i])) {
+       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;
+
+       for (i=0; i<d->num_share_modes; i++) {
+               struct share_mode_entry *e = &d->share_modes[i];
+
+               if (!is_valid_share_mode_entry(e)) {
                        continue;
                }
 
-               if (lck->data->share_modes[i].op_type == NO_OPLOCK &&
-                               is_stat_open(lck->data->share_modes[i].access_mask)) {
+               if (e->op_type == NO_OPLOCK && is_stat_open(e->access_mask)) {
                        /* We ignore stat opens in the table - they
                           always have NO_OPLOCK and never get or
                           cause breaks. JRA. */
                        continue;
                }
 
-               if (BATCH_OPLOCK_TYPE(lck->data->share_modes[i].op_type)) {
+               num_non_stat_opens += 1;
+
+               if (BATCH_OPLOCK_TYPE(e->op_type)) {
                        /* batch - can only be one. */
-                       if (share_mode_stale_pid(lck->data, i)) {
+                       if (share_mode_stale_pid(d, i)) {
                                DEBUG(10, ("Found stale batch oplock\n"));
                                continue;
                        }
-                       if (*pp_ex_or_batch || *pp_batch || *got_level2 || *got_no_oplock) {
-                               smb_panic("Bad batch oplock entry.");
+                       if (ex_or_batch || batch || level2 || no_oplock) {
+                               DEBUG(0, ("Bad batch oplock entry %u.",
+                                         (unsigned)i));
+                               return false;
                        }
-                       *pp_batch = &lck->data->share_modes[i];
+                       batch = true;
                }
 
-               if (EXCLUSIVE_OPLOCK_TYPE(lck->data->share_modes[i].op_type)) {
-                       if (share_mode_stale_pid(lck->data, i)) {
+               if (EXCLUSIVE_OPLOCK_TYPE(e->op_type)) {
+                       if (share_mode_stale_pid(d, i)) {
                                DEBUG(10, ("Found stale duplicate oplock\n"));
                                continue;
                        }
                        /* Exclusive or batch - can only be one. */
-                       if (*pp_ex_or_batch || *got_level2 || *got_no_oplock) {
-                               smb_panic("Bad exclusive or batch oplock entry.");
+                       if (ex_or_batch || level2 || no_oplock) {
+                               DEBUG(0, ("Bad exclusive or batch oplock "
+                                         "entry %u.", (unsigned)i));
+                               return false;
                        }
-                       *pp_ex_or_batch = &lck->data->share_modes[i];
+                       ex_or_batch = true;
                }
 
-               if (LEVEL_II_OPLOCK_TYPE(lck->data->share_modes[i].op_type)) {
-                       if (*pp_batch || *pp_ex_or_batch) {
-                               if (share_mode_stale_pid(lck->data, i)) {
+               if (LEVEL_II_OPLOCK_TYPE(e->op_type)) {
+                       if (batch || ex_or_batch) {
+                               if (share_mode_stale_pid(d, i)) {
                                        DEBUG(10, ("Found stale LevelII "
                                                   "oplock\n"));
                                        continue;
                                }
-                               smb_panic("Bad levelII oplock entry.");
+                               DEBUG(0, ("Bad levelII oplock entry %u.",
+                                         (unsigned)i));
+                               return false;
                        }
-                       *got_level2 = true;
+                       level2 = true;
                }
 
-               if (lck->data->share_modes[i].op_type == NO_OPLOCK) {
-                       if (*pp_batch || *pp_ex_or_batch) {
-                               if (share_mode_stale_pid(lck->data, i)) {
+               if (e->op_type == NO_OPLOCK) {
+                       if (batch || ex_or_batch) {
+                               if (share_mode_stale_pid(d, i)) {
                                        DEBUG(10, ("Found stale NO_OPLOCK "
                                                   "entry\n"));
                                        continue;
                                }
-                               smb_panic("Bad no oplock entry.");
+                               DEBUG(0, ("Bad no oplock entry %u.",
+                                         (unsigned)i));
+                               return false;
                        }
-                       *got_no_oplock = true;
+                       no_oplock = true;
                }
        }
+
+       remove_stale_share_mode_entries(d);
+
+       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));
+               return false;
+       }
+
+       return true;
 }
 
-static bool delay_for_batch_oplocks(files_struct *fsp,
-                                       uint64_t mid,
-                                       int oplock_request,
-                                       struct share_mode_entry *batch_entry)
+static bool delay_for_oplock(files_struct *fsp,
+                            int oplock_request,
+                            struct share_mode_lock *lck,
+                            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 (batch_entry == NULL) {
+       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 open around. There can't be any exclusive or
+                * batch left, this is all level2.
+                */
                return false;
        }
 
-       if (server_id_is_disconnected(&batch_entry->pid)) {
+       if (server_id_is_disconnected(&entry->pid)) {
                /*
                 * TODO: clean up.
                 * This could be achieved by sending a break message
@@ -1320,33 +1397,52 @@ static bool delay_for_batch_oplocks(files_struct *fsp,
                return false;
        }
 
-       /* Found a batch oplock */
-       send_break_message(fsp, batch_entry, mid, oplock_request);
-       return true;
-}
+       switch (create_disposition) {
+       case FILE_SUPERSEDE:
+       case FILE_OVERWRITE_IF:
+               break_to = NO_OPLOCK;
+               break;
+       default:
+               break_to = LEVEL_II_OPLOCK;
+               break;
+       }
 
-static bool delay_for_exclusive_oplocks(files_struct *fsp,
-                                       uint64_t mid,
-                                       int oplock_request,
-                                       struct share_mode_entry *ex_entry)
-{
-       if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) {
+       if (have_sharing_violation && (entry->op_type & BATCH_OPLOCK)) {
+               if (share_mode_stale_pid(d, 0)) {
+                       return false;
+               }
+               send_break_message(fsp->conn->sconn->msg_ctx, entry, break_to);
+               return true;
+       }
+       if (have_sharing_violation) {
+               /*
+                * Non-batch exclusive is not broken if we have a sharing
+                * violation
+                */
                return false;
        }
-       if (ex_entry == NULL) {
+       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 (server_id_is_disconnected(&ex_entry->pid)) {
+       if (!EXCLUSIVE_OPLOCK_TYPE(entry->op_type)) {
                /*
-                * since only durable handles can get disconnected,
-                * and we can only get durable handles with batch oplocks,
-                * this should actually never be reached...
+                * No break for NO_OPLOCK or LEVEL2_OPLOCK oplocks
                 */
                return false;
        }
+       if (share_mode_stale_pid(d, 0)) {
+               return false;
+       }
 
-       send_break_message(fsp, ex_entry, mid, oplock_request);
+       send_break_message(fsp->conn->sconn->msg_ctx, entry, break_to);
        return true;
 }
 
@@ -1358,16 +1454,17 @@ static bool file_has_brlocks(files_struct *fsp)
        if (!br_lck)
                return false;
 
-       return br_lck->num_locks > 0 ? true : false;
+       return (brl_num_locks(br_lck) > 0);
 }
 
 static void grant_fsp_oplock_type(files_struct *fsp,
-                               int oplock_request,
-                               bool got_level2_oplock,
-                               bool got_a_none_oplock)
+                                 struct share_mode_lock *lck,
+                                 int oplock_request)
 {
        bool allow_level2 = (global_client_caps & CAP_LEVEL_II_OPLOCKS) &&
                            lp_level2_oplocks(SNUM(fsp->conn));
+       bool got_level2_oplock, got_a_none_oplock;
+       uint32_t i;
 
        /* Start by granting what the client asked for,
           but ensure no SAMBA_PRIVATE bits can be set. */
@@ -1394,29 +1491,29 @@ static void grant_fsp_oplock_type(files_struct *fsp,
                return;
        }
 
+       got_level2_oplock = false;
+       got_a_none_oplock = false;
+
+       for (i=0; i<lck->data->num_share_modes; i++) {
+               int op_type = lck->data->share_modes[i].op_type;
+
+               if (LEVEL_II_OPLOCK_TYPE(op_type)) {
+                       got_level2_oplock = true;
+               }
+               if (op_type == NO_OPLOCK) {
+                       got_a_none_oplock = true;
+               }
+       }
+
        /*
         * Match what was requested (fsp->oplock_type) with
         * what was found in the existing share modes.
         */
 
-       if (got_a_none_oplock) {
-               fsp->oplock_type = NO_OPLOCK;
-       } else if (got_level2_oplock) {
-               if (fsp->oplock_type == NO_OPLOCK ||
-                               fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) {
-                       /* Store a level2 oplock, but don't tell the client */
-                       fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
-               } else {
+       if (got_level2_oplock || got_a_none_oplock) {
+               if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
                        fsp->oplock_type = LEVEL_II_OPLOCK;
                }
-       } else {
-               /* All share_mode_entries are placeholders or deferred.
-                * Silently upgrade to fake levelII if the client didn't
-                * ask for an oplock. */
-               if (fsp->oplock_type == NO_OPLOCK) {
-                       /* Store a level2 oplock, but don't tell the client */
-                       fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
-               }
        }
 
        /*
@@ -1424,7 +1521,20 @@ static void grant_fsp_oplock_type(files_struct *fsp,
         * or if we've turned them off.
         */
        if (fsp->oplock_type == LEVEL_II_OPLOCK && !allow_level2) {
-               fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
+               fsp->oplock_type = NO_OPLOCK;
+       }
+
+       if (fsp->oplock_type == LEVEL_II_OPLOCK && !got_level2_oplock) {
+               /*
+                * We're the first level2 oplock. Indicate that in brlock.tdb.
+                */
+               struct byte_range_lock *brl;
+
+               brl = brl_get_locks(talloc_tos(), fsp);
+               if (brl != NULL) {
+                       brl_set_have_read_oplocks(brl, true);
+                       TALLOC_FREE(brl);
+               }
        }
 
        DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n",
@@ -1440,6 +1550,13 @@ static bool request_timed_out(struct timeval request_time,
        return (timeval_compare(&end_time, &now) < 0);
 }
 
+struct defer_open_state {
+       struct smbd_server_connection *sconn;
+       uint64_t mid;
+};
+
+static void defer_open_done(struct tevent_req *req);
+
 /****************************************************************************
  Handle the 1 second delay in returning a SHARING_VIOLATION error.
 ****************************************************************************/
@@ -1450,44 +1567,82 @@ static void defer_open(struct share_mode_lock *lck,
                       struct smb_request *req,
                       struct deferred_open_record *state)
 {
-       struct server_id self = messaging_server_id(req->sconn->msg_ctx);
+       struct deferred_open_record *open_rec;
 
-       /* Paranoia check */
+       DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred "
+                 "open entry for mid %llu\n",
+                 (unsigned int)request_time.tv_sec,
+                 (unsigned int)request_time.tv_usec,
+                 (unsigned long long)req->mid));
 
-       if (lck) {
-               int i;
+       open_rec = talloc(NULL, struct deferred_open_record);
+       if (open_rec == NULL) {
+               TALLOC_FREE(lck);
+               exit_server("talloc failed");
+       }
 
-               for (i=0; i<lck->data->num_share_modes; i++) {
-                       struct share_mode_entry *e = &lck->data->share_modes[i];
+       *open_rec = *state;
 
-                       if (is_deferred_open_entry(e) &&
-                           serverid_equal(&self, &e->pid) &&
-                           (e->op_mid == req->mid)) {
-                               DEBUG(0, ("Trying to defer an already deferred "
-                                       "request: mid=%llu, exiting\n",
-                                       (unsigned long long)req->mid));
-                               TALLOC_FREE(lck);
-                               exit_server("attempt to defer a deferred request");
-                       }
+       if (lck) {
+               struct defer_open_state *watch_state;
+               struct tevent_req *watch_req;
+               bool ret;
+
+               watch_state = talloc(open_rec, struct defer_open_state);
+               if (watch_state == NULL) {
+                       exit_server("talloc failed");
                }
-       }
+               watch_state->sconn = req->sconn;
+               watch_state->mid = req->mid;
 
-       /* End paranoia check */
+               DEBUG(10, ("defering mid %llu\n",
+                          (unsigned long long)req->mid));
 
-       DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred "
-                 "open entry for mid %llu\n",
-                 (unsigned int)request_time.tv_sec,
-                 (unsigned int)request_time.tv_usec,
-                 (unsigned long long)req->mid));
+               watch_req = dbwrap_record_watch_send(
+                       watch_state, req->sconn->ev_ctx, lck->data->record,
+                       req->sconn->msg_ctx);
+               if (watch_req == NULL) {
+                       exit_server("Could not watch share mode record");
+               }
+               tevent_req_set_callback(watch_req, defer_open_done,
+                                       watch_state);
+
+               ret = tevent_req_set_endtime(
+                       watch_req, req->sconn->ev_ctx,
+                       timeval_sum(&request_time, &timeout));
+               SMB_ASSERT(ret);
+       }
 
        if (!push_deferred_open_message_smb(req, request_time, timeout,
-                                      state->id, (char *)state, sizeof(*state))) {
+                                           state->id, open_rec)) {
                TALLOC_FREE(lck);
                exit_server("push_deferred_open_message_smb failed");
        }
-       if (lck) {
-               add_deferred_open(lck, req->mid, request_time, self, state->id);
+}
+
+static void defer_open_done(struct tevent_req *req)
+{
+       struct defer_open_state *state = tevent_req_callback_data(
+               req, struct defer_open_state);
+       NTSTATUS status;
+       bool ret;
+
+       status = dbwrap_record_watch_recv(req, talloc_tos(), NULL);
+       TALLOC_FREE(req);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(5, ("dbwrap_record_watch_recv returned %s\n",
+                         nt_errstr(status)));
+               /*
+                * Even if it failed, retry anyway. TODO: We need a way to
+                * tell a re-scheduled open about that error.
+                */
        }
+
+       DEBUG(10, ("scheduling mid %llu\n", (unsigned long long)state->mid));
+
+       ret = schedule_deferred_open_message_smb(state->sconn, state->mid);
+       SMB_ASSERT(ret);
+       TALLOC_FREE(state);
 }
 
 
@@ -1570,7 +1725,8 @@ static NTSTATUS fcb_or_dos_open(struct smb_request *req,
                          (unsigned int)fsp->fh->private_options,
                          (unsigned int)fsp->access_mask ));
 
-               if (fsp->fh->fd != -1 &&
+               if (fsp != fsp_to_dup_into &&
+                   fsp->fh->fd != -1 &&
                    fsp->vuid == vuid &&
                    fsp->file_pid == file_pid &&
                    (fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
@@ -1601,6 +1757,7 @@ static NTSTATUS fcb_or_dos_open(struct smb_request *req,
 }
 
 static void schedule_defer_open(struct share_mode_lock *lck,
+                               struct file_id id,
                                struct timeval request_time,
                                struct smb_request *req)
 {
@@ -1631,7 +1788,7 @@ static void schedule_defer_open(struct share_mode_lock *lck,
 
        state.delayed_for_oplocks = True;
        state.async_open = false;
-       state.id = lck->data->id;
+       state.id = id;
 
        if (!request_timed_out(request_time, timeout)) {
                defer_open(lck, request_time, timeout, req, &state);
@@ -1681,7 +1838,8 @@ static NTSTATUS smbd_calculate_maximum_allowed_access(
        status = SMB_VFS_GET_NT_ACL(conn, smb_fname->base_name,
                                    (SECINFO_OWNER |
                                     SECINFO_GROUP |
-                                    SECINFO_DACL),&sd);
+                                    SECINFO_DACL),
+                                   talloc_tos(), &sd);
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
                /*
@@ -1698,7 +1856,13 @@ static NTSTATUS smbd_calculate_maximum_allowed_access(
        }
 
        /*
-        * Never test FILE_READ_ATTRIBUTES. se_file_access_check()
+        * If we can access the path to this file, by
+        * default we have FILE_READ_ATTRIBUTES from the
+        * containing directory. See the section:
+        * "Algorithm to Check Access to an Existing File"
+        * in MS-FSA.pdf.
+        *
+        * se_file_access_check()
         * also takes care of owner WRITE_DAC and READ_CONTROL.
         */
        status = se_file_access_check(sd,
@@ -1776,28 +1940,13 @@ NTSTATUS smbd_calculate_access_mask(connection_struct *conn,
  Remove the deferred open entry under lock.
 ****************************************************************************/
 
-void remove_deferred_open_entry(struct file_id id, uint64_t mid,
-                               struct server_id pid)
-{
-       struct share_mode_lock *lck = get_existing_share_mode_lock(
-               talloc_tos(), id);
-       if (lck == NULL) {
-               DEBUG(0, ("could not get share mode lock\n"));
-               return;
-       }
-       del_deferred_open_entry(lck, mid, pid);
-       TALLOC_FREE(lck);
-}
-
 /****************************************************************************
  Return true if this is a state pointer to an asynchronous create.
 ****************************************************************************/
 
-bool is_deferred_open_async(const void *ptr)
+bool is_deferred_open_async(const struct deferred_open_record *rec)
 {
-       const struct deferred_open_record *state = (const struct deferred_open_record *)ptr;
-
-       return state->async_open;
+       return rec->async_open;
 }
 
 static bool clear_ads(uint32_t create_disposition)
@@ -1869,6 +2018,37 @@ static int disposition_to_open_flags(uint32_t create_disposition)
        return ret;
 }
 
+static int calculate_open_access_flags(uint32_t access_mask,
+                                      int oplock_request,
+                                      uint32_t private_flags)
+{
+       bool need_write, need_read;
+
+       /*
+        * Note that we ignore the append flag as append does not
+        * mean the same thing under DOS and Unix.
+        */
+
+       need_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA));
+       if (!need_write) {
+               return O_RDONLY;
+       }
+
+       /* DENY_DOS opens are always underlying read-write on the
+          file handle, no matter what the requested access mask
+          says. */
+
+       need_read =
+               ((private_flags & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) ||
+                access_mask & (FILE_READ_ATTRIBUTES|FILE_READ_DATA|
+                               FILE_READ_EA|FILE_EXECUTE));
+
+       if (!need_read) {
+               return O_WRONLY;
+       }
+       return O_RDWR;
+}
+
 /****************************************************************************
  Open a file with a share mode. Passed in an already created files_struct *.
 ****************************************************************************/
@@ -1893,6 +2073,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
        bool def_acl = False;
        bool posix_open = False;
        bool new_file_created = False;
+       bool first_open_attempt = true;
        NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED;
        mode_t new_unx_mode = (mode_t)0;
        mode_t unx_mode = (mode_t)0;
@@ -1904,6 +2085,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
        NTSTATUS status;
        char *parent_dir;
        SMB_STRUCT_STAT saved_stat = smb_fname->st;
+       struct timespec old_write_time;
+       struct file_id id;
 
        if (conn->printer) {
                /*
@@ -1959,9 +2142,12 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                   create_options, (unsigned int)unx_mode, oplock_request,
                   (unsigned int)private_flags));
 
-       if ((req == NULL) && ((oplock_request & INTERNAL_OPEN_ONLY) == 0)) {
-               DEBUG(0, ("No smb request but not an internal only open!\n"));
-               return NT_STATUS_INTERNAL_ERROR;
+       if (req == NULL) {
+               /* Ensure req == NULL means INTERNAL_OPEN_ONLY */
+               SMB_ASSERT(((oplock_request & INTERNAL_OPEN_ONLY) != 0));
+       } else {
+               /* And req != NULL means no INTERNAL_OPEN_ONLY */
+               SMB_ASSERT(((oplock_request & INTERNAL_OPEN_ONLY) == 0));
        }
 
        /*
@@ -1969,10 +2155,10 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
         */
 
        if (req) {
-               void *ptr;
+               struct deferred_open_record *open_rec;
                if (get_deferred_open_message_state(req,
                                &request_time,
-                               &ptr)) {
+                               &open_rec)) {
                        /* Remember the absolute time of the original
                           request with this mid. We'll use it later to
                           see if this has timed out. */
@@ -1980,19 +2166,15 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                        /* If it was an async create retry, the file
                           didn't exist. */
 
-                       if (is_deferred_open_async(ptr)) {
+                       if (is_deferred_open_async(open_rec)) {
                                SET_STAT_INVALID(smb_fname->st);
                                file_existed = false;
-                       } else {
-                               struct deferred_open_record *state = (struct deferred_open_record *)ptr;
-                               /* Remove the deferred open entry under lock. */
-                               remove_deferred_open_entry(
-                                       state->id, req->mid,
-                                       messaging_server_id(req->sconn->msg_ctx));
                        }
 
                        /* Ensure we don't reprocess this message. */
                        remove_deferred_open_message_smb(req->sconn, req->mid);
+
+                       first_open_attempt = false;
                }
        }
 
@@ -2110,7 +2292,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 
        open_access_mask = access_mask;
 
-       if ((flags2 & O_TRUNC) || (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE)) {
+       if (flags2 & O_TRUNC) {
                open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */
        }
 
@@ -2123,21 +2305,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
         * mean the same thing under DOS and Unix.
         */
 
-       if ((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ||
-           (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE)) {
-               /* DENY_DOS opens are always underlying read-write on the
-                  file handle, no matter what the requested access mask
-                   says. */
-               if ((private_flags & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) ||
-                   access_mask & (FILE_READ_ATTRIBUTES|FILE_READ_DATA|
-                                  FILE_READ_EA|FILE_EXECUTE)) {
-                       flags = O_RDWR;
-               } else {
-                       flags = O_WRONLY;
-               }
-       } else {
-               flags = O_RDONLY;
-       }
+       flags = calculate_open_access_flags(access_mask, oplock_request,
+                                           private_flags);
 
        /*
         * Currently we only look at FILE_WRITE_THROUGH for create options.
@@ -2162,6 +2331,24 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                flags2 &= ~(O_CREAT|O_TRUNC);
        }
 
+       if (first_open_attempt && lp_kernel_oplocks(SNUM(conn))) {
+               /*
+                * With kernel oplocks the open breaking an oplock
+                * blocks until the oplock holder has given up the
+                * oplock or closed the file. We prevent this by first
+                * trying to open the file with O_NONBLOCK (see "man
+                * fcntl" on Linux). For the second try, triggered by
+                * an oplock break response, we do not need this
+                * anymore.
+                *
+                * This is true under the assumption that only Samba
+                * requests kernel oplocks. Once someone else like
+                * NFSv4 starts to use that API, we will have to
+                * modify this by communicating with the NFSv4 server.
+                */
+               flags2 |= O_NONBLOCK;
+       }
+
        /*
         * Ensure we can't write on a read-only share or file.
         */
@@ -2191,209 +2378,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                request_time = fsp->open_time;
        }
 
-       if (file_existed) {
-               struct share_mode_entry *batch_entry = NULL;
-               struct share_mode_entry *exclusive_entry = NULL;
-               bool got_level2_oplock = false;
-               bool got_a_none_oplock = false;
-               struct file_id id;
-
-               struct timespec old_write_time = smb_fname->st.st_ex_mtime;
-               id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
-
-               lck = get_share_mode_lock(talloc_tos(), id,
-                                         conn->connectpath,
-                                         smb_fname, &old_write_time);
-               if (lck == NULL) {
-                       DEBUG(0, ("Could not get share mode lock\n"));
-                       return NT_STATUS_SHARING_VIOLATION;
-               }
-
-               /* Get the types we need to examine. */
-               find_oplock_types(fsp,
-                               oplock_request,
-                               lck,
-                               &batch_entry,
-                               &exclusive_entry,
-                               &got_level2_oplock,
-                               &got_a_none_oplock);
-
-               /* First pass - send break only on batch oplocks. */
-               if ((req != NULL) &&
-                               delay_for_batch_oplocks(fsp,
-                                       req->mid,
-                                       oplock_request,
-                                       batch_entry)) {
-                       schedule_defer_open(lck, request_time, req);
-                       TALLOC_FREE(lck);
-                       return NT_STATUS_SHARING_VIOLATION;
-               }
-
-               /* Use the client requested access mask here, not the one we
-                * open with. */
-               status = open_mode_check(conn, lck, fsp->name_hash,
-                                       access_mask, share_access,
-                                        create_options, &file_existed);
-
-               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_exclusive_oplocks(
-                                               fsp,
-                                               req->mid,
-                                               oplock_request,
-                                               exclusive_entry)) {
-                               schedule_defer_open(lck, request_time, req);
-                               TALLOC_FREE(lck);
-                               return NT_STATUS_SHARING_VIOLATION;
-                       }
-               }
-
-               if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
-                       /* DELETE_PENDING is not deferred for a second */
-                       TALLOC_FREE(lck);
-                       return status;
-               }
-
-               grant_fsp_oplock_type(fsp,
-                                oplock_request,
-                                got_level2_oplock,
-                                got_a_none_oplock);
-
-               if (!NT_STATUS_IS_OK(status)) {
-                       uint32 can_access_mask;
-                       bool can_access = True;
-
-                       SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION));
-
-                       /* Check if this can be done with the deny_dos and fcb
-                        * calls. */
-                       if (private_flags &
-                           (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
-                            NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
-                               if (req == NULL) {
-                                       DEBUG(0, ("DOS open without an SMB "
-                                                 "request!\n"));
-                                       TALLOC_FREE(lck);
-                                       return NT_STATUS_INTERNAL_ERROR;
-                               }
-
-                               /* Use the client requested access mask here,
-                                * not the one we open with. */
-                               status = fcb_or_dos_open(req,
-                                                       conn,
-                                                       fsp,
-                                                       smb_fname,
-                                                       id,
-                                                       req->smbpid,
-                                                       req->vuid,
-                                                       access_mask,
-                                                       share_access,
-                                                       create_options);
-
-                               if (NT_STATUS_IS_OK(status)) {
-                                       TALLOC_FREE(lck);
-                                       if (pinfo) {
-                                               *pinfo = FILE_WAS_OPENED;
-                                       }
-                                       return NT_STATUS_OK;
-                               }
-                       }
-
-                       /*
-                        * This next line is a subtlety we need for
-                        * MS-Access. If a file open will fail due to share
-                        * permissions and also for security (access) reasons,
-                        * we need to return the access failed error, not the
-                        * share error. We can't open the file due to kernel
-                        * oplock deadlock (it's possible we failed above on
-                        * the open_mode_check()) so use a userspace check.
-                        */
-
-                       if (flags & O_RDWR) {
-                               can_access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
-                       } else if (flags & O_WRONLY) {
-                               can_access_mask = FILE_WRITE_DATA;
-                       } else {
-                               can_access_mask = FILE_READ_DATA;
-                       }
-
-                       if (((can_access_mask & FILE_WRITE_DATA) &&
-                               !CAN_WRITE(conn)) ||
-                               !NT_STATUS_IS_OK(smbd_check_access_rights(conn,
-                                                       smb_fname,
-                                                       false,
-                                                       can_access_mask))) {
-                               can_access = False;
-                       }
-
-                       /*
-                        * If we're returning a share violation, ensure we
-                        * cope with the braindead 1 second delay.
-                        */
-
-                       if (!(oplock_request & INTERNAL_OPEN_ONLY) &&
-                           lp_defer_sharing_violations()) {
-                               struct timeval timeout;
-                               struct deferred_open_record state;
-                               int timeout_usecs;
-
-                               /* this is a hack to speed up torture tests
-                                  in 'make test' */
-                               timeout_usecs = lp_parm_int(SNUM(conn),
-                                                           "smbd","sharedelay",
-                                                           SHARING_VIOLATION_USEC_WAIT);
-
-                               /* This is a relative time, added to the absolute
-                                  request_time value to get the absolute timeout time.
-                                  Note that if this is the second or greater time we enter
-                                  this codepath for this particular request mid then
-                                  request_time is left as the absolute time of the *first*
-                                  time this request mid was processed. This is what allows
-                                  the request to eventually time out. */
-
-                               timeout = timeval_set(0, timeout_usecs);
-
-                               /* Nothing actually uses state.delayed_for_oplocks
-                                  but it's handy to differentiate in debug messages
-                                  between a 30 second delay due to oplock break, and
-                                  a 1 second delay for share mode conflicts. */
-
-                               state.delayed_for_oplocks = False;
-                               state.async_open = false;
-                               state.id = id;
-
-                               if ((req != NULL)
-                                   && !request_timed_out(request_time,
-                                                         timeout)) {
-                                       defer_open(lck, request_time, timeout,
-                                                  req, &state);
-                               }
-                       }
-
-                       TALLOC_FREE(lck);
-                       if (can_access) {
-                               /*
-                                * We have detected a sharing violation here
-                                * so return the correct error code
-                                */
-                               status = NT_STATUS_SHARING_VIOLATION;
-                       } else {
-                               status = NT_STATUS_ACCESS_DENIED;
-                       }
-                       return status;
-               }
-
-               /*
-                * We exit this block with the share entry *locked*.....
-                */
-       }
-
-       SMB_ASSERT(!file_existed || (lck != NULL));
-
        /*
         * Ensure we pay attention to default ACLs on directories if required.
         */
@@ -2413,11 +2397,67 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                             flags|flags2, unx_mode, access_mask,
                             open_access_mask, &new_file_created);
 
+       if (NT_STATUS_EQUAL(fsp_open, NT_STATUS_NETWORK_BUSY)) {
+               struct deferred_open_record state;
+
+               /*
+                * EWOULDBLOCK/EAGAIN maps to NETWORK_BUSY.
+                */
+               if (file_existed && S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
+                       DEBUG(10, ("FIFO busy\n"));
+                       return NT_STATUS_NETWORK_BUSY;
+               }
+               if (req == NULL) {
+                       DEBUG(10, ("Internal open busy\n"));
+                       return NT_STATUS_NETWORK_BUSY;
+               }
+
+               /*
+                * From here on we assume this is an oplock break triggered
+                */
+
+               lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
+               if (lck == NULL) {
+                       state.delayed_for_oplocks = false;
+                       state.async_open = false;
+                       state.id = fsp->file_id;
+                       defer_open(NULL, request_time, timeval_set(0, 0),
+                                  req, &state);
+                       DEBUG(10, ("No share mode lock found after "
+                                  "EWOULDBLOCK, retrying sync\n"));
+                       return NT_STATUS_SHARING_VIOLATION;
+               }
+
+               if (!validate_oplock_types(lck)) {
+                       smb_panic("validate_oplock_types failed");
+               }
+
+               if (delay_for_oplock(fsp, 0, lck, false, create_disposition)) {
+                       schedule_defer_open(lck, fsp->file_id, request_time, req);
+                       TALLOC_FREE(lck);
+                       DEBUG(10, ("Sent oplock break request to kernel "
+                                  "oplock holder\n"));
+                       return NT_STATUS_SHARING_VIOLATION;
+               }
+
+               /*
+                * No oplock from Samba around. Immediately retry with
+                * a blocking open.
+                */
+               state.delayed_for_oplocks = false;
+               state.async_open = false;
+               state.id = fsp->file_id;
+               defer_open(lck, request_time, timeval_set(0, 0), req, &state);
+               TALLOC_FREE(lck);
+               DEBUG(10, ("No Samba oplock around after EWOULDBLOCK. "
+                          "Retrying sync\n"));
+               return NT_STATUS_SHARING_VIOLATION;
+       }
+
        if (!NT_STATUS_IS_OK(fsp_open)) {
                if (NT_STATUS_EQUAL(fsp_open, NT_STATUS_RETRY)) {
                        schedule_async_open(request_time, req);
                }
-               TALLOC_FREE(lck);
                return fsp_open;
        }
 
@@ -2431,7 +2471,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                 * just fail the open to prevent creating any problems
                 * in the open file db having the wrong dev/ino key.
                 */
-               TALLOC_FREE(lck);
                fd_close(fsp);
                DEBUG(1,("open_file_ntcreate: file %s - dev/ino mismatch. "
                        "Old (dev=0x%llu, ino =0x%llu). "
@@ -2445,120 +2484,221 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       if (!file_existed) {
-               struct share_mode_entry *batch_entry = NULL;
-               struct share_mode_entry *exclusive_entry = NULL;
-               bool got_level2_oplock = false;
-               bool got_a_none_oplock = false;
-               struct timespec old_write_time = smb_fname->st.st_ex_mtime;
-               struct file_id id;
-               /*
-                * Deal with the race condition where two smbd's detect the
-                * file doesn't exist and do the create at the same time. One
-                * of them will win and set a share mode, the other (ie. this
-                * one) should check if the requested share mode for this
-                * create is allowed.
-                */
+       old_write_time = smb_fname->st.st_ex_mtime;
 
-               /*
-                * Now the file exists and fsp is successfully opened,
-                * fsp->dev and fsp->inode are valid and should replace the
-                * dev=0,inode=0 from a non existent file. Spotted by
-                * Nadav Danieli <nadavd@exanet.com>. JRA.
-                */
+       /*
+        * Deal with the race condition where two smbd's detect the
+        * file doesn't exist and do the create at the same time. One
+        * of them will win and set a share mode, the other (ie. this
+        * one) should check if the requested share mode for this
+        * create is allowed.
+        */
 
-               id = fsp->file_id;
+       /*
+        * Now the file exists and fsp is successfully opened,
+        * fsp->dev and fsp->inode are valid and should replace the
+        * dev=0,inode=0 from a non existent file. Spotted by
+        * Nadav Danieli <nadavd@exanet.com>. JRA.
+        */
 
-               lck = get_share_mode_lock(talloc_tos(), id,
-                                         conn->connectpath,
-                                         smb_fname, &old_write_time);
+       id = fsp->file_id;
 
-               if (lck == NULL) {
-                       DEBUG(0, ("open_file_ntcreate: Could not get share "
-                                 "mode lock for %s\n",
-                                 smb_fname_str_dbg(smb_fname)));
-                       fd_close(fsp);
-                       return NT_STATUS_SHARING_VIOLATION;
-               }
+       lck = get_share_mode_lock(talloc_tos(), id,
+                                 conn->connectpath,
+                                 smb_fname, &old_write_time);
 
-               /* Get the types we need to examine. */
-               find_oplock_types(fsp,
-                               oplock_request,
-                               lck,
-                               &batch_entry,
-                               &exclusive_entry,
-                               &got_level2_oplock,
-                               &got_a_none_oplock);
-
-               /* First pass - send break only on batch oplocks. */
-               if ((req != NULL) &&
-                               delay_for_batch_oplocks(fsp,
-                                       req->mid,
-                                       oplock_request,
-                                       batch_entry)) {
-                       schedule_defer_open(lck, request_time, req);
-                       TALLOC_FREE(lck);
-                       fd_close(fsp);
-                       return NT_STATUS_SHARING_VIOLATION;
-               }
+       if (lck == NULL) {
+               DEBUG(0, ("open_file_ntcreate: Could not get share "
+                         "mode lock for %s\n",
+                         smb_fname_str_dbg(smb_fname)));
+               fd_close(fsp);
+               return NT_STATUS_SHARING_VIOLATION;
+       }
+
+       /* Get the types we need to examine. */
+       if (!validate_oplock_types(lck)) {
+               smb_panic("validate_oplock_types failed");
+       }
+
+       if (has_delete_on_close(lck, fsp->name_hash)) {
+               TALLOC_FREE(lck);
+               fd_close(fsp);
+               return NT_STATUS_DELETE_PENDING;
+       }
 
-               status = open_mode_check(conn, lck, fsp->name_hash,
-                                       access_mask, share_access,
-                                        create_options, &file_existed);
+       status = open_mode_check(conn, lck,
+                                access_mask, share_access);
 
-               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_exclusive_oplocks(
-                                               fsp,
-                                               req->mid,
-                                               oplock_request,
-                                               exclusive_entry)) {
-                               schedule_defer_open(lck, request_time, req);
+       if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
+           (lck->data->num_share_modes > 0)) {
+               /*
+                * This comes from ancient times out of open_mode_check. I
+                * have no clue whether this is still necessary. I can't think
+                * of a case where this would actually matter further down in
+                * this function. I leave it here for further investigation
+                * :-)
+                */
+               file_existed = true;
+       }
+
+       if ((req != NULL) &&
+           delay_for_oplock(
+                   fsp, oplock_request, lck,
+                   NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION),
+                   create_disposition)) {
+               schedule_defer_open(lck, fsp->file_id, request_time, req);
+               TALLOC_FREE(lck);
+               fd_close(fsp);
+               return NT_STATUS_SHARING_VIOLATION;
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               uint32 can_access_mask;
+               bool can_access = True;
+
+               SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION));
+
+               /* Check if this can be done with the deny_dos and fcb
+                * calls. */
+               if (private_flags &
+                   (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
+                    NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
+                       if (req == NULL) {
+                               DEBUG(0, ("DOS open without an SMB "
+                                         "request!\n"));
                                TALLOC_FREE(lck);
                                fd_close(fsp);
-                               return NT_STATUS_SHARING_VIOLATION;
+                               return NT_STATUS_INTERNAL_ERROR;
+                       }
+
+                       /* Use the client requested access mask here,
+                        * not the one we open with. */
+                       status = fcb_or_dos_open(req,
+                                                conn,
+                                                fsp,
+                                                smb_fname,
+                                                id,
+                                                req->smbpid,
+                                                req->vuid,
+                                                access_mask,
+                                                share_access,
+                                                create_options);
+
+                       if (NT_STATUS_IS_OK(status)) {
+                               TALLOC_FREE(lck);
+                               if (pinfo) {
+                                       *pinfo = FILE_WAS_OPENED;
+                               }
+                               return NT_STATUS_OK;
                        }
                }
 
-               if (!NT_STATUS_IS_OK(status)) {
+               /*
+                * This next line is a subtlety we need for
+                * MS-Access. If a file open will fail due to share
+                * permissions and also for security (access) reasons,
+                * we need to return the access failed error, not the
+                * share error. We can't open the file due to kernel
+                * oplock deadlock (it's possible we failed above on
+                * the open_mode_check()) so use a userspace check.
+                */
+
+               if (flags & O_RDWR) {
+                       can_access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
+               } else if (flags & O_WRONLY) {
+                       can_access_mask = FILE_WRITE_DATA;
+               } else {
+                       can_access_mask = FILE_READ_DATA;
+               }
+
+               if (((can_access_mask & FILE_WRITE_DATA) &&
+                    !CAN_WRITE(conn)) ||
+                   !NT_STATUS_IS_OK(smbd_check_access_rights(conn,
+                                                             smb_fname,
+                                                             false,
+                                                             can_access_mask))) {
+                       can_access = False;
+               }
+
+               /*
+                * If we're returning a share violation, ensure we
+                * cope with the braindead 1 second delay (SMB1 only).
+                */
+
+               if (!(oplock_request & INTERNAL_OPEN_ONLY) &&
+                   !conn->sconn->using_smb2 &&
+                   lp_defer_sharing_violations()) {
+                       struct timeval timeout;
                        struct deferred_open_record state;
+                       int timeout_usecs;
+
+                       /* this is a hack to speed up torture tests
+                          in 'make test' */
+                       timeout_usecs = lp_parm_int(SNUM(conn),
+                                                   "smbd","sharedelay",
+                                                   SHARING_VIOLATION_USEC_WAIT);
+
+                       /* This is a relative time, added to the absolute
+                          request_time value to get the absolute timeout time.
+                          Note that if this is the second or greater time we enter
+                          this codepath for this particular request mid then
+                          request_time is left as the absolute time of the *first*
+                          time this request mid was processed. This is what allows
+                          the request to eventually time out. */
+
+                       timeout = timeval_set(0, timeout_usecs);
+
+                       /* Nothing actually uses state.delayed_for_oplocks
+                          but it's handy to differentiate in debug messages
+                          between a 30 second delay due to oplock break, and
+                          a 1 second delay for share mode conflicts. */
 
                        state.delayed_for_oplocks = False;
                        state.async_open = false;
                        state.id = id;
 
-                       /* Do it all over again immediately. In the second
-                        * round we will find that the file existed and handle
-                        * the DELETE_PENDING and FCB cases correctly. No need
-                        * to duplicate the code here. Essentially this is a
-                        * "goto top of this function", but don't tell
-                        * anybody... */
-
-                       if (req != NULL) {
-                               defer_open(lck, request_time, timeval_zero(),
+                       if ((req != NULL)
+                           && !request_timed_out(request_time,
+                                                 timeout)) {
+                               defer_open(lck, request_time, timeout,
                                           req, &state);
                        }
-                       TALLOC_FREE(lck);
-                       fd_close(fsp);
-                       return status;
                }
 
-               grant_fsp_oplock_type(fsp,
-                                oplock_request,
-                                got_level2_oplock,
-                                got_a_none_oplock);
+               TALLOC_FREE(lck);
+               fd_close(fsp);
+               if (can_access) {
+                       /*
+                        * We have detected a sharing violation here
+                        * so return the correct error code
+                        */
+                       status = NT_STATUS_SHARING_VIOLATION;
+               } else {
+                       status = NT_STATUS_ACCESS_DENIED;
+               }
+               return status;
+       }
 
-               /*
-                * We exit this block with the share entry *locked*.....
-                */
+       /* Should we atomically (to the client at least) truncate ? */
+       if ((!new_file_created) &&
+           (flags2 & O_TRUNC) &&
+           (!S_ISFIFO(fsp->fsp_name->st.st_ex_mode))) {
+               int ret;
 
+               ret = vfs_set_filelen(fsp, 0);
+               if (ret != 0) {
+                       status = map_nt_error_from_unix(errno);
+                       TALLOC_FREE(lck);
+                       fd_close(fsp);
+                       return status;
+               }
        }
 
-       SMB_ASSERT(lck != NULL);
+       grant_fsp_oplock_type(fsp, lck, oplock_request);
+
+       /*
+        * We have the share entry *locked*.....
+        */
 
        /* Delete streams if create_disposition requires it */
        if (!new_file_created && clear_ads(create_disposition) &&
@@ -2640,18 +2780,21 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
         * file structs.
         */
 
-       status = set_file_oplock(fsp, fsp->oplock_type);
+       status = set_file_oplock(fsp);
        if (!NT_STATUS_IS_OK(status)) {
                /*
-                * Could not get the kernel oplock or there are byte-range
-                * locks on the file.
+                * Could not get the kernel oplock
                 */
                fsp->oplock_type = NO_OPLOCK;
        }
 
-       set_share_mode(lck, fsp, get_current_uid(conn),
-                       req ? req->mid : 0,
-                      fsp->oplock_type);
+       if (!set_share_mode(lck, fsp, get_current_uid(conn),
+                           req ? req->mid : 0,
+                           fsp->oplock_type)) {
+               TALLOC_FREE(lck);
+               fd_close(fsp);
+               return NT_STATUS_NO_MEMORY;
+       }
 
        /* Handle strange delete on close create semantics. */
        if (create_options & FILE_DELETE_ON_CLOSE) {
@@ -2738,50 +2881,22 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                                  (unsigned int)new_unx_mode));
        }
 
-       /* If this is a successful open, we must remove any deferred open
-        * records. */
-       if (req != NULL) {
-               del_deferred_open_entry(lck, req->mid,
-                                       messaging_server_id(req->sconn->msg_ctx));
+       {
+               /*
+                * Deal with other opens having a modified write time.
+                */
+               struct timespec write_time = get_share_mode_write_time(lck);
+
+               if (!null_timespec(write_time)) {
+                       update_stat_ex_mtime(&fsp->fsp_name->st, write_time);
+               }
        }
+
        TALLOC_FREE(lck);
 
        return NT_STATUS_OK;
 }
 
-
-/****************************************************************************
- Open a file for for write to ensure that we can fchmod it.
-****************************************************************************/
-
-NTSTATUS open_file_fchmod(connection_struct *conn,
-                         struct smb_filename *smb_fname,
-                         files_struct **result)
-{
-       if (!VALID_STAT(smb_fname->st)) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-        return SMB_VFS_CREATE_FILE(
-               conn,                                   /* conn */
-               NULL,                                   /* req */
-               0,                                      /* root_dir_fid */
-               smb_fname,                              /* fname */
-               FILE_WRITE_DATA,                        /* access_mask */
-               (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
-                   FILE_SHARE_DELETE),
-               FILE_OPEN,                              /* create_disposition*/
-               0,                                      /* create_options */
-               0,                                      /* file_attributes */
-               INTERNAL_OPEN_ONLY,                     /* oplock_request */
-               0,                                      /* allocation_size */
-               0,                                      /* private_flags */
-               NULL,                                   /* sd */
-               NULL,                                   /* ea_list */
-               result,                                 /* result */
-               NULL);                                  /* pinfo */
-}
-
 static NTSTATUS mkdir_internal(connection_struct *conn,
                               struct smb_filename *smb_dname,
                               uint32 file_attributes)
@@ -2793,7 +2908,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
        bool need_re_stat = false;
        uint32_t access_mask = SEC_DIR_ADD_SUBDIR;
 
-       if(access_mask & ~(conn->share_access)) {
+       if (!CAN_WRITE(conn) || (access_mask & ~(conn->share_access))) {
                DEBUG(5,("mkdir_internal: failing share access "
                         "%s\n", lp_servicename(talloc_tos(), SNUM(conn))));
                return NT_STATUS_ACCESS_DENIED;
@@ -2850,7 +2965,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
                }
        }
 
-       if (lp_inherit_perms(SNUM(conn))) {
+       if (lp_inherit_permissions(SNUM(conn))) {
                inherit_access_posix_acl(conn, parent_dir,
                                         smb_dname->base_name, mode);
                need_re_stat = true;
@@ -3090,21 +3205,39 @@ static NTSTATUS open_directory(connection_struct *conn,
                return status;
        }
 
-       mtimespec = smb_dname->st.st_ex_mtime;
-
+       /* Don't store old timestamps for directory
+          handles in the internal database. We don't
+          update them in there if new objects
+          are creaded in the directory. Currently
+          we only update timestamps on file writes.
+          See bug #9870.
+       */
+       ZERO_STRUCT(mtimespec);
+
+       if (access_mask & (FILE_LIST_DIRECTORY|
+                          FILE_ADD_FILE|
+                          FILE_ADD_SUBDIRECTORY|
+                          FILE_TRAVERSE|
+                          DELETE_ACCESS|
+                          FILE_DELETE_CHILD)) {
 #ifdef O_DIRECTORY
-       status = fd_open(conn, fsp, O_RDONLY|O_DIRECTORY, 0);
+               status = fd_open(conn, fsp, O_RDONLY|O_DIRECTORY, 0);
 #else
-       /* POSIX allows us to open a directory with O_RDONLY. */
-       status = fd_open(conn, fsp, O_RDONLY, 0);
+               /* POSIX allows us to open a directory with O_RDONLY. */
+               status = fd_open(conn, fsp, O_RDONLY, 0);
 #endif
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(5, ("open_directory: Could not open fd for "
-                       "%s (%s)\n",
-                       smb_fname_str_dbg(smb_dname),
-                       nt_errstr(status)));
-               file_free(req, fsp);
-               return status;
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(5, ("open_directory: Could not open fd for "
+                               "%s (%s)\n",
+                               smb_fname_str_dbg(smb_dname),
+                               nt_errstr(status)));
+                       file_free(req, fsp);
+                       return status;
+               }
+       } else {
+               fsp->fh->fd = -1;
+               DEBUG(10, ("Not opening Directory %s\n",
+                       smb_fname_str_dbg(smb_dname)));
        }
 
        status = vfs_stat_fsp(fsp);
@@ -3136,9 +3269,15 @@ static NTSTATUS open_directory(connection_struct *conn,
                return NT_STATUS_SHARING_VIOLATION;
        }
 
-       status = open_mode_check(conn, lck, fsp->name_hash,
-                               access_mask, share_access,
-                                create_options, &dir_existed);
+       if (has_delete_on_close(lck, fsp->name_hash)) {
+               TALLOC_FREE(lck);
+               fd_close(fsp);
+               file_free(req, fsp);
+               return NT_STATUS_DELETE_PENDING;
+       }
+
+       status = open_mode_check(conn, lck,
+                                access_mask, share_access);
 
        if (!NT_STATUS_IS_OK(status)) {
                TALLOC_FREE(lck);
@@ -3147,14 +3286,20 @@ static NTSTATUS open_directory(connection_struct *conn,
                return status;
        }
 
-       set_share_mode(lck, fsp, get_current_uid(conn),
-                       req ? req->mid : 0, NO_OPLOCK);
+       if (!set_share_mode(lck, fsp, get_current_uid(conn),
+                           req ? req->mid : 0, NO_OPLOCK)) {
+               TALLOC_FREE(lck);
+               fd_close(fsp);
+               file_free(req, fsp);
+               return NT_STATUS_NO_MEMORY;
+       }
 
        /* For directories the delete on close bit at open time seems
           always to be honored on close... See test 19 in Samba4 BASE-DELETE. */
        if (create_options & FILE_DELETE_ON_CLOSE) {
                status = can_set_delete_on_close(fsp, 0);
                if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
+                       del_share_mode(lck, fsp);
                        TALLOC_FREE(lck);
                        fd_close(fsp);
                        file_free(req, fsp);
@@ -3168,6 +3313,18 @@ static NTSTATUS open_directory(connection_struct *conn,
                }
        }
 
+       {
+               /*
+                * Deal with other opens having a modified write time. Is this
+                * possible for directories?
+                */
+               struct timespec write_time = get_share_mode_write_time(lck);
+
+               if (!null_timespec(write_time)) {
+                       update_stat_ex_mtime(&fsp->fsp_name->st, write_time);
+               }
+       }
+
        TALLOC_FREE(lck);
 
        if (pinfo) {
@@ -3195,6 +3352,7 @@ NTSTATUS create_directory(connection_struct *conn, struct smb_request *req,
                FILE_DIRECTORY_FILE,                    /* create_options */
                FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
                0,                                      /* oplock_request */
+               NULL,                                   /* lease */
                0,                                      /* allocation_size */
                0,                                      /* private_flags */
                NULL,                                   /* sd */
@@ -3253,9 +3411,9 @@ void msg_file_was_renamed(struct messaging_context *msg,
                stream_name = NULL;
        }
 
-       status = create_synthetic_smb_fname(talloc_tos(), base_name,
-                                           stream_name, NULL, &smb_fname);
-       if (!NT_STATUS_IS_OK(status)) {
+       smb_fname = synthetic_smb_fname(talloc_tos(), base_name,
+                                       stream_name, NULL);
+       if (smb_fname == NULL) {
                return;
        }
 
@@ -3342,17 +3500,17 @@ NTSTATUS open_streams_for_delete(connection_struct *conn,
        }
 
        for (i=0; i<num_streams; i++) {
-               struct smb_filename *smb_fname = NULL;
+               struct smb_filename *smb_fname;
 
                if (strequal(stream_info[i].name, "::$DATA")) {
                        streams[i] = NULL;
                        continue;
                }
 
-               status = create_synthetic_smb_fname(talloc_tos(), fname,
-                                                   stream_info[i].name,
-                                                   NULL, &smb_fname);
-               if (!NT_STATUS_IS_OK(status)) {
+               smb_fname = synthetic_smb_fname(
+                       talloc_tos(), fname, stream_info[i].name, NULL);
+               if (smb_fname == NULL) {
+                       status = NT_STATUS_NO_MEMORY;
                        goto fail;
                }
 
@@ -3373,6 +3531,7 @@ NTSTATUS open_streams_for_delete(connection_struct *conn,
                         0,                     /* create_options */
                         FILE_ATTRIBUTE_NORMAL, /* file_attributes */
                         0,                     /* oplock_request */
+                        NULL,                  /* lease */
                         0,                     /* allocation_size */
                         NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE, /* private_flags */
                         NULL,                  /* sd */
@@ -3419,27 +3578,37 @@ NTSTATUS open_streams_for_delete(connection_struct *conn,
 
 static NTSTATUS inherit_new_acl(files_struct *fsp)
 {
-       TALLOC_CTX *ctx = talloc_tos();
+       TALLOC_CTX *frame = talloc_stackframe();
        char *parent_name = NULL;
        struct security_descriptor *parent_desc = NULL;
        NTSTATUS status = NT_STATUS_OK;
        struct security_descriptor *psd = NULL;
-       struct dom_sid *owner_sid = NULL;
-       struct dom_sid *group_sid = NULL;
+       const struct dom_sid *owner_sid = NULL;
+       const struct dom_sid *group_sid = NULL;
        uint32_t security_info_sent = (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL);
+       struct security_token *token = fsp->conn->session_info->security_token;
        bool inherit_owner = lp_inherit_owner(SNUM(fsp->conn));
        bool inheritable_components = false;
+       bool try_builtin_administrators = false;
+       const struct dom_sid *BA_U_sid = NULL;
+       const struct dom_sid *BA_G_sid = NULL;
+       bool try_system = false;
+       const struct dom_sid *SY_U_sid = NULL;
+       const struct dom_sid *SY_G_sid = NULL;
        size_t size = 0;
 
-       if (!parent_dirname(ctx, fsp->fsp_name->base_name, &parent_name, NULL)) {
+       if (!parent_dirname(frame, fsp->fsp_name->base_name, &parent_name, NULL)) {
+               TALLOC_FREE(frame);
                return NT_STATUS_NO_MEMORY;
        }
 
        status = SMB_VFS_GET_NT_ACL(fsp->conn,
-                               parent_name,
-                               (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL),
-                               &parent_desc);
+                                   parent_name,
+                                   (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL),
+                                   frame,
+                                   &parent_desc);
        if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
                return status;
        }
 
@@ -3447,6 +3616,7 @@ static NTSTATUS inherit_new_acl(files_struct *fsp)
                                        fsp->is_directory);
 
        if (!inheritable_components && !inherit_owner) {
+               TALLOC_FREE(frame);
                /* Nothing to inherit and not setting owner. */
                return NT_STATUS_OK;
        }
@@ -3466,13 +3636,99 @@ static NTSTATUS inherit_new_acl(files_struct *fsp)
        }
 
        if (owner_sid == NULL) {
-               owner_sid = &fsp->conn->session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
+               if (security_token_has_builtin_administrators(token)) {
+                       try_builtin_administrators = true;
+               } else if (security_token_is_system(token)) {
+                       try_builtin_administrators = true;
+                       try_system = true;
+               }
+       }
+
+       if (group_sid == NULL &&
+           token->num_sids == PRIMARY_GROUP_SID_INDEX)
+       {
+               if (security_token_is_system(token)) {
+                       try_builtin_administrators = true;
+                       try_system = true;
+               }
+       }
+
+       if (try_builtin_administrators) {
+               struct unixid ids;
+               bool ok;
+
+               ZERO_STRUCT(ids);
+               ok = sids_to_unixids(&global_sid_Builtin_Administrators, 1, &ids);
+               if (ok) {
+                       switch (ids.type) {
+                       case ID_TYPE_BOTH:
+                               BA_U_sid = &global_sid_Builtin_Administrators;
+                               BA_G_sid = &global_sid_Builtin_Administrators;
+                               break;
+                       case ID_TYPE_UID:
+                               BA_U_sid = &global_sid_Builtin_Administrators;
+                               break;
+                       case ID_TYPE_GID:
+                               BA_G_sid = &global_sid_Builtin_Administrators;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       if (try_system) {
+               struct unixid ids;
+               bool ok;
+
+               ZERO_STRUCT(ids);
+               ok = sids_to_unixids(&global_sid_System, 1, &ids);
+               if (ok) {
+                       switch (ids.type) {
+                       case ID_TYPE_BOTH:
+                               SY_U_sid = &global_sid_System;
+                               SY_G_sid = &global_sid_System;
+                               break;
+                       case ID_TYPE_UID:
+                               SY_U_sid = &global_sid_System;
+                               break;
+                       case ID_TYPE_GID:
+                               SY_G_sid = &global_sid_System;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       if (owner_sid == NULL) {
+               owner_sid = BA_U_sid;
+       }
+
+       if (owner_sid == NULL) {
+               owner_sid = SY_U_sid;
+       }
+
+       if (group_sid == NULL) {
+               group_sid = SY_G_sid;
+       }
+
+       if (try_system && group_sid == NULL) {
+               group_sid = BA_G_sid;
+       }
+
+       if (owner_sid == NULL) {
+               owner_sid = &token->sids[PRIMARY_USER_SID_INDEX];
        }
        if (group_sid == NULL) {
-               group_sid = &fsp->conn->session_info->security_token->sids[PRIMARY_GROUP_SID_INDEX];
+               if (token->num_sids == PRIMARY_GROUP_SID_INDEX) {
+                       group_sid = &token->sids[PRIMARY_USER_SID_INDEX];
+               } else {
+                       group_sid = &token->sids[PRIMARY_GROUP_SID_INDEX];
+               }
        }
 
-       status = se_create_child_secdesc(ctx,
+       status = se_create_child_secdesc(frame,
                        &psd,
                        &size,
                        parent_desc,
@@ -3480,6 +3736,7 @@ static NTSTATUS inherit_new_acl(files_struct *fsp)
                        group_sid,
                        fsp->is_directory);
        if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
                return status;
        }
 
@@ -3510,6 +3767,7 @@ static NTSTATUS inherit_new_acl(files_struct *fsp)
        if (inherit_owner) {
                unbecome_root();
        }
+       TALLOC_FREE(frame);
        return status;
 }
 
@@ -3613,17 +3871,36 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
                }
 
                /* Create an smb_filename with stream_name == NULL. */
-               status = create_synthetic_smb_fname(talloc_tos(),
-                                                   smb_fname->base_name,
-                                                   NULL, NULL,
-                                                   &smb_fname_base);
-               if (!NT_STATUS_IS_OK(status)) {
+               smb_fname_base = synthetic_smb_fname(talloc_tos(),
+                                                    smb_fname->base_name,
+                                                    NULL, NULL);
+               if (smb_fname_base == NULL) {
+                       status = NT_STATUS_NO_MEMORY;
                        goto fail;
                }
 
                if (SMB_VFS_STAT(conn, smb_fname_base) == -1) {
                        DEBUG(10, ("Unable to stat stream: %s\n",
                                   smb_fname_str_dbg(smb_fname_base)));
+               } else {
+                       /*
+                        * https://bugzilla.samba.org/show_bug.cgi?id=10229
+                        * We need to check if the requested access mask
+                        * could be used to open the underlying file (if
+                        * it existed), as we're passing in zero for the
+                        * access mask to the base filename.
+                        */
+                       status = check_base_file_access(conn,
+                                                       smb_fname_base,
+                                                       access_mask);
+
+                       if (!NT_STATUS_IS_OK(status)) {
+                               DEBUG(10, ("Permission check "
+                                       "for base %s failed: "
+                                       "%s\n", smb_fname->base_name,
+                                       nt_errstr(status)));
+                               goto fail;
+                       }
                }
 
                /* Open the base file. */
@@ -3837,6 +4114,17 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
                }
        }
 
+       if ((conn->fs_capabilities & FILE_FILE_COMPRESSION)
+        && (create_options & FILE_NO_COMPRESSION)
+        && (info == FILE_WAS_CREATED)) {
+               status = SMB_VFS_SET_COMPRESSION(conn, fsp, fsp,
+                                                COMPRESSION_FORMAT_NONE);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(1, ("failed to disable compression: %s\n",
+                                 nt_errstr(status)));
+               }
+       }
+
        DEBUG(10, ("create_file_unixpath: info=%d\n", info));
 
        *result = fsp;
@@ -3998,6 +4286,7 @@ NTSTATUS create_file_default(connection_struct *conn,
                             uint32_t create_options,
                             uint32_t file_attributes,
                             uint32_t oplock_request,
+                            struct smb2_lease *lease,
                             uint64_t allocation_size,
                             uint32_t private_flags,
                             struct security_descriptor *sd,