[SCM] CTDB repository - branch master updated - ctdb-1.0.114-141-gf62c7e4

Ronnie Sahlberg sahlberg at samba.org
Fri Jun 4 23:46:08 MDT 2010


The branch, master has been updated
       via  f62c7e44dc303f274bbc1dd59fad2167e72a2af0 (commit)
       via  463a266205f145cd9c4c36b9c59d3747eeef0e2e (commit)
      from  8fec60cb92d26886d853c918b8bc7931fec46469 (commit)

http://gitweb.samba.org/?p=sahlberg/ctdb.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit f62c7e44dc303f274bbc1dd59fad2167e72a2af0
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Sat Jun 5 15:43:01 2010 +1000

    In ctdb_writerecord()
    Verify that the lock is still held and refuse the write otherwise.
    
    We have to guarantee that we dont write to an unlocked record.
    
    If we write to a record after it has been released, the record may have
    already migrated off the node, in which case we get a DMASTER split brain for this record. (These application bugs are incredibly hard to track down)

commit 463a266205f145cd9c4c36b9c59d3747eeef0e2e
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Sat Jun 5 15:38:11 2010 +1000

    Split ctdb_release_lock() into a function to release the locvk and another function to free the data structures.
    This allows us to keep the datastructure valid after the lock has been released by the application and we can trap and warn when the application is accessing the lock after it has been released. I.e. application bugs.

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

Summary of changes:
 include/ctdb.h |    3 +++
 libctdb/ctdb.c |   29 +++++++++++++++++++++++++++--
 libctdb/tst.c  |    4 +++-
 3 files changed, 33 insertions(+), 3 deletions(-)


Changeset truncated at 500 lines:

diff --git a/include/ctdb.h b/include/ctdb.h
index e62bb45..0dc5da7 100644
--- a/include/ctdb.h
+++ b/include/ctdb.h
@@ -214,6 +214,9 @@ struct ctdb_db *ctdb_attachdb_recv(struct ctdb_connection *ctdb,
  *
  * You MUST NOT block during holding this lock and MUST release it
  * quickly by performing ctdb_release_lock(lock).
+ * Do NOT make any system calls that may block while holding the lock.
+ *
+ * Try to release the lock as quickly as possible.
  */
 struct ctdb_lock;
 
diff --git a/libctdb/ctdb.c b/libctdb/ctdb.c
index 9d79f6e..b7f1c59 100644
--- a/libctdb/ctdb.c
+++ b/libctdb/ctdb.c
@@ -642,10 +642,26 @@ void ctdb_release_lock(struct ctdb_lock *lock)
 		lock->held = false;
 		remove_lock(lock->ctdb_db->ctdb, lock);
 	}
+}
+
+static void ctdb_free_lock(struct ctdb_lock *lock)
+{
+	if (lock->held) {
+		errno = EEXIST;
+		DEBUG(lock->ctdb_db->ctdb, LOG_ERR,
+			"Lock freed before it was released");
+		ctdb_release_lock(lock);
+	}
 	free(lock->hdr);
 	free(lock);
 }
 
+static void ctdb_destroy_lock(struct ctdb_lock *lock)
+{
+	ctdb_release_lock(lock);
+	ctdb_free_lock(lock);
+}
+
 /* We keep the lock if local node is the dmaster. */
 static bool try_readrecordlock(struct ctdb_lock *lock, TDB_DATA *data)
 {
@@ -676,7 +692,7 @@ static bool try_readrecordlock(struct ctdb_lock *lock, TDB_DATA *data)
 static void destroy_lock(struct ctdb_connection *ctdb,
 			 struct ctdb_request *req)
 {
-	ctdb_release_lock(req->extra);
+	ctdb_destroy_lock(req->extra);
 }
 
 static void readrecordlock_retry(struct ctdb_connection *ctdb,
@@ -704,6 +720,7 @@ static void readrecordlock_retry(struct ctdb_connection *ctdb,
 		/* Now it's their responsibility to free lock & request! */
 		req->extra_destructor = NULL;
 		lock->callback(lock->ctdb_db, lock, data, private);
+		ctdb_free_lock(lock);
 		return;
 	}
 
@@ -743,6 +760,7 @@ ctdb_readrecordlock_async(struct ctdb_db *ctdb_db, TDB_DATA key,
 	/* Fast path. */
 	if (try_readrecordlock(lock, &data)) {
 		callback(ctdb_db, lock, data, cbdata);
+		ctdb_free_lock(lock);
 		return true;
 	}
 
@@ -752,7 +770,7 @@ ctdb_readrecordlock_async(struct ctdb_db *ctdb_db, TDB_DATA key,
 	if (!req) {
 		DEBUG(ctdb_db->ctdb, LOG_ERR,
 		      "ctdb_readrecordlock_async: allocation failed");
-		ctdb_release_lock(lock);
+		ctdb_destroy_lock(lock);
 		return NULL;
 	}
 	req->extra = lock;
@@ -776,6 +794,13 @@ ctdb_readrecordlock_async(struct ctdb_db *ctdb_db, TDB_DATA key,
 
 int ctdb_writerecord(struct ctdb_lock *lock, TDB_DATA data)
 {
+	if (!lock->held) {
+		errno = EBADF;
+		DEBUG(lock->ctdb_db->ctdb, LOG_ERR,
+		      "ctdb_writerecord: Can not write. Lock has been released.");
+		return -1;
+	}
+		
 	if (lock->ctdb_db->persistent) {
 		errno = EINVAL;
 		DEBUG(lock->ctdb_db->ctdb, LOG_ERR,
diff --git a/libctdb/tst.c b/libctdb/tst.c
index c8c08cf..391e92c 100644
--- a/libctdb/tst.c
+++ b/libctdb/tst.c
@@ -109,9 +109,11 @@ static void rrl_cb(struct ctdb_db *ctdb_db,
 	data.dsize = strlen(tmp) + 1;
 	ctdb_writerecord(lock, data);
 
+	/* Release the lock as quickly as possible */
+	ctdb_release_lock(lock);
+
 	printf("Wrote new record : %s\n", tmp);
 
-	ctdb_release_lock(lock);
 }
 
 static bool registered = false;


-- 
CTDB repository


More information about the samba-cvs mailing list