diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/open.c | 64 |
1 files changed, 40 insertions, 24 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a893c59b9e..cd8e2a095b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1212,16 +1212,16 @@ static NTSTATUS send_break_message(files_struct *fsp, static bool 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) { struct share_mode_data *d = lck->data; + bool batch = false; + bool ex_or_batch = false; + bool level2 = false; + bool no_oplock = false; uint32_t i; - *pp_batch = NULL; - *pp_ex_or_batch = NULL; *got_level2 = false; *got_no_oplock = false; @@ -1253,12 +1253,12 @@ static bool find_oplock_types(files_struct *fsp, DEBUG(10, ("Found stale batch oplock\n")); continue; } - if (*pp_ex_or_batch || *pp_batch || *got_level2 || *got_no_oplock) { + if (ex_or_batch || batch || level2 || no_oplock) { DEBUG(0, ("Bad batch oplock entry %u.", (unsigned)i)); return false; } - *pp_batch = e; + batch = true; } if (EXCLUSIVE_OPLOCK_TYPE(e->op_type)) { @@ -1267,16 +1267,16 @@ static bool find_oplock_types(files_struct *fsp, continue; } /* Exclusive or batch - can only be one. */ - if (*pp_ex_or_batch || *got_level2 || *got_no_oplock) { + if (ex_or_batch || level2 || no_oplock) { DEBUG(0, ("Bad exclusive or batch oplock " "entry %u.", (unsigned)i)); return false; } - *pp_ex_or_batch = e; + ex_or_batch = true; } if (LEVEL_II_OPLOCK_TYPE(e->op_type)) { - if (*pp_batch || *pp_ex_or_batch) { + if (batch || ex_or_batch) { if (share_mode_stale_pid(d, i)) { DEBUG(10, ("Found stale LevelII " "oplock\n")); @@ -1286,11 +1286,11 @@ static bool find_oplock_types(files_struct *fsp, (unsigned)i)); return false; } - *got_level2 = true; + level2 = true; } if (e->op_type == NO_OPLOCK) { - if (*pp_batch || *pp_ex_or_batch) { + if (batch || ex_or_batch) { if (share_mode_stale_pid(d, i)) { DEBUG(10, ("Found stale NO_OPLOCK " "entry\n")); @@ -1300,21 +1300,41 @@ static bool find_oplock_types(files_struct *fsp, (unsigned)i)); return false; } - *got_no_oplock = true; + no_oplock = true; } } + + remove_stale_share_mode_entries(d); + + if ((batch || ex_or_batch) && (d->num_share_modes != 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; + } + + *got_level2 = level2; + *got_no_oplock = no_oplock; return true; } static bool delay_for_oplock(files_struct *fsp, uint64_t mid, int oplock_request, - struct share_mode_entry *entry) + struct share_mode_lock *lck, + int delay_for_type) { + struct share_mode_entry *entry; + if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) { return false; } - if (entry == NULL) { + if (lck->data->num_share_modes != 1) { + return false; + } + entry = &lck->data->share_modes[0]; + + if (!(entry->op_type & delay_for_type)) { return false; } @@ -1949,8 +1969,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, NTSTATUS status; char *parent_dir; SMB_STRUCT_STAT saved_stat = smb_fname->st; - 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; @@ -2294,14 +2312,13 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, } if (!find_oplock_types(fsp, 0, lck, - &batch_entry, &exclusive_entry, &got_level2_oplock, &got_a_none_oplock)) { smb_panic("find_oplock_types failed"); } - if (delay_for_oplock(fsp, req->mid, 0, batch_entry) || - delay_for_oplock(fsp, req->mid, 0, exclusive_entry)) { + if (delay_for_oplock(fsp, req->mid, 0, lck, + BATCH_OPLOCK|EXCLUSIVE_OPLOCK)) { schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); DEBUG(10, ("Sent oplock break request to kernel " @@ -2386,7 +2403,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, /* Get the types we need to examine. */ if (!find_oplock_types(fsp, oplock_request, lck, - &batch_entry, &exclusive_entry, &got_level2_oplock, &got_a_none_oplock)) { smb_panic("find_oplock_types failed"); @@ -2400,8 +2416,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, /* First pass - send break only on batch oplocks. */ if ((req != NULL) && - delay_for_oplock(fsp, req->mid, oplock_request, - batch_entry)) { + delay_for_oplock(fsp, req->mid, oplock_request, lck, + BATCH_OPLOCK)) { schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); fd_close(fsp); @@ -2418,8 +2434,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, /* Second pass - send break for both batch or * exclusive oplocks. */ if ((req != NULL) && - delay_for_oplock(fsp, req->mid, oplock_request, - exclusive_entry)) { + delay_for_oplock(fsp, req->mid, oplock_request, lck, + BATCH_OPLOCK|EXCLUSIVE_OPLOCK)) { schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); fd_close(fsp); |