[SCM] Samba Shared Repository - branch master updated
Jeremy Allison
jra at samba.org
Tue Nov 11 16:04:11 MST 2014
The branch, master has been updated
via 2d44498 s3:smb2_break: First test for NT_STATUS_INVALID_OPLOCK_PROTOCOL, then for in_oplock_level being reasonable
via 837e290 s3:locking: convert brl_have_read field to brl_num_read.
via 1020c59 s3:smbd: Don't set fsp->oplock_type before we've granted any oplocks.
via a08b0e7 s3:smbd: move all oplock granting code to grant_fsp_oplock_type()
via 87a1021 s3:smbd: break oplocks to none with FILE_OVERWRITE
from c2bda5b pdb_tdb: Avoid a nasty error message with ctdb
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 2d44498740d98edd9d09f12d35dc91d8d17e0c62
Author: Volker Lendecke <vl at samba.org>
Date: Tue Sep 23 18:49:46 2014 +0200
s3:smb2_break: First test for NT_STATUS_INVALID_OPLOCK_PROTOCOL, then for in_oplock_level being reasonable
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Autobuild-User(master): Jeremy Allison <jra at samba.org>
Autobuild-Date(master): Wed Nov 12 00:03:34 CET 2014 on sn-devel-104
commit 837e29035c911f3509135252c3f423d0f56b606d
Author: Volker Lendecke <vl at samba.org>
Date: Tue Oct 28 15:27:09 2014 -0700
s3:locking: convert brl_have_read field to brl_num_read.
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
commit 1020c5942a996e3e900e2b81f9964dd61fc9c71d
Author: Jeremy Allison <jra at samba.org>
Date: Wed Oct 22 17:53:01 2014 -0700
s3:smbd: Don't set fsp->oplock_type before we've granted any oplocks.
It's not needed, and may lead to unexpected side effects.
grant_fsp_oplock_type() is the only place to touch this.
Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
commit a08b0e78220f84f87b2af1535d645a994a5c93ab
Author: Volker Lendecke <vl at samba.org>
Date: Tue Oct 28 15:27:09 2014 -0700
s3:smbd: move all oplock granting code to grant_fsp_oplock_type()
Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
Pair-Programmed-With: Jeremy Allison <jra at samba.org>
Signed-off-by: Volker Lendecke <vl at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Jeremy Allison <jra at samba.org>
commit 87a102189bf2d87e39dd1762fff92465aa7be5ec
Author: Volker Lendecke <vl at samba.org>
Date: Tue Sep 23 23:34:14 2014 +0200
s3:smbd: break oplocks to none with FILE_OVERWRITE
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
-----------------------------------------------------------------------
Summary of changes:
source3/locking/brlock.c | 123 +++++++++++++++++++++-------------------------
source3/locking/proto.h | 6 +--
source3/smbd/open.c | 86 +++++++++++++++++---------------
source3/smbd/oplock.c | 115 ++++++++++++++++++++++++++-----------------
source3/smbd/proto.h | 2 +
source3/smbd/smb2_break.c | 22 ++++-----
6 files changed, 188 insertions(+), 166 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index 0bed9f9..6c73c72 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -47,7 +47,7 @@ struct byte_range_lock {
struct files_struct *fsp;
unsigned int num_locks;
bool modified;
- bool have_read_oplocks;
+ uint32_t num_read_oplocks;
struct lock_struct *lock_data;
struct db_record *record;
};
@@ -82,18 +82,18 @@ struct files_struct *brl_fsp(struct byte_range_lock *brl)
return brl->fsp;
}
-bool brl_have_read_oplocks(const struct byte_range_lock *brl)
+uint32_t brl_num_read_oplocks(const struct byte_range_lock *brl)
{
- return brl->have_read_oplocks;
+ return brl->num_read_oplocks;
}
-void brl_set_have_read_oplocks(struct byte_range_lock *brl,
- bool have_read_oplocks)
+void brl_set_num_read_oplocks(struct byte_range_lock *brl,
+ uint32_t num_read_oplocks)
{
- DEBUG(10, ("Setting have_read_oplocks to %s\n",
- have_read_oplocks ? "true" : "false"));
+ DEBUG(10, ("Setting num_read_oplocks to %"PRIu32"\n",
+ num_read_oplocks));
SMB_ASSERT(brl->record != NULL); /* otherwise we're readonly */
- brl->have_read_oplocks = have_read_oplocks;
+ brl->num_read_oplocks = num_read_oplocks;
brl->modified = true;
}
@@ -1850,7 +1850,6 @@ int brl_forall(void (*fn)(struct file_id id, struct server_id pid,
static void byte_range_lock_flush(struct byte_range_lock *br_lck)
{
- size_t data_len;
unsigned i;
struct lock_struct *locks = br_lck->lock_data;
@@ -1874,15 +1873,7 @@ static void byte_range_lock_flush(struct byte_range_lock *br_lck)
}
}
- data_len = br_lck->num_locks * sizeof(struct lock_struct);
-
- if (br_lck->have_read_oplocks) {
- data_len += 1;
- }
-
- DEBUG(10, ("data_len=%d\n", (int)data_len));
-
- if (data_len == 0) {
+ if ((br_lck->num_locks == 0) && (br_lck->num_read_oplocks == 0)) {
/* No locks - delete this entry. */
NTSTATUS status = dbwrap_record_delete(br_lck->record);
if (!NT_STATUS_IS_OK(status)) {
@@ -1891,19 +1882,20 @@ static void byte_range_lock_flush(struct byte_range_lock *br_lck)
smb_panic("Could not delete byte range lock entry");
}
} else {
+ size_t lock_len, data_len;
TDB_DATA data;
NTSTATUS status;
+ lock_len = br_lck->num_locks * sizeof(struct lock_struct);
+ data_len = lock_len + sizeof(br_lck->num_read_oplocks);
+
data.dsize = data_len;
data.dptr = talloc_array(talloc_tos(), uint8_t, data_len);
SMB_ASSERT(data.dptr != NULL);
- memcpy(data.dptr, br_lck->lock_data,
- br_lck->num_locks * sizeof(struct lock_struct));
-
- if (br_lck->have_read_oplocks) {
- data.dptr[data_len-1] = 1;
- }
+ memcpy(data.dptr, br_lck->lock_data, lock_len);
+ memcpy(data.dptr + lock_len, &br_lck->num_read_oplocks,
+ sizeof(br_lck->num_read_oplocks));
status = dbwrap_record_store(br_lck->record, data, TDB_REPLACE);
TALLOC_FREE(data.dptr);
@@ -1926,6 +1918,32 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck)
return 0;
}
+static bool brl_parse_data(struct byte_range_lock *br_lck, TDB_DATA data)
+{
+ size_t data_len;
+
+ if (data.dsize == 0) {
+ return true;
+ }
+ if (data.dsize % sizeof(struct lock_struct) !=
+ sizeof(br_lck->num_read_oplocks)) {
+ DEBUG(1, ("Invalid data size: %u\n", (unsigned)data.dsize));
+ return false;
+ }
+
+ br_lck->num_locks = data.dsize / sizeof(struct lock_struct);
+ data_len = br_lck->num_locks * sizeof(struct lock_struct);
+
+ br_lck->lock_data = talloc_memdup(br_lck, data.dptr, data_len);
+ if (br_lck->lock_data == NULL) {
+ DEBUG(1, ("talloc_memdup failed\n"));
+ return false;
+ }
+ memcpy(&br_lck->num_read_oplocks, data.dptr + data_len,
+ sizeof(br_lck->num_read_oplocks));
+ return true;
+}
+
/*******************************************************************
Fetch a set of byte range lock data from the database.
Leave the record locked.
@@ -1935,16 +1953,14 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck)
struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp)
{
TDB_DATA key, data;
- struct byte_range_lock *br_lck = talloc(mem_ctx, struct byte_range_lock);
+ struct byte_range_lock *br_lck;
+ br_lck = talloc_zero(mem_ctx, struct byte_range_lock);
if (br_lck == NULL) {
return NULL;
}
br_lck->fsp = fsp;
- br_lck->num_locks = 0;
- br_lck->have_read_oplocks = false;
- br_lck->modified = False;
key.dptr = (uint8 *)&fsp->file_id;
key.dsize = sizeof(struct file_id);
@@ -1959,30 +1975,12 @@ struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp)
data = dbwrap_record_get_value(br_lck->record);
- br_lck->lock_data = NULL;
-
- talloc_set_destructor(br_lck, byte_range_lock_destructor);
-
- br_lck->num_locks = data.dsize / sizeof(struct lock_struct);
-
- if (br_lck->num_locks != 0) {
- br_lck->lock_data = talloc_array(
- br_lck, struct lock_struct, br_lck->num_locks);
- if (br_lck->lock_data == NULL) {
- DEBUG(0, ("malloc failed\n"));
- TALLOC_FREE(br_lck);
- return NULL;
- }
-
- memcpy(br_lck->lock_data, data.dptr,
- talloc_get_size(br_lck->lock_data));
+ if (!brl_parse_data(br_lck, data)) {
+ TALLOC_FREE(br_lck);
+ return NULL;
}
- DEBUG(10, ("data.dsize=%d\n", (int)data.dsize));
-
- if ((data.dsize % sizeof(struct lock_struct)) == 1) {
- br_lck->have_read_oplocks = (data.dptr[data.dsize-1] == 1);
- }
+ talloc_set_destructor(br_lck, byte_range_lock_destructor);
if (DEBUGLEVEL >= 10) {
unsigned int i;
@@ -2008,28 +2006,19 @@ static void brl_get_locks_readonly_parser(TDB_DATA key, TDB_DATA data,
{
struct brl_get_locks_readonly_state *state =
(struct brl_get_locks_readonly_state *)private_data;
- struct byte_range_lock *br_lock;
+ struct byte_range_lock *br_lck;
- br_lock = talloc_pooled_object(
+ br_lck = talloc_pooled_object(
state->mem_ctx, struct byte_range_lock, 1, data.dsize);
- if (br_lock == NULL) {
+ if (br_lck == NULL) {
*state->br_lock = NULL;
return;
}
- br_lock->lock_data = (struct lock_struct *)talloc_memdup(
- br_lock, data.dptr, data.dsize);
- br_lock->num_locks = data.dsize / sizeof(struct lock_struct);
-
- if ((data.dsize % sizeof(struct lock_struct)) == 1) {
- br_lock->have_read_oplocks = (data.dptr[data.dsize-1] == 1);
- } else {
- br_lock->have_read_oplocks = false;
+ if (!brl_parse_data(br_lck, data)) {
+ *state->br_lock = NULL;
+ return;
}
-
- DEBUG(10, ("Got %d bytes, have_read_oplocks: %s\n", (int)data.dsize,
- br_lock->have_read_oplocks ? "true" : "false"));
-
- *state->br_lock = br_lock;
+ *state->br_lock = br_lck;
}
struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp)
@@ -2072,7 +2061,7 @@ struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp)
return NULL;
}
- br_lock->have_read_oplocks = false;
+ br_lock->num_read_oplocks = 0;
br_lock->num_locks = 0;
br_lock->lock_data = NULL;
diff --git a/source3/locking/proto.h b/source3/locking/proto.h
index 44f3ba1..8eccff8 100644
--- a/source3/locking/proto.h
+++ b/source3/locking/proto.h
@@ -30,9 +30,9 @@ void brl_shutdown(void);
unsigned int brl_num_locks(const struct byte_range_lock *brl);
struct files_struct *brl_fsp(struct byte_range_lock *brl);
-bool brl_have_read_oplocks(const struct byte_range_lock *brl);
-void brl_set_have_read_oplocks(struct byte_range_lock *brl,
- bool have_read_oplocks);
+uint32_t brl_num_read_oplocks(const struct byte_range_lock *brl);
+void brl_set_num_read_oplocks(struct byte_range_lock *brl,
+ uint32_t num_read_oplocks);
NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck,
struct lock_struct *plock,
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index ccea1e9..1952823 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1431,6 +1431,7 @@ static bool delay_for_oplock(files_struct *fsp,
switch (create_disposition) {
case FILE_SUPERSEDE:
+ case FILE_OVERWRITE:
case FILE_OVERWRITE_IF:
break_to = NO_OPLOCK;
break;
@@ -1489,38 +1490,37 @@ static bool file_has_brlocks(files_struct *fsp)
return (brl_num_locks(br_lck) > 0);
}
-static void grant_fsp_oplock_type(files_struct *fsp,
- struct share_mode_lock *lck,
- int oplock_request)
+static NTSTATUS grant_fsp_oplock_type(struct smb_request *req,
+ struct files_struct *fsp,
+ struct share_mode_lock *lck,
+ int oplock_request)
{
bool allow_level2 = (global_client_caps & CAP_LEVEL_II_OPLOCKS) &&
lp_level2_oplocks(SNUM(fsp->conn));
bool got_level2_oplock, got_a_none_oplock;
uint32_t i;
+ bool ok;
+ NTSTATUS status;
/* Start by granting what the client asked for,
but ensure no SAMBA_PRIVATE bits can be set. */
fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK);
+ if (fsp->oplock_type == NO_OPLOCK) {
+ goto type_selected;
+ }
+
if (oplock_request & INTERNAL_OPEN_ONLY) {
/* No oplocks on internal open. */
fsp->oplock_type = NO_OPLOCK;
- DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n",
- fsp->oplock_type, fsp_str_dbg(fsp)));
- return;
+ goto type_selected;
}
if (lp_locking(fsp->conn->params) && file_has_brlocks(fsp)) {
DEBUG(10,("grant_fsp_oplock_type: file %s has byte range locks\n",
fsp_str_dbg(fsp)));
fsp->oplock_type = NO_OPLOCK;
- }
-
- if (is_stat_open(fsp->access_mask)) {
- /* Leave the value already set. */
- DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n",
- fsp->oplock_type, fsp_str_dbg(fsp)));
- return;
+ goto type_selected;
}
got_level2_oplock = false;
@@ -1554,23 +1554,35 @@ static void grant_fsp_oplock_type(files_struct *fsp,
*/
if (fsp->oplock_type == LEVEL_II_OPLOCK && !allow_level2) {
fsp->oplock_type = NO_OPLOCK;
+ goto type_selected;
}
- if (fsp->oplock_type == LEVEL_II_OPLOCK && !got_level2_oplock) {
+ type_selected:
+ status = set_file_oplock(fsp);
+ if (!NT_STATUS_IS_OK(status)) {
/*
- * We're the first level2 oplock. Indicate that in brlock.tdb.
+ * Could not get the kernel oplock
*/
- struct byte_range_lock *brl;
+ fsp->oplock_type = NO_OPLOCK;
+ }
- brl = brl_get_locks(talloc_tos(), fsp);
- if (brl != NULL) {
- brl_set_have_read_oplocks(brl, true);
- TALLOC_FREE(brl);
- }
+ ok = set_share_mode(lck, fsp, get_current_uid(fsp->conn),
+ req ? req->mid : 0,
+ fsp->oplock_type);
+ if (!ok) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ok = update_num_read_oplocks(fsp, lck);
+ if (!ok) {
+ del_share_mode(lck, fsp);
+ return NT_STATUS_INTERNAL_ERROR;
}
DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n",
fsp->oplock_type, fsp_str_dbg(fsp)));
+
+ return NT_STATUS_OK;
}
static bool request_timed_out(struct timeval request_time,
@@ -2404,9 +2416,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
* the open is done. */
fsp->posix_open = posix_open;
- /* 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;
}
@@ -2738,8 +2747,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
}
}
- grant_fsp_oplock_type(fsp, lck, oplock_request);
-
/*
* We have the share entry *locked*.....
*/
@@ -2799,9 +2806,18 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
}
if (file_existed) {
- /* stat opens on existing files don't get oplocks. */
+ /*
+ * stat opens on existing files don't get oplocks.
+ *
+ * Note that we check for stat open on the *open_access_mask*,
+ * i.e. the access mask we actually used to do the open,
+ * not the one the client asked for (which is in
+ * fsp->access_mask). This is due to the fact that
+ * FILE_OVERWRITE and FILE_OVERWRITE_IF add in O_TRUNC,
+ * which adds FILE_WRITE_DATA to open_access_mask.
+ */
if (is_stat_open(open_access_mask)) {
- fsp->oplock_type = NO_OPLOCK;
+ oplock_request = NO_OPLOCK;
}
}
@@ -2823,21 +2839,11 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
* Setup the oplock info in both the shared memory and
* file structs.
*/
-
- status = set_file_oplock(fsp);
+ status = grant_fsp_oplock_type(req, fsp, lck, oplock_request);
if (!NT_STATUS_IS_OK(status)) {
- /*
- * Could not get the kernel oplock
- */
- fsp->oplock_type = NO_OPLOCK;
- }
-
- if (!set_share_mode(lck, fsp, get_current_uid(conn),
- req ? req->mid : 0,
- fsp->oplock_type)) {
TALLOC_FREE(lck);
fd_close(fsp);
- return NT_STATUS_NO_MEMORY;
+ return status;
}
/* Handle strange delete on close create semantics. */
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 7935092..aa99f68 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -148,6 +148,53 @@ static void downgrade_file_oplock(files_struct *fsp)
TALLOC_FREE(fsp->oplock_timeout);
}
+bool update_num_read_oplocks(files_struct *fsp, struct share_mode_lock *lck)
+{
+ struct share_mode_data *d = lck->data;
+ struct byte_range_lock *br_lck;
+ uint32_t num_read_oplocks = 0;
+ uint32_t i;
+
+ if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
+ /*
+ * If we're the only one, we don't need a brlock entry
+ */
+ SMB_ASSERT(d->num_share_modes == 1);
+ SMB_ASSERT(EXCLUSIVE_OPLOCK_TYPE(d->share_modes[0].op_type));
+ return true;
+ }
+
+ for (i=0; i<d->num_share_modes; i++) {
+ struct share_mode_entry *e = &d->share_modes[i];
+
+ if (EXCLUSIVE_OPLOCK_TYPE(e->op_type)) {
+ num_read_oplocks += 1;
+ continue;
+ }
+
+ if (LEVEL_II_OPLOCK_TYPE(e->op_type)) {
+ num_read_oplocks += 1;
+ continue;
+ }
+ }
+
+ br_lck = brl_get_locks_readonly(fsp);
+ if (br_lck == NULL) {
+ return false;
+ }
+ if (brl_num_read_oplocks(br_lck) == num_read_oplocks) {
+ return true;
+ }
+
+ br_lck = brl_get_locks(talloc_tos(), fsp);
+ if (br_lck == NULL) {
+ return false;
+ }
+ brl_set_num_read_oplocks(br_lck, num_read_oplocks);
+ TALLOC_FREE(br_lck);
+ return true;
+}
+
/****************************************************************************
Remove a file oplock. Copes with level II and exclusive.
Locks then unlocks the share mode lock. Client can decide to go directly
@@ -170,44 +217,6 @@ bool remove_oplock(files_struct *fsp)
return False;
}
- if (fsp->oplock_type == LEVEL_II_OPLOCK) {
-
- /*
- * If we're the only LEVEL_II holder, we have to remove the
- * have_read_oplocks from the brlock entry
- */
-
- struct share_mode_data *data = lck->data;
- uint32_t i, num_level2;
-
- num_level2 = 0;
- for (i=0; i<data->num_share_modes; i++) {
- if (data->share_modes[i].op_type == LEVEL_II_OPLOCK) {
- num_level2 += 1;
- }
- if (num_level2 > 1) {
- /*
- * No need to count them all...
- */
- break;
- }
- }
-
- if (num_level2 == 1) {
- /*
- * That's only us. We are dropping that level2 oplock,
- * so remove the brlock flag.
--
Samba Shared Repository
More information about the samba-cvs
mailing list