[SCM] Samba Shared Repository - branch v3-6-test updated

Jeremy Allison jra at samba.org
Fri Aug 13 11:50:27 MDT 2010


The branch, v3-6-test has been updated
       via  5720be0... tdb: workaround starvation problem in locking entire database.
       via  b7ecdd9... Eliminate any chance of a class of "uninitialized auto variable" errors.
      from  5ea7f0e... Fix bug #7617 - smbd coredump due to uninitialized variables in the performance counter code.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test


- Log -----------------------------------------------------------------
commit 5720be02c69109f1a6f5a16ecdeb2d79cc555498
Author: Rusty Russell <rusty at rustcorp.com.au>
Date:   Sat Aug 14 02:13:26 2010 +0930

    tdb: workaround starvation problem in locking entire database.
    
    We saw tdb_lockall() take 71 seconds under heavy load; this is because Linux
    (at least) doesn't prevent new small locks being obtained while we're waiting
    for a big log.
    
    The workaround is to do divide and conquer using non-blocking chainlocks: if
    we get down to a single chain we block.  Using a simple test program where
    children did "hold lock for 100ms, sleep for 1 second" the time to do
    tdb_lockall() dropped signifiantly.  There are ln(hashsize) locks taken in
    the contended case, but that's slow anyway.
    
    More analysis is given in my blog at http://rusty.ozlabs.org/?p=120
    
    This may also help transactions, though in that case it's the initial
    read lock which uses this gradual locking routine; the update-to-write-lock
    code is separate and still tries to update in one go.
    
    Even though ABI doesn't change, minor version bumped so behavior change
    can be easily detected.
    
    Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>
    (cherry picked from commit 11ab43084b10cf53b530cdc3a6036c898b79ca38)

commit b7ecdd9a188c1b06d8244a926d3bd59d5fcfdc29
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Aug 13 10:47:08 2010 -0700

    Eliminate any chance of a class of "uninitialized auto variable" errors.
    
    Jeremy.
    (cherry picked from commit 15d3541c678894adebd3e9c446e3aa1c43148837)

-----------------------------------------------------------------------

Summary of changes:
 lib/tdb/ABI/{tdb-1.2.2.sigs => tdb-1.2.3.sigs} |    0 
 lib/tdb/common/lock.c                          |   86 +++++++++++++++++++-----
 lib/tdb/configure.ac                           |    2 +-
 lib/tdb/wscript                                |    2 +-
 source3/rpc_server/srv_winreg_nt.c             |   50 +++++++-------
 5 files changed, 95 insertions(+), 45 deletions(-)
 copy lib/tdb/ABI/{tdb-1.2.2.sigs => tdb-1.2.3.sigs} (100%)


Changeset truncated at 500 lines:

diff --git a/lib/tdb/ABI/tdb-1.2.2.sigs b/lib/tdb/ABI/tdb-1.2.3.sigs
similarity index 100%
copy from lib/tdb/ABI/tdb-1.2.2.sigs
copy to lib/tdb/ABI/tdb-1.2.3.sigs
diff --git a/lib/tdb/common/lock.c b/lib/tdb/common/lock.c
index 285b7a3..803feee 100644
--- a/lib/tdb/common/lock.c
+++ b/lib/tdb/common/lock.c
@@ -152,14 +152,6 @@ int tdb_brlock(struct tdb_context *tdb,
 		return -1;
 	}
 
-	/* Sanity check */
-	if (tdb->transaction && offset >= lock_offset(-1) && len != 0) {
-		tdb->ecode = TDB_ERR_RDONLY;
-		TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_brlock attempted in transaction at offset %d rw_type=%d flags=%d len=%d\n",
-			 offset, rw_type, flags, (int)len));
-		return -1;
-	}
-
 	do {
 		ret = fcntl_lock(tdb, rw_type, offset, len,
 				 flags & TDB_LOCK_WAIT);
@@ -486,11 +478,9 @@ int tdb_transaction_unlock(struct tdb_context *tdb, int ltype)
 	return tdb_nest_unlock(tdb, TRANSACTION_LOCK, ltype, false);
 }
 
-
-/* lock/unlock entire database.  It can only be upgradable if you have some
- * other way of guaranteeing exclusivity (ie. transaction write lock). */
-int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
-		       enum tdb_lock_flags flags, bool upgradable)
+/* Returns 0 if all done, -1 if error, 1 if ok. */
+static int tdb_allrecord_check(struct tdb_context *tdb, int ltype,
+			       enum tdb_lock_flags flags, bool upgradable)
 {
 	/* There are no locks on read-only dbs */
 	if (tdb->read_only || tdb->traverse_read) {
@@ -520,11 +510,73 @@ int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
 		tdb->ecode = TDB_ERR_LOCK;
 		return -1;
 	}
+	return 1;
+}
 
-	if (tdb_brlock(tdb, ltype, FREELIST_TOP, 0, flags)) {
-		if (flags & TDB_LOCK_WAIT) {
-			TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno)));
-		}
+/* We only need to lock individual bytes, but Linux merges consecutive locks
+ * so we lock in contiguous ranges. */
+static int tdb_chainlock_gradual(struct tdb_context *tdb,
+				 int ltype, enum tdb_lock_flags flags,
+				 size_t off, size_t len)
+{
+	int ret;
+	enum tdb_lock_flags nb_flags = (flags & ~TDB_LOCK_WAIT);
+
+	if (len <= 4) {
+		/* Single record.  Just do blocking lock. */
+		return tdb_brlock(tdb, ltype, off, len, flags);
+	}
+
+	/* First we try non-blocking. */
+	ret = tdb_brlock(tdb, ltype, off, len, nb_flags);
+	if (ret == 0) {
+		return 0;
+	}
+
+	/* Try locking first half, then second. */
+	ret = tdb_chainlock_gradual(tdb, ltype, flags, off, len / 2);
+	if (ret == -1)
+		return -1;
+
+	ret = tdb_chainlock_gradual(tdb, ltype, flags,
+				    off + len / 2, len - len / 2);
+	if (ret == -1) {
+		tdb_brunlock(tdb, ltype, off, len / 2);
+		return -1;
+	}
+	return 0;
+}
+
+/* lock/unlock entire database.  It can only be upgradable if you have some
+ * other way of guaranteeing exclusivity (ie. transaction write lock).
+ * We do the locking gradually to avoid being starved by smaller locks. */
+int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
+		       enum tdb_lock_flags flags, bool upgradable)
+{
+	switch (tdb_allrecord_check(tdb, ltype, flags, upgradable)) {
+	case -1:
+		return -1;
+	case 0:
+		return 0;
+	}
+
+	/* We cover two kinds of locks:
+	 * 1) Normal chain locks.  Taken for almost all operations.
+	 * 3) Individual records locks.  Taken after normal or free
+	 *    chain locks.
+	 *
+	 * It is (1) which cause the starvation problem, so we're only
+	 * gradual for that. */
+	if (tdb_chainlock_gradual(tdb, ltype, flags, FREELIST_TOP,
+				  tdb->header.hash_size * 4) == -1) {
+		return -1;
+	}
+
+	/* Grab individual record locks. */
+	if (tdb_brlock(tdb, ltype, lock_offset(tdb->header.hash_size), 0,
+		       flags) == -1) {
+		tdb_brunlock(tdb, ltype, FREELIST_TOP,
+			     tdb->header.hash_size * 4);
 		return -1;
 	}
 
diff --git a/lib/tdb/configure.ac b/lib/tdb/configure.ac
index 4e36779..2843d98 100644
--- a/lib/tdb/configure.ac
+++ b/lib/tdb/configure.ac
@@ -2,7 +2,7 @@ AC_PREREQ(2.50)
 AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""])
 AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""])
 AC_DEFUN([SMB_ENABLE], [echo -n ""])
-AC_INIT(tdb, 1.2.2)
+AC_INIT(tdb, 1.2.3)
 AC_CONFIG_SRCDIR([common/tdb.c])
 AC_CONFIG_HEADER(include/config.h)
 AC_LIBREPLACE_ALL_CHECKS
diff --git a/lib/tdb/wscript b/lib/tdb/wscript
index a7afa98..2fdd67f 100644
--- a/lib/tdb/wscript
+++ b/lib/tdb/wscript
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 APPNAME = 'tdb'
-VERSION = '1.2.2'
+VERSION = '1.2.3'
 
 blddir = 'bin'
 
diff --git a/source3/rpc_server/srv_winreg_nt.c b/source3/rpc_server/srv_winreg_nt.c
index 568545f..198a84f 100644
--- a/source3/rpc_server/srv_winreg_nt.c
+++ b/source3/rpc_server/srv_winreg_nt.c
@@ -403,7 +403,7 @@ WERROR _winreg_GetVersion(struct pipes_struct *p,
 WERROR _winreg_EnumKey(struct pipes_struct *p,
 		       struct winreg_EnumKey *r)
 {
-	WERROR err;
+	WERROR err = WERR_OK;
 	struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
 
 	if ( !key )
@@ -430,10 +430,10 @@ WERROR _winreg_EnumKey(struct pipes_struct *p,
 WERROR _winreg_EnumValue(struct pipes_struct *p,
 			 struct winreg_EnumValue *r)
 {
-	WERROR err;
+	WERROR err = WERR_OK;
 	struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
-	char *valname;
-	struct registry_value *val;
+	char *valname = NULL;
+	struct registry_value *val = NULL;
 
 	if ( !key )
 		return WERR_BADFID;
@@ -519,8 +519,8 @@ WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
 	fstring str_reason;
 	fstring do_reboot;
 	fstring f;
-	int ret;
-	bool can_shutdown;
+	int ret = -1;
+	bool can_shutdown = false;
 
  	shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
 	if (!shutdown_script) {
@@ -605,11 +605,9 @@ WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
 WERROR _winreg_AbortSystemShutdown(struct pipes_struct *p,
 				   struct winreg_AbortSystemShutdown *r)
 {
-	const char *abort_shutdown_script;
-	int ret;
-	bool can_shutdown;
-
-	abort_shutdown_script = lp_abort_shutdown_script();
+	const char *abort_shutdown_script = lp_abort_shutdown_script();
+	int ret = -1;
+	bool can_shutdown = false;
 
 	if (!*abort_shutdown_script)
 		return WERR_ACCESS_DENIED;
@@ -643,7 +641,7 @@ static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
 	char *p = NULL;
 	int num_services = lp_numservices();
 	int snum = -1;
-	const char *share_path;
+	const char *share_path = NULL;
 	char *fname = *pp_fname;
 
 	/* convert to a unix path, stripping the C:\ along the way */
@@ -684,7 +682,7 @@ WERROR _winreg_RestoreKey(struct pipes_struct *p,
 {
 	struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
 	char *fname = NULL;
-	int             snum;
+	int snum = -1;
 
 	if ( !regkey )
 		return WERR_BADFID;
@@ -770,8 +768,8 @@ WERROR _winreg_CreateKey(struct pipes_struct *p,
 			 struct winreg_CreateKey *r)
 {
 	struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
-	struct registry_key *new_key;
-	WERROR result;
+	struct registry_key *new_key = NULL;
+	WERROR result = WERR_OK;
 
 	if ( !parent )
 		return WERR_BADFID;
@@ -801,7 +799,7 @@ WERROR _winreg_SetValue(struct pipes_struct *p,
 			struct winreg_SetValue *r)
 {
 	struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
-	struct registry_value *val;
+	struct registry_value *val = NULL;
 
 	if ( !key )
 		return WERR_BADFID;
@@ -859,10 +857,10 @@ WERROR _winreg_GetKeySecurity(struct pipes_struct *p,
 			      struct winreg_GetKeySecurity *r)
 {
 	struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
-	WERROR err;
-	struct security_descriptor *secdesc;
-	uint8 *data;
-	size_t len;
+	WERROR err = WERR_OK;
+	struct security_descriptor *secdesc = NULL;
+	uint8 *data = NULL;
+	size_t len = 0;
 
 	if ( !key )
 		return WERR_BADFID;
@@ -903,8 +901,8 @@ WERROR _winreg_SetKeySecurity(struct pipes_struct *p,
 			      struct winreg_SetKeySecurity *r)
 {
 	struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
-	struct security_descriptor *secdesc;
-	WERROR err;
+	struct security_descriptor *secdesc = NULL;
+	WERROR err = WERR_OK;
 
 	if ( !key )
 		return WERR_BADFID;
@@ -996,7 +994,7 @@ WERROR _winreg_QueryMultipleValues(struct pipes_struct *p,
 				   struct winreg_QueryMultipleValues *r)
 {
 	struct winreg_QueryMultipleValues2 r2;
-	uint32_t needed;
+	uint32_t needed = 0;
 
 	r2.in.key_handle	= r->in.key_handle;
 	r2.in.values_in		= r->in.values_in;
@@ -1049,9 +1047,9 @@ WERROR _winreg_QueryMultipleValues2(struct pipes_struct *p,
 	struct registry_value *vals = NULL;
 	const char **names = NULL;
 	uint32_t offset = 0, num_vals = 0;
-	DATA_BLOB result;
-	int i;
-	WERROR err;
+	DATA_BLOB result = data_blob_null;
+	int i = 0;
+	WERROR err = WERR_OK;
 
 	if (!regkey) {
 		return WERR_BADFID;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list