summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2019-08-07 12:15:45 +0200
committerJeremy Allison <jra@samba.org>2019-08-19 23:14:39 +0000
commit385a7fb196f7a6bdcdeb74b6e8553da7c810c1ca (patch)
treea4d6fbab73dbd6baf4c1ebc9f64567de018514b9
parentd4e98b8ae5f08d6e332b15d868e7bf85995974f3 (diff)
downloadsamba-385a7fb196f7a6bdcdeb74b6e8553da7c810c1ca.tar.gz
smbd: Introduce handle_share_mode_lease()
This consolidates the core share_mode_lock access of open_file_ntcreate into one routine. Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
-rw-r--r--source3/smbd/open.c109
1 files changed, 71 insertions, 38 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index d06db5f20a3..cdc69e1af1a 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -2339,6 +2339,66 @@ static NTSTATUS grant_fsp_oplock_type(struct files_struct *fsp,
return NT_STATUS_OK;
}
+static NTSTATUS handle_share_mode_lease(
+ files_struct *fsp,
+ struct share_mode_lock *lck,
+ uint32_t create_disposition,
+ uint32_t access_mask,
+ uint32_t share_access,
+ int oplock_request,
+ const struct smb2_lease *lease,
+ bool first_open_attempt)
+{
+ bool sharing_violation = false;
+ bool delay = false;
+ NTSTATUS status;
+
+ status = open_mode_check(
+ fsp->conn, lck, access_mask, share_access);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+ sharing_violation = true;
+ status = NT_STATUS_OK; /* handled later */
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (oplock_request == INTERNAL_OPEN_ONLY) {
+ if (sharing_violation) {
+ DBG_DEBUG("Sharing violation for internal open\n");
+ return NT_STATUS_SHARING_VIOLATION;
+ }
+
+ /*
+ * Internal opens never do oplocks or leases. We don't
+ * need to go through delay_for_oplock().
+ */
+ fsp->oplock_type = NO_OPLOCK;
+
+ return NT_STATUS_OK;
+ }
+
+ delay = delay_for_oplock(
+ fsp,
+ oplock_request,
+ lease,
+ lck,
+ sharing_violation,
+ create_disposition,
+ first_open_attempt);
+ if (delay) {
+ return NT_STATUS_RETRY;
+ }
+
+ if (sharing_violation) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
+
+ status = grant_fsp_oplock_type(fsp, lck, oplock_request, lease);
+ return status;
+}
+
static bool request_timed_out(struct smb_request *req, struct timeval timeout)
{
struct timeval now, end_time;
@@ -3460,50 +3520,23 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
return NT_STATUS_DELETE_PENDING;
}
- status = open_mode_check(conn, lck,
- access_mask, share_access);
-
- if (req != NULL) {
- /*
- * Handle oplocks, deferring the request if delay_for_oplock()
- * triggered a break message and we have to wait for the break
- * response.
- */
- bool delay;
- bool sharing_violation = NT_STATUS_EQUAL(
- status, NT_STATUS_SHARING_VIOLATION);
-
- delay = delay_for_oplock(fsp, oplock_request, lease, lck,
- sharing_violation,
- create_disposition,
- first_open_attempt);
- if (delay) {
- schedule_defer_open(lck, fsp->file_id, req);
- TALLOC_FREE(lck);
- fd_close(fsp);
- return NT_STATUS_SHARING_VIOLATION;
- }
- }
-
- if (!NT_STATUS_IS_OK(status)) {
-
- SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION));
+ status = handle_share_mode_lease(
+ fsp,
+ lck,
+ create_disposition,
+ access_mask,
+ share_access,
+ oplock_request,
+ lease,
+ first_open_attempt);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
+ schedule_defer_open(lck, fsp->file_id, req);
TALLOC_FREE(lck);
fd_close(fsp);
-
return NT_STATUS_SHARING_VIOLATION;
}
- /*
- * Setup the oplock info in both the shared memory and
- * file structs.
- */
- status = grant_fsp_oplock_type(
- fsp,
- lck,
- oplock_request,
- lease);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(lck);
fd_close(fsp);