[SCM] Samba Shared Repository - branch v4-1-test updated
Karolin Seeger
kseeger at samba.org
Thu Sep 26 11:34:05 CEST 2013
The branch, v4-1-test has been updated
via fd1583b torture3: Trigger a nasty cleanup bug in smbd
via 3a5ae0c smbd: Fix flawed share_mode_stale_pid API
via 9cfc001 smbd: Rename parameter "i" to "idx"
via 252a2bc smbd: Don't store in-memory only flags in locking.tdb
via 1706214 smbd: Simplify find_oplock_types
from 4182c97 python-samba-tool fsmo: Do not give an error on a successful role transfer
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v4-1-test
- Log -----------------------------------------------------------------
commit fd1583b3ce6d2275696e833f967e66f412367d5f
Author: Volker Lendecke <vl at samba.org>
Date: Sun Sep 1 18:54:59 2013 +0200
torture3: Trigger a nasty cleanup bug in smbd
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
Autobuild-User(master): Michael Adam <obnox at samba.org>
Autobuild-Date(master): Tue Sep 3 19:13:14 CEST 2013 on sn-devel-104
(cherry picked from commit ade8477f98fcffcc6e3c5ea31618b49d0c1bba95)
The last 5 patches address bug #10138 - smbd doesn't always clean up share modes
after hard crash.
Autobuild-User(v4-1-test): Karolin Seeger <kseeger at samba.org>
Autobuild-Date(v4-1-test): Thu Sep 26 11:33:29 CEST 2013 on sn-devel-104
commit 3a5ae0c11c4234950e6080a3b71f3d66db06edac
Author: Volker Lendecke <vl at samba.org>
Date: Fri Aug 30 12:49:43 2013 +0000
smbd: Fix flawed share_mode_stale_pid API
The comment for this routine said:
> Modifies d->num_share_modes, watch out in routines iterating over
> that array.
Well, it turns out that *every* caller of this API got it wrong. So I
think it's better to change the routine.
This leaves the array untouched while iterating but filters out the
deleted ones while saving them back to disk.
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
(cherry picked from commit 7d91ffc6fdc3b371564e14f09822a96264ea372a)
commit 9cfc00190882aea1915a721af2abbd07784ce6a7
Author: Volker Lendecke <vl at samba.org>
Date: Fri Aug 30 12:27:36 2013 +0000
smbd: Rename parameter "i" to "idx"
We'll need "i" in a later checkin ... :-)
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
(cherry picked from commit 5006db98aaf1efe119f1da8be091587a9bc2b952)
commit 252a2bc946de82697e49a015c60daf2fc5dee485
Author: Volker Lendecke <vl at samba.org>
Date: Sun Sep 1 11:07:19 2013 +0200
smbd: Don't store in-memory only flags in locking.tdb
Hey, pidl knows the [skip] attribute ... :-)
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
(cherry picked from commit 696bc569b17f024f840774e3d59761229836a310)
commit 17062140cc2977dc0877890928b25b798de3cacc
Author: Volker Lendecke <vl at samba.org>
Date: Thu Aug 22 08:49:07 2013 +0000
smbd: Simplify find_oplock_types
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
(cherry picked from commit 94b320527eee0c7ba1d3818816e7d59cb863bf3f)
-----------------------------------------------------------------------
Summary of changes:
source3/librpc/idl/open_files.idl | 10 ++++-
source3/locking/locking.c | 47 +++++++++++++++++--------
source3/locking/proto.h | 2 +-
source3/locking/share_mode_lock.c | 24 +++++++++++++
source3/selftest/tests.py | 1 +
source3/smbd/open.c | 19 +++++-----
source3/torture/proto.h | 1 +
source3/torture/test_cleanup.c | 70 +++++++++++++++++++++++++++++++++++++
source3/torture/torture.c | 1 +
9 files changed, 148 insertions(+), 27 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/librpc/idl/open_files.idl b/source3/librpc/idl/open_files.idl
index fa87bc7..686bc02 100644
--- a/source3/librpc/idl/open_files.idl
+++ b/source3/librpc/idl/open_files.idl
@@ -23,6 +23,12 @@ interface open_files
uint32 uid;
uint16 flags;
uint32 name_hash;
+
+ /*
+ * In-memory flag indicating a non-existing pid. We don't want
+ * to store this share_mode_entry on disk.
+ */
+ [skip] boolean8 stale;
} share_mode_entry;
typedef [public] struct {
@@ -42,8 +48,8 @@ interface open_files
[size_is(num_delete_tokens)] delete_token delete_tokens[];
timespec old_write_time;
timespec changed_write_time;
- uint8 fresh;
- uint8 modified;
+ [skip] boolean8 fresh;
+ [skip] boolean8 modified;
[ignore] db_record *record;
} share_mode_data;
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 7e65616..5090082 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -617,6 +617,10 @@ bool is_valid_share_mode_entry(const struct share_mode_entry *e)
{
int num_props = 0;
+ if (e->stale) {
+ return false;
+ }
+
num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
@@ -630,40 +634,53 @@ bool is_valid_share_mode_entry(const struct share_mode_entry *e)
/*
* In case d->share_modes[i] conflicts with something or otherwise is
* being used, we need to make sure the corresponding process still
- * exists. This routine checks it and potentially removes the entry
- * from d->share_modes. Modifies d->num_share_modes, watch out in
- * routines iterating over that array.
+ * exists.
*/
-bool share_mode_stale_pid(struct share_mode_data *d, unsigned i)
+bool share_mode_stale_pid(struct share_mode_data *d, unsigned idx)
{
struct share_mode_entry *e;
- if (i > d->num_share_modes) {
+ if (idx > d->num_share_modes) {
DEBUG(1, ("Asking for index %u, only %u around\n",
- i, (unsigned)d->num_share_modes));
+ idx, (unsigned)d->num_share_modes));
return false;
}
- e = &d->share_modes[i];
+ e = &d->share_modes[idx];
if (serverid_exists(&e->pid)) {
DEBUG(10, ("PID %s (index %u out of %u) still exists\n",
- procid_str_static(&e->pid), i,
+ procid_str_static(&e->pid), idx,
(unsigned)d->num_share_modes));
return false;
}
DEBUG(10, ("PID %s (index %u out of %u) does not exist anymore\n",
- procid_str_static(&e->pid), i,
+ procid_str_static(&e->pid), idx,
(unsigned)d->num_share_modes));
- *e = d->share_modes[d->num_share_modes-1];
- d->num_share_modes -= 1;
- if (d->num_share_modes == 0 &&
- d->num_delete_tokens) {
+ e->stale = true;
+
+ if (d->num_delete_tokens != 0) {
+ uint32_t i, num_stale;
+
/*
* We cannot have any delete tokens
* if there are no valid share modes.
*/
- TALLOC_FREE(d->delete_tokens);
- d->num_delete_tokens = 0;
+
+ num_stale = 0;
+
+ for (i=0; i<d->num_share_modes; i++) {
+ if (d->share_modes[i].stale) {
+ num_stale += 1;
+ }
+ }
+
+ if (num_stale == d->num_share_modes) {
+ /*
+ * No non-stale share mode found
+ */
+ TALLOC_FREE(d->delete_tokens);
+ d->num_delete_tokens = 0;
+ }
}
d->modified = true;
diff --git a/source3/locking/proto.h b/source3/locking/proto.h
index adb30b7..93fbea5 100644
--- a/source3/locking/proto.h
+++ b/source3/locking/proto.h
@@ -170,7 +170,7 @@ void get_file_infos(struct file_id id,
bool *delete_on_close,
struct timespec *write_time);
bool is_valid_share_mode_entry(const struct share_mode_entry *e);
-bool share_mode_stale_pid(struct share_mode_data *d, unsigned i);
+bool share_mode_stale_pid(struct share_mode_data *d, unsigned idx);
void set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
uid_t uid, uint64_t mid, uint16 op_type);
bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp);
diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c
index 0693cf5..342f910 100644
--- a/source3/locking/share_mode_lock.c
+++ b/source3/locking/share_mode_lock.c
@@ -121,6 +121,7 @@ static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx,
{
struct share_mode_data *d;
enum ndr_err_code ndr_err;
+ uint32_t i;
DATA_BLOB blob;
d = talloc(mem_ctx, struct share_mode_data);
@@ -140,6 +141,14 @@ static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx,
goto fail;
}
+ /*
+ * Initialize the values that are [skip] in the idl. The NDR code does
+ * not initialize them.
+ */
+
+ for (i=0; i<d->num_share_modes; i++) {
+ d->share_modes[i].stale = false;
+ }
d->modified = false;
d->fresh = false;
@@ -162,12 +171,27 @@ static TDB_DATA unparse_share_modes(struct share_mode_data *d)
{
DATA_BLOB blob;
enum ndr_err_code ndr_err;
+ uint32_t i;
if (DEBUGLEVEL >= 10) {
DEBUG(10, ("unparse_share_modes:\n"));
NDR_PRINT_DEBUG(share_mode_data, d);
}
+ i = 0;
+ while (i < d->num_share_modes) {
+ if (d->share_modes[i].stale) {
+ /*
+ * Remove the stale entries before storing
+ */
+ struct share_mode_entry *m = d->share_modes;
+ m[i] = m[d->num_share_modes-1];
+ d->num_share_modes -= 1;
+ } else {
+ i += 1;
+ }
+ }
+
if (d->num_share_modes == 0) {
DEBUG(10, ("No used share mode found\n"));
return make_tdb_data(NULL, 0);
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 3fc6684..e5ae63e 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -63,6 +63,7 @@ tests = ["FDPASS", "LOCK1", "LOCK2", "LOCK3", "LOCK4", "LOCK5", "LOCK6", "LOCK7"
"SMB2-SESSION-REAUTH", "SMB2-SESSION-RECONNECT",
"CLEANUP1",
"CLEANUP2",
+ "CLEANUP4",
"BAD-NBT-SESSION"]
for t in tests:
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index dcf6bb5..10b04e7 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1251,19 +1251,20 @@ static void find_oplock_types(files_struct *fsp,
}
for (i=0; i<lck->data->num_share_modes; i++) {
- if (!is_valid_share_mode_entry(&lck->data->share_modes[i])) {
+ struct share_mode_entry *e = &lck->data->share_modes[i];
+
+ if (!is_valid_share_mode_entry(e)) {
continue;
}
- if (lck->data->share_modes[i].op_type == NO_OPLOCK &&
- is_stat_open(lck->data->share_modes[i].access_mask)) {
+ if (e->op_type == NO_OPLOCK && is_stat_open(e->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->data->share_modes[i].op_type)) {
+ if (BATCH_OPLOCK_TYPE(e->op_type)) {
/* batch - can only be one. */
if (share_mode_stale_pid(lck->data, i)) {
DEBUG(10, ("Found stale batch oplock\n"));
@@ -1272,10 +1273,10 @@ static void find_oplock_types(files_struct *fsp,
if (*pp_ex_or_batch || *pp_batch || *got_level2 || *got_no_oplock) {
smb_panic("Bad batch oplock entry.");
}
- *pp_batch = &lck->data->share_modes[i];
+ *pp_batch = e;
}
- if (EXCLUSIVE_OPLOCK_TYPE(lck->data->share_modes[i].op_type)) {
+ if (EXCLUSIVE_OPLOCK_TYPE(e->op_type)) {
if (share_mode_stale_pid(lck->data, i)) {
DEBUG(10, ("Found stale duplicate oplock\n"));
continue;
@@ -1284,10 +1285,10 @@ static void find_oplock_types(files_struct *fsp,
if (*pp_ex_or_batch || *got_level2 || *got_no_oplock) {
smb_panic("Bad exclusive or batch oplock entry.");
}
- *pp_ex_or_batch = &lck->data->share_modes[i];
+ *pp_ex_or_batch = e;
}
- if (LEVEL_II_OPLOCK_TYPE(lck->data->share_modes[i].op_type)) {
+ if (LEVEL_II_OPLOCK_TYPE(e->op_type)) {
if (*pp_batch || *pp_ex_or_batch) {
if (share_mode_stale_pid(lck->data, i)) {
DEBUG(10, ("Found stale LevelII "
@@ -1299,7 +1300,7 @@ static void find_oplock_types(files_struct *fsp,
*got_level2 = true;
}
- if (lck->data->share_modes[i].op_type == NO_OPLOCK) {
+ if (e->op_type == NO_OPLOCK) {
if (*pp_batch || *pp_ex_or_batch) {
if (share_mode_stale_pid(lck->data, i)) {
DEBUG(10, ("Found stale NO_OPLOCK "
diff --git a/source3/torture/proto.h b/source3/torture/proto.h
index 4f4c9e2..c9fc2c5 100644
--- a/source3/torture/proto.h
+++ b/source3/torture/proto.h
@@ -104,6 +104,7 @@ bool run_local_sprintf_append(int dummy);
bool run_cleanup1(int dummy);
bool run_cleanup2(int dummy);
bool run_cleanup3(int dummy);
+bool run_cleanup4(int dummy);
bool run_ctdb_conn(int dummy);
bool run_msg_test(int dummy);
bool run_notify_bench2(int dummy);
diff --git a/source3/torture/test_cleanup.c b/source3/torture/test_cleanup.c
index d9dce40..319a55f 100644
--- a/source3/torture/test_cleanup.c
+++ b/source3/torture/test_cleanup.c
@@ -329,3 +329,73 @@ bool run_cleanup3(int dummy)
return true;
}
+
+bool run_cleanup4(int dummy)
+{
+ struct cli_state *cli1, *cli2;
+ const char *fname = "\\cleanup4";
+ uint16_t fnum1, fnum2;
+ NTSTATUS status;
+
+ printf("CLEANUP4: Checking that a conflicting share mode is cleaned "
+ "up\n");
+
+ if (!torture_open_connection(&cli1, 0)) {
+ return false;
+ }
+ if (!torture_open_connection(&cli2, 0)) {
+ return false;
+ }
+
+ status = cli_ntcreate(
+ cli1, fname, 0,
+ FILE_GENERIC_READ|DELETE_ACCESS,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ|FILE_SHARE_DELETE,
+ FILE_OVERWRITE_IF, 0, 0, &fnum1);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("creating file failed: %s\n",
+ nt_errstr(status));
+ return false;
+ }
+
+ status = cli_ntcreate(
+ cli2, fname, 0,
+ FILE_GENERIC_READ|DELETE_ACCESS,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ|FILE_SHARE_DELETE,
+ FILE_OPEN, 0, 0, &fnum2);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("opening file 1st time failed: %s\n",
+ nt_errstr(status));
+ return false;
+ }
+
+ status = smbXcli_conn_samba_suicide(cli1->conn, 1);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("smbXcli_conn_samba_suicide failed: %s\n",
+ nt_errstr(status));
+ return false;
+ }
+
+ /*
+ * The next open will conflict with both opens above. The first open
+ * above will be correctly cleaned up. A bug in smbd iterating over
+ * the share mode array made it skip the share conflict check for the
+ * second open. Trigger this bug.
+ */
+
+ status = cli_ntcreate(
+ cli2, fname, 0,
+ FILE_GENERIC_WRITE|DELETE_ACCESS,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ FILE_OPEN, 0, 0, &fnum2);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+ printf("opening file 2nd time returned: %s\n",
+ nt_errstr(status));
+ return false;
+ }
+
+ return true;
+}
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index c6c5322..ee51a4d 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -9509,6 +9509,7 @@ static struct {
{ "CLEANUP1", run_cleanup1 },
{ "CLEANUP2", run_cleanup2 },
{ "CLEANUP3", run_cleanup3 },
+ { "CLEANUP4", run_cleanup4 },
{ "LOCAL-SUBSTITUTE", run_local_substitute, 0},
{ "LOCAL-GENCACHE", run_local_gencache, 0},
{ "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
--
Samba Shared Repository
More information about the samba-cvs
mailing list