summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/include/smb.h9
-rw-r--r--source3/smbd/open.c33
-rw-r--r--source3/smbd/oplock.c1
-rw-r--r--source3/smbd/trans2.c4
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) {