svn commit: samba r21140 - in branches/SAMBA_4_0/source/cluster/ctdb: .

tridge at samba.org tridge at samba.org
Mon Feb 5 03:23:46 GMT 2007


Author: tridge
Date: 2007-02-05 03:23:45 +0000 (Mon, 05 Feb 2007)
New Revision: 21140

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=21140

Log:

enable the pending lock notify code in the ctdb backend so that timed
locks retry immediately when another blocking lock is removed.

Modified:
   branches/SAMBA_4_0/source/cluster/ctdb/brlock_ctdb.c


Changeset:
Modified: branches/SAMBA_4_0/source/cluster/ctdb/brlock_ctdb.c
===================================================================
--- branches/SAMBA_4_0/source/cluster/ctdb/brlock_ctdb.c	2007-02-05 03:04:01 UTC (rev 21139)
+++ branches/SAMBA_4_0/source/cluster/ctdb/brlock_ctdb.c	2007-02-05 03:23:45 UTC (rev 21140)
@@ -31,8 +31,6 @@
 #include "ntvfs/common/brlock.h"
 #include "include/ctdb.h"
 
-#define ENABLE_NOTIFIES 0
-
 enum my_functions {FUNC_BRL_LOCK=1, FUNC_BRL_UNLOCK=2, 
 		   FUNC_BRL_REMOVE_PENDING=3, FUNC_BRL_LOCKTEST=4,
 		   FUNC_BRL_CLOSE=5};
@@ -296,26 +294,19 @@
 	struct lock_struct lock, *locks=NULL;
 	NTSTATUS status = NT_STATUS_OK;
 
-#if ENABLE_NOTIFIES
 	/* if this is a pending lock, then with the chainlock held we
 	   try to get the real lock. If we succeed then we don't need
 	   to make it pending. This prevents a possible race condition
 	   where the pending lock gets created after the lock that is
 	   preventing the real lock gets removed */
-	if (lock_type >= PENDING_READ_LOCK) {
-		enum brl_type rw = (lock_type==PENDING_READ_LOCK? READ_LOCK : WRITE_LOCK);
-
-		/* here we need to force that the last_lock isn't overwritten */
-		lock = brlh->last_lock;
-		status = brl_ctdb_lock(brl, brlh, smbpid, start, size, rw, NULL);
-		brlh->last_lock = lock;
-
-		if (NT_STATUS_IS_OK(status)) {
-			tdb_chainunlock(brl->w->tdb, kbuf);
-			return NT_STATUS_OK;
+	if (req->lock_type >= PENDING_READ_LOCK) {
+		enum brl_type lock_type = req->lock_type;
+		req->lock_type = (req->lock_type==PENDING_READ_LOCK? READ_LOCK : WRITE_LOCK);
+		if (brl_ctdb_lock_func(call) == 0 && call->status == NT_STATUS_V(NT_STATUS_OK)) {
+			return 0;
 		}
+		req->lock_type = lock_type;
 	}
-#endif
 
 	dbuf = call->record_data;
 
@@ -383,6 +374,7 @@
 	struct ctdb_lock_req req;
 	struct ctdb_call call;
 	int ret;
+	NTSTATUS status;
 
 	call.call_id = FUNC_BRL_LOCK;
 	call.key.dptr = brlh->key.data;
@@ -405,18 +397,35 @@
 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
 	}
 
-	return NT_STATUS(call.status);
+	status = NT_STATUS(call.status);
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
+		struct lock_struct lock;
+		lock.context.smbpid = smbpid;
+		lock.context.server = brl->server;
+		lock.context.ctx = brl;
+		lock.ntvfs = brlh->ntvfs;
+		lock.start = start;
+		lock.size = size;
+		lock.lock_type = lock_type;
+		lock.notify_ptr = notify_ptr;
+		status = brl_ctdb_lock_failed(brlh, &lock);
+	}
+
+	return status;
 }
 
-#if ENABLE_NOTIFIES
 /*
-  we are removing a lock that might be holding up a pending lock. Scan for pending
-  locks that cover this range and if we find any then notify the server that it should
-  retry the lock
+  we are removing a lock that might be holding up a pending lock. Scan
+  for pending locks that cover this range and if we find any then
+  notify the server that it should retry the lock. In this backend, we
+  notify by sending the list of locks that need to be notified on back
+  in the reply_data of the ctdb call. The caller then does the
+  messaging for us. 
 */
-static void brl_ctdb_notify_unlock(struct brl_context *brl,
-			      struct lock_struct *locks, int count, 
-			      struct lock_struct *removed_lock)
+static int brl_ctdb_notify_unlock(struct ctdb_call_info *call,
+				  struct lock_struct *locks, int count, 
+				   struct lock_struct *removed_lock)
 {
 	int i, last_notice;
 
@@ -429,36 +438,68 @@
 	for (i=0;i<count;i++) {
 		if (locks[i].lock_type >= PENDING_READ_LOCK &&
 		    brl_ctdb_overlap(&locks[i], removed_lock)) {
+			struct lock_struct *nlocks;
+			int ncount;
+
 			if (last_notice != -1 && brl_ctdb_overlap(&locks[i], &locks[last_notice])) {
 				continue;
 			}
 			if (locks[i].lock_type == PENDING_WRITE_LOCK) {
 				last_notice = i;
 			}
-			messaging_send_ptr(brl->messaging_ctx, locks[i].context.server, 
-					   MSG_BRL_RETRY, locks[i].notify_ptr);
+			if (call->reply_data == NULL) {
+				call->reply_data = talloc_zero(call, TDB_DATA);
+				if (call->reply_data == NULL) {
+					return CTDB_ERR_NOMEM;
+				}
+			}
+			/* add to the list of pending locks to notify caller of */
+			ncount = call->reply_data->dsize / sizeof(struct lock_struct);
+			nlocks = talloc_realloc(call->reply_data, call->reply_data->dptr, 
+						struct lock_struct, ncount + 1);
+			if (nlocks == NULL) {
+				return CTDB_ERR_NOMEM;
+			}
+			call->reply_data->dptr = (uint8_t *)nlocks;
+			nlocks[ncount] = locks[i];
+			call->reply_data->dsize += sizeof(struct lock_struct);
 		}
 	}
+
+	return 0;
 }
-#endif
 
 /*
   send notifications for all pending locks - the file is being closed by this
   user
 */
-static void brl_ctdb_notify_all(struct brl_context *brl,
-			   struct lock_struct *locks, int count)
+static int brl_ctdb_notify_all(struct ctdb_call_info *call,
+				struct lock_struct *locks, int count)
 {
 	int i;
 	for (i=0;i<count;i++) {
 		if (locks->lock_type >= PENDING_READ_LOCK) {
-#if ENABLE_NOTIFIES
-			brl_ctdb_notify_unlock(brl, locks, count, &locks[i]);
-#endif
+			int ret = brl_ctdb_notify_unlock(call, locks, count, &locks[i]);
+			if (ret != 0) return ret;
 		}
 	}
+	return 0;
 }
 
+/*
+  send off any messages needed to notify of pending locks that should now retry
+*/
+static void brl_ctdb_notify_send(struct brl_context *brl, TDB_DATA *reply_data)
+{
+	struct lock_struct *locks = (struct lock_struct *)reply_data->dptr;
+	int i, count = reply_data->dsize / sizeof(struct lock_struct);
+	for (i=0;i<count;i++) {
+		messaging_send_ptr(brl->messaging_ctx, locks[i].context.server, 
+				   MSG_BRL_RETRY, locks[i].notify_ptr);
+	}
+}
+
+
 struct ctdb_unlock_req {
 	uint16_t smbpid;
 	uint64_t start;
@@ -515,9 +556,7 @@
 
 found:
 	if (i < count) {
-#if ENABLE_NOTIFIES
 		struct lock_struct removed_lock = *lock;
-#endif
 
 		call->new_data = talloc(call, TDB_DATA);
 		if (call->new_data == NULL) {
@@ -535,9 +574,8 @@
 		       (count-(i+1))*sizeof(*lock));
 		
 		if (count > 1) {
-#if ENABLE_NOTIFIES
-			brl_ctdb_notify_unlock(req->brl, locks, count, &removed_lock);
-#endif
+			int ret = brl_ctdb_notify_unlock(call, locks, count, &removed_lock);
+			if (ret != 0) return ret;
 		}
 	}
 
@@ -584,6 +622,8 @@
 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
 	}
 
+	brl_ctdb_notify_send(brl, &call.reply_data);
+
 	return NT_STATUS(call.status);
 }
 
@@ -808,6 +848,8 @@
 		if (call->new_data == NULL) {
 			return CTDB_ERR_NOMEM;
 		}
+
+		brl_ctdb_notify_all(call, locks, count);
 		
 		call->new_data->dptr = talloc_size(call, count*sizeof(struct lock_struct));
 		if (call->new_data->dptr == NULL) {
@@ -850,6 +892,8 @@
 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
 	}
 
+	brl_ctdb_notify_send(brl, &call.reply_data);
+
 	return NT_STATUS(call.status);
 }
 



More information about the samba-cvs mailing list