[pve-devel] r5471 - in pve-cluster/trunk/data: . perl src

svn-commits at proxmox.com svn-commits at proxmox.com
Tue Feb 1 12:10:45 CET 2011


Author: dietmar
Date: 2011-02-01 12:10:45 +0100 (Tue, 01 Feb 2011)
New Revision: 5471

Modified:
   pve-cluster/trunk/data/ChangeLog
   pve-cluster/trunk/data/perl/Cluster.pm
   pve-cluster/trunk/data/src/cfs-plug-memdb.c
   pve-cluster/trunk/data/src/dcdb.c
   pve-cluster/trunk/data/src/memdb.c
   pve-cluster/trunk/data/src/memdb.h
Log:
fix lock implementation


Modified: pve-cluster/trunk/data/ChangeLog
===================================================================
--- pve-cluster/trunk/data/ChangeLog	2011-02-01 07:53:24 UTC (rev 5470)
+++ pve-cluster/trunk/data/ChangeLog	2011-02-01 11:10:45 UTC (rev 5471)
@@ -1,3 +1,7 @@
+2011-02-01  Proxmox Support Team  <support at proxmox.com>
+
+	* perl/Cluster.pm (cfs_lock_file): first try.
+
 2011-01-31  Proxmox Support Team  <support at proxmox.com>
 
 	* src/dcdb.c (dcdb_deliver): implement a simple distributed lock

Modified: pve-cluster/trunk/data/perl/Cluster.pm
===================================================================
--- pve-cluster/trunk/data/perl/Cluster.pm	2011-02-01 07:53:24 UTC (rev 5470)
+++ pve-cluster/trunk/data/perl/Cluster.pm	2011-02-01 11:10:45 UTC (rev 5471)
@@ -21,7 +21,7 @@
 
 use Data::Dumper; # fixme: remove
 
-my $lockdir = "/var/lock/pve-manager";
+my $lockdir = "/etc/pve/priv/lock";
 mkdir $lockdir;
 
 # x509 certificate utils
@@ -492,17 +492,74 @@
     PVE::Tools::file_set_contents($fsname, $raw);
 }
 
+my $cfs_lock = sub {
+    my ($lockid, $timeout, $text, $code, @param) = @_;
+
+    my $res;
+
+    # fixed timeout: cfs locks have a timeout of 120
+    # using 60 gives us another 60 seconds to abort the task
+
+    $timeout = 10 if !$timeout;
+
+    my $filename = "$lockdir/$lockid";
+    
+    eval {
+
+        local $SIG{ALRM} = sub { die "can't aquire lock for $text '$lockid': got timeout\n"; };
+
+        alarm ($timeout);
+
+	if (!(mkdir $filename)) {
+	    print STDERR "trying to aquire cfs lock '$lockid' ...";
+ 	    while (1) {
+		if (!(mkdir $filename)) {
+		    (utime 0, 0, $filename); # cfs unlock request
+		} else {
+		    print STDERR " OK\n";
+ 		    last;
+		}
+		sleep(1);
+	    }
+	}
+	
+	# fixed timeout: cfs locks have a timeout of 120
+	# using 60 gives us another 60 seconds to abort the task
+	alarm(60);
+	local $SIG{ALRM} = sub { die "got lock timeout - aborting command\n"; };
+
+	$res = &$code(@param);
+
+	alarm(0);
+    };
+
+    my $err = $@;
+
+    alarm(0);
+
+    if (!$err || $err !~ /^got lock timeout -/) {
+	rmdir $filename; # cfs unlock
+    }
+
+    if ($err) {
+        $@ = $err;
+        return undef;
+    }
+
+    $@ = undef;
+
+    return $res;
+};
+
 sub cfs_lock_file {
     my ($filename, $timeout, $text, $code, @param) = @_;
 
-    my $info = $file_info->{$filename} || die "unknown file '$filename'";
+    my $info = $observed->{$filename} || die "unknown file '$filename'";
 
-    my $lockid = $filename;
+    my $lockid = "file-$filename";
     $lockid =~ s/[.\/]/_/g;
 
-    # fimxe: do cluster wide lock instead
-
-    PVE::Tools::lock_file("$lockdir/.lock-file-$lockid", $timeout, $text, $code, @param);
+    &$cfs_lock($lockid, $timeout, $text, $code, @param);
 }
 
 my $log_levels = {

Modified: pve-cluster/trunk/data/src/cfs-plug-memdb.c
===================================================================
--- pve-cluster/trunk/data/src/cfs-plug-memdb.c	2011-02-01 07:53:24 UTC (rev 5470)
+++ pve-cluster/trunk/data/src/cfs-plug-memdb.c	2011-02-01 11:10:45 UTC (rev 5471)
@@ -369,6 +369,7 @@
 	uint32_t mtime = tv[1].tv_sec;
 
 	gboolean unlock_req = FALSE;
+	guchar csum[32];
 
 	if (te && mtime == 0 && te->type == DT_DIR &&
 	    path_is_lockdir(path)) {
@@ -376,7 +377,6 @@
 	}
 
 	if (mdb->dfsm) {
-		guchar csum[32];
 		if (unlock_req && memdb_tree_entry_csum(te, csum))
 			dcdb_send_unlock(mdb->dfsm, path, csum, TRUE);
 	    
@@ -384,7 +384,8 @@
 					     NULL, NULL, 0, mtime, 0);
 	} else {
 		uint32_t ctime = time(NULL);
-		if (unlock_req && memdb_lock_expired(mdb->memdb, path)) {
+		if (unlock_req && memdb_tree_entry_csum(te, csum) &&
+		    memdb_lock_expired(mdb->memdb, path, csum)) {
 			res = memdb_delete(mdb->memdb, path, 0, ctime);
 		} else {
 			res = memdb_mtime(mdb->memdb, path, 0, mtime);

Modified: pve-cluster/trunk/data/src/dcdb.c
===================================================================
--- pve-cluster/trunk/data/src/dcdb.c	2011-02-01 07:53:24 UTC (rev 5470)
+++ pve-cluster/trunk/data/src/dcdb.c	2011-02-01 11:10:45 UTC (rev 5471)
@@ -836,7 +836,7 @@
 
 				cfs_debug("got valid unlock request message");
 			
-				if (memdb_lock_expired(memdb, path)) {
+				if (memdb_lock_expired(memdb, path, csum)) {
 					cfs_debug("sending unlock message");
 					dcdb_send_unlock(dfsm, path, csum, FALSE);
 				}

Modified: pve-cluster/trunk/data/src/memdb.c
===================================================================
--- pve-cluster/trunk/data/src/memdb.c	2011-02-01 07:53:24 UTC (rev 5470)
+++ pve-cluster/trunk/data/src/memdb.c	2011-02-01 11:10:45 UTC (rev 5471)
@@ -339,25 +339,35 @@
 	return ret;
 }
 
+
 gboolean
 memdb_lock_expired(
 	memdb_t *memdb,
-	const char *path)
+	const char *path,
+	const guchar csum[32])
 {
 	g_return_val_if_fail(memdb != NULL, FALSE);
 	g_return_val_if_fail(memdb->locks != NULL, FALSE);
 	g_return_val_if_fail(path != NULL, FALSE);
+	g_return_val_if_fail(csum != NULL, FALSE);
 
 	memdb_lock_info_t *li;
 	uint32_t ctime = time(NULL);
 
 	if ((li = g_hash_table_lookup(memdb->locks, path))) {
+		if (memcmp(csum, li->csum, 32) != 0) {
+			li->ltime = ctime;
+			memcpy(li->csum, csum, 32);
+			g_critical("wrong lock csum - reset timeout");
+			return FALSE;
+		}
 		if ((ctime > li->ltime) && ((ctime - li->ltime) > CFS_LOCK_TIMEOUT))
 			return TRUE;
 	} else {
 		li = g_new0(memdb_lock_info_t, 1);
 		li->path = g_strdup(path);
 		li->ltime = ctime;
+		memcpy(li->csum, csum, 32);
 		g_hash_table_replace(memdb->locks, li->path, li);
 	}
 
@@ -398,13 +408,20 @@
 		li = g_new0(memdb_lock_info_t, 1);
 		li->path = g_strdup_printf("priv/lock/%s", lock_te->name);
 
-		memdb_lock_info_t *oldli;
-		if ((oldli = g_hash_table_lookup(memdb->locks, lock_te->name))) {
-			li->ltime = oldli->ltime;
+		guchar csum[32];
+		if (memdb_tree_entry_csum(lock_te, csum)) {
+			memcpy(li->csum, csum, 32);
+			memdb_lock_info_t *oldli;
+			if ((oldli = g_hash_table_lookup(memdb->locks, lock_te->name)) &&
+			    (memcmp(csum, oldli->csum, 32) == 0)) {
+				li->ltime = oldli->ltime;
+			} else {
+				li->ltime = time(NULL);
+			}
+			g_hash_table_insert(memdb->locks, li->path, li);
 		} else {
-			li->ltime = time(NULL);
+			memdb_lock_info_free(li);
 		}
-		g_hash_table_insert(memdb->locks, li->path, li);
 	}
 
 	if (old)
@@ -608,7 +625,10 @@
 
 	if (strcmp(dirname, "priv/lock") == 0) {
 		g_hash_table_remove(memdb->locks, path);
-		memdb_lock_expired(memdb, path); // insert a new entry
+		guchar csum[32];
+		if (memdb_tree_entry_csum(te, csum)) {
+			memdb_lock_expired(memdb, path, csum); // insert a new entry
+		}
 	}
 
 	ret = 0;

Modified: pve-cluster/trunk/data/src/memdb.h
===================================================================
--- pve-cluster/trunk/data/src/memdb.h	2011-02-01 07:53:24 UTC (rev 5470)
+++ pve-cluster/trunk/data/src/memdb.h	2011-02-01 11:10:45 UTC (rev 5471)
@@ -71,6 +71,7 @@
 typedef struct {
 	char *path;
 	guint32 ltime;
+	guchar csum[32];
 } memdb_lock_info_t;
 
 typedef struct {
@@ -98,7 +99,8 @@
 gboolean
 memdb_lock_expired(
 	memdb_t *memdb,
-	const char *path);
+	const char *path,
+	const guchar csum[32]);
 
 void
 memdb_update_locks(memdb_t *memdb);



More information about the pve-devel mailing list