mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
Fix the SMB2 showstopper, found by an extended torture test from Volker.
In the oplock refactoring, the algorithm underwent an unnoticed change. In 3.5.x stat_opens were silently (i.e. no explicit code had comments explaining this) ignored when looking for oplock breaks and share mode violations. After the refactoring, the function find_oplock_types() no longer ignored stat_open entries in the share mode table when looking for batch and exclusive oplocks. This patch adds two changes to find_oplock_types() to ignore the case where the incoming open request is a stat open being tested against existing opens, and also when the incoming open request is a non-stat open being tested against existing stat opens. Neither of these cause an oplock break or share mode violation. Thanks a *lot* to Volker, who persevered in reproducing this problem. Autobuild-User: Jeremy Allison <jra@samba.org> Autobuild-Date: Mon May 16 22:38:20 CEST 2011 on sn-devel-104
This commit is contained in:
parent
fe21bdc43c
commit
8cf14c21b3
@ -949,7 +949,9 @@ static NTSTATUS send_break_message(files_struct *fsp,
|
||||
* Do internal consistency checks on the share mode for a file.
|
||||
*/
|
||||
|
||||
static void find_oplock_types(struct share_mode_lock *lck,
|
||||
static void find_oplock_types(files_struct *fsp,
|
||||
int oplock_request,
|
||||
struct share_mode_lock *lck,
|
||||
struct share_mode_entry **pp_batch,
|
||||
struct share_mode_entry **pp_ex_or_batch,
|
||||
bool *got_level2,
|
||||
@ -962,11 +964,27 @@ static void find_oplock_types(struct share_mode_lock *lck,
|
||||
*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->num_share_modes; i++) {
|
||||
if (!is_valid_share_mode_entry(&lck->share_modes[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lck->share_modes[i].op_type == NO_OPLOCK &&
|
||||
is_stat_open(lck->share_modes[i].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->share_modes[i].op_type)) {
|
||||
/* batch - can only be one. */
|
||||
if (*pp_ex_or_batch || *pp_batch || *got_level2 || *got_no_oplock) {
|
||||
@ -1906,7 +1924,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
|
||||
}
|
||||
|
||||
/* Get the types we need to examine. */
|
||||
find_oplock_types(lck,
|
||||
find_oplock_types(fsp,
|
||||
oplock_request,
|
||||
lck,
|
||||
&batch_entry,
|
||||
&exclusive_entry,
|
||||
&got_level2_oplock,
|
||||
@ -2151,7 +2171,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
|
||||
}
|
||||
|
||||
/* Get the types we need to examine. */
|
||||
find_oplock_types(lck,
|
||||
find_oplock_types(fsp,
|
||||
oplock_request,
|
||||
lck,
|
||||
&batch_entry,
|
||||
&exclusive_entry,
|
||||
&got_level2_oplock,
|
||||
|
Loading…
Reference in New Issue
Block a user