diff options
author | Jeremy Allison <jra@samba.org> | 2006-05-30 18:17:37 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:17:14 -0500 |
commit | 7361c7a883646dd065eabf81e0b1dc60cc9d1f39 (patch) | |
tree | c355c3da953c8b21b79bd5b579550d7d1e1c090b /source3 | |
parent | bef4969247da237e7b50fd2abd207de92e9bc980 (diff) | |
download | samba-7361c7a883646dd065eabf81e0b1dc60cc9d1f39.tar.gz samba-7361c7a883646dd065eabf81e0b1dc60cc9d1f39.tar.bz2 samba-7361c7a883646dd065eabf81e0b1dc60cc9d1f39.zip |
r15958: Make us pass RAW-OPLOCK with kernel oplocks off.
This allows a requestor to set FORCE_OPLOCK_BREAK_TO_NONE
to ensure we don't break to level 2. Fixed a couple
of resource leaks in error paths in open_file_ntcreatex.
Jeremy.
(This used to be commit c7c9adcce7f13d01445f31b07fb28a76f0a1d6df)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/smb.h | 9 | ||||
-rw-r--r-- | source3/smbd/open.c | 33 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 1 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 4 |
4 files changed, 31 insertions, 16 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h index f06c551cc0..41ffce1a15 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1541,18 +1541,25 @@ extern int chain_size; /* * Bits we test with. + * Note these must fit into 16-bits. */ - + #define NO_OPLOCK 0 #define EXCLUSIVE_OPLOCK 1 #define BATCH_OPLOCK 2 #define LEVEL_II_OPLOCK 4 + +/* The following are Samba-private. */ #define INTERNAL_OPEN_ONLY 8 #define FAKE_LEVEL_II_OPLOCK 16 /* Client requested no_oplock, but we have to * inform potential level2 holders on * write. */ #define DEFERRED_OPEN_ENTRY 32 #define UNUSED_SHARE_MODE_ENTRY 64 +#define FORCE_OPLOCK_BREAK_TO_NONE 128 + +/* None of the following should ever appear in fsp->oplock_request. */ +#define SAMBA_PRIVATE_OPLOCK_MASK (INTERNAL_OPEN_ONLY|DEFERRED_OPEN_ENTRY|UNUSED_SHARE_MODE_ENTRY|FORCE_OPLOCK_BREAK_TO_NONE) #define EXCLUSIVE_OPLOCK_TYPE(lck) ((lck) & ((unsigned int)EXCLUSIVE_OPLOCK|(unsigned int)BATCH_OPLOCK)) #define BATCH_OPLOCK_TYPE(lck) ((lck) & (unsigned int)BATCH_OPLOCK) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5b615f01e2..042d41453e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -611,7 +611,7 @@ static BOOL is_delete_request(files_struct *fsp) { static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, int pass_number, - BOOL internal_only_open) + int oplock_request) { int i; struct share_mode_entry *exclusive = NULL; @@ -619,7 +619,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, BOOL delay_it = False; BOOL have_level2 = False; - if (internal_only_open || is_stat_open(fsp->access_mask)) { + if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) { fsp->oplock_type = NO_OPLOCK; return False; } @@ -686,8 +686,16 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, procid_str_static(&exclusive->pid))); exclusive->op_mid = get_current_mid(); + /* Create the message. */ share_mode_entry_to_message(msg, exclusive); + /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We don't + want this set in the share mode struct pointed to by lck. */ + + if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) { + SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); + } + become_root(); ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); @@ -1090,7 +1098,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, int flags2=0; BOOL file_existed = VALID_STAT(*psbuf); BOOL def_acl = False; - BOOL internal_only_open = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; BOOL fsp_open = False; @@ -1133,11 +1140,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, create_disposition, create_options, unx_mode, oplock_request)); - if (oplock_request == INTERNAL_OPEN_ONLY) { - internal_only_open = True; - oplock_request = 0; - } - if ((pml = get_open_deferred_message(mid)) != NULL) { struct deferred_open_record *state = (struct deferred_open_record *)pml->private_data.data; @@ -1174,7 +1176,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* ignore any oplock requests if oplocks are disabled */ if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break || IS_VETO_OPLOCK_PATH(conn, fname)) { - oplock_request = 0; + /* Mask off everything except the private Samba bits. */ + oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK; } /* this is for OS/2 long file names - say we don't support them */ @@ -1349,7 +1352,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, fsp->share_access = share_access; fsp->fh->private_options = create_options; fsp->access_mask = access_mask; - fsp->oplock_type = oplock_request; + /* Ensure no SAMBA_PRIVATE bits can be set. */ + fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); if (timeval_is_zero(&request_time)) { request_time = fsp->open_time; @@ -1364,15 +1368,17 @@ files_struct *open_file_ntcreate(connection_struct *conn, fname); if (lck == NULL) { + file_free_fsp(fsp); DEBUG(0, ("Could not get share mode lock\n")); set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); return NULL; } /* First pass - send break only on batch oplocks. */ - if (delay_for_oplocks(lck, fsp, 1, internal_only_open)) { + if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); + file_free_fsp(fsp); return NULL; } @@ -1383,9 +1389,10 @@ files_struct *open_file_ntcreate(connection_struct *conn, 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 (delay_for_oplocks(lck, fsp, 2, internal_only_open)) { + if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); + file_free_fsp(fsp); return NULL; } } @@ -1459,7 +1466,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, * cope with the braindead 1 second delay. */ - if (!internal_only_open && + if (!(oplock_request & INTERNAL_OPEN_ONLY) && lp_defer_sharing_violations()) { struct timeval timeout; struct deferred_open_record state; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 42c64a2843..1f731e1729 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -540,6 +540,7 @@ static void process_oplock_break_message(int msg_type, struct process_id src, } if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) && + !(msg.op_type & FORCE_OPLOCK_BREAK_TO_NONE) && !koplocks && /* NOTE: we force levelII off for kernel oplocks - * this will change when it is supported */ lp_level2_oplocks(SNUM(fsp->conn))) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a033833d00..eda4837ba4 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4024,7 +4024,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, - NO_OPLOCK, + FORCE_OPLOCK_BREAK_TO_NONE, NULL); if (new_fsp == NULL) { @@ -4667,7 +4667,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", FILE_OPEN, 0, FILE_ATTRIBUTE_NORMAL, - NO_OPLOCK, + FORCE_OPLOCK_BREAK_TO_NONE, NULL); if (new_fsp == NULL) { |