summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2006-03-21 06:53:49 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:15:39 -0500
commit5067cca077ab8dde110f79ea9e60611dc25ddf64 (patch)
treec105e7aa1400abfb67c3773f0047c34971a20758
parent97ee5b1afa342eea40f973f5370c9f620c63bd01 (diff)
downloadsamba-5067cca077ab8dde110f79ea9e60611dc25ddf64.tar.gz
samba-5067cca077ab8dde110f79ea9e60611dc25ddf64.tar.bz2
samba-5067cca077ab8dde110f79ea9e60611dc25ddf64.zip
r14602: Fix another logic bug in new oplock handling. Just
because lck->num_share_modes != 0 doesn't mean that there *are* other valid share modes. They may be all marked "UNUSED" or be deferred open entries. In that case don't downgrade the granted oplock to level2 needlessly - a client can have an exclusive oplock in this case. The original code handled this correctly in the lck->num_share_modes == 0 case but not in the case where there were no valid share modes but lck->num_share_modes != 0. I'll clean up my Samba4 torture tester for this and commit it tomorrow. Jeremy. (This used to be commit 306061c93d9181262298516fefd83444f5a65ce5)
-rw-r--r--source3/smbd/open.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 0cf8b68c28..5de03b8dd7 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -612,6 +612,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp)
{
int i;
struct share_mode_entry *exclusive = NULL;
+ BOOL valid_entry = False;
BOOL delay_it = False;
BOOL have_level2 = False;
@@ -620,33 +621,36 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp)
return False;
}
- if (lck->num_share_modes == 0) {
- /* No files open at all: Directly grant whatever the client
- * wants. */
-
- if (fsp->oplock_type == NO_OPLOCK) {
- /* Store a level2 oplock, but don't tell the client */
- fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
- }
- return False;
- }
-
for (i=0; i<lck->num_share_modes; i++) {
if (!is_valid_share_mode_entry(&lck->share_modes[i])) {
continue;
}
+ /* At least one entry is not an invalid or deferred entry. */
+ valid_entry = True;
+
if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
SMB_ASSERT(exclusive == NULL);
exclusive = &lck->share_modes[i];
}
if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) {
+ SMB_ASSERT(exclusive == NULL);
have_level2 = True;
}
}
+ if (!valid_entry) {
+ /* All entries are placeholders or deferred.
+ * Directly grant whatever the client wants. */
+ if (fsp->oplock_type == NO_OPLOCK) {
+ /* Store a level2 oplock, but don't tell the client */
+ fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
+ }
+ return False;
+ }
+
if (exclusive != NULL) { /* Found an exclusive oplock */
SMB_ASSERT(!have_level2);
delay_it = is_delete_request(fsp) ?
@@ -654,7 +658,8 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp)
}
if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
- /* We can at most grant level2 */
+ /* We can at most grant level2 as there are other
+ * level2 or NO_OPLOCK entries. */
fsp->oplock_type = LEVEL_II_OPLOCK;
}