diff options
Diffstat (limited to 'source3/smbd/open.c')
-rw-r--r-- | source3/smbd/open.c | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b13b4f2a6c..2c259e7822 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -623,8 +623,11 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, BOOL delay_it = False; BOOL have_level2 = False; - if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) { + if (oplock_request & INTERNAL_OPEN_ONLY) { fsp->oplock_type = NO_OPLOCK; + } + + if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) { return False; } @@ -1582,10 +1585,43 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } + /* + * The share entry is again *locked*..... + */ + + /* First pass - send break only on batch oplocks. */ + if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { + schedule_defer_open(lck, request_time); + fd_close(conn, fsp); + file_free(fsp); + TALLOC_FREE(lck); + return NT_STATUS_SHARING_VIOLATION; + } + status = open_mode_check(conn, fname, lck, 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 (delay_for_oplocks(lck, fsp, 2, oplock_request)) { + schedule_defer_open(lck, request_time); + fd_close(conn, fsp); + file_free(fsp); + 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 */ + fd_close(conn, fsp); + file_free(fsp); + TALLOC_FREE(lck); + return status; + } + if (!NT_STATUS_IS_OK(status)) { struct deferred_open_record state; @@ -1609,10 +1645,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } - /* - * The share entry is again *locked*..... - */ - /* note that we ignore failure for the following. It is basically a hack for NFS, and NFS will never set one of these only read them. Nobody but Samba can ever set a deny @@ -1653,6 +1685,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->access_mask = access_mask; if (file_existed) { + /* stat opens on existing files don't get oplocks. */ + if (is_stat_open(fsp->access_mask)) { + fsp->oplock_type = NO_OPLOCK; + } + if (!(flags2 & O_TRUNC)) { info = FILE_WAS_OPENED; } else { |