summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2012-09-13 15:40:17 +0200
committerVolker Lendecke <vl@samba.org>2012-09-29 08:42:49 -0700
commit173e808ed48a67ffbafd77a5e9d54ba6b8d3e6e8 (patch)
tree63b82141a608bc5ebdde2134f42f632dc36af94c
parent590d3138be0293fbe9cb575261eb5319351d1e91 (diff)
downloadsamba-173e808ed48a67ffbafd77a5e9d54ba6b8d3e6e8.tar.gz
samba-173e808ed48a67ffbafd77a5e9d54ba6b8d3e6e8.tar.bz2
samba-173e808ed48a67ffbafd77a5e9d54ba6b8d3e6e8.zip
s3: Remove share mode handling before we open the file
This is a significant behaviour change: We do not open the file under the share mode lock anymore. This might lead to more open calls in case of oplock breaks or sharing violations, but those are slow error paths and as such might be not too performance sensitive. The benefit of this patch is a significant reduction of complexity of open_file_ntcreate()
-rw-r--r--source3/smbd/open.c205
1 files changed, 1 insertions, 204 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 9c9eff5a46..a67f8103e9 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -2214,209 +2214,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.
*/
@@ -2468,7 +2265,7 @@ 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;