[pve-devel] [RFC PATCH common] Implement refcounting for flocks

Fabian Grünbichler f.gruenbichler at proxmox.com
Wed Feb 10 08:25:23 CET 2016


This was already implemented in PVE::LXC::lock_aquire() and
lock_release(). Enabling refcounting in the general
PVE::Tools::lock_file() and lock_file_full() methods allows
us to use one code base for flocking.

Furthermore, we could get rid of various xx_no_lock methods
that were required because the old non-refcounting version
did not support nested flocks (the inner most flock would
close the file handle and thus release the flock).
---
A manual code review found no issues regarding nesting, and the refcounting
code is already used by the LXC codebase.

This should allow the LXC codebase to drop lock_aquire and lock_release, and
is a first step towards moving a lot of the duplicated config file handling
code in the LXC and Qemu codebases into pve-common.

 src/PVE/Tools.pm | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm
index 9f08aa6..60ba8aa 100644
--- a/src/PVE/Tools.pm
+++ b/src/PVE/Tools.pm
@@ -126,15 +126,16 @@ sub lock_file_full {
 
     my $lock_func = sub {
         if (!$lock_handles->{$$}->{$filename}) {
-            $lock_handles->{$$}->{$filename} = new IO::File (">>$filename") ||
-                die "can't open file - $!\n";
+	    my $fh = new IO::File(">>$filename") ||
+		die "can't open file - $!\n";
+	    $lock_handles->{$$}->{$filename} = { fh => $fh, refcount => 0};
         }
 
-        if (!flock ($lock_handles->{$$}->{$filename}, $mode|LOCK_NB)) {
+        if (!flock($lock_handles->{$$}->{$filename}->{fh}, $mode|LOCK_NB)) {
             print STDERR "trying to acquire lock...";
 	    my $success;
 	    while(1) {
-		$success = flock($lock_handles->{$$}->{$filename}, $mode);
+		$success = flock($lock_handles->{$$}->{$filename}->{fh}, $mode);
 		# try again on EINTR (see bug #273)
 		if ($success || ($! != EINTR)) {
 		    last;
@@ -146,6 +147,7 @@ sub lock_file_full {
             }
             print STDERR " OK\n";
         }
+	$lock_handles->{$$}->{$filename}->{refcount}++;
     };
 
     my $res;
@@ -159,9 +161,12 @@ sub lock_file_full {
 	$err = $@;
     }
 
-    if (my $fh = $lock_handles->{$$}->{$filename}) {
-        $lock_handles->{$$}->{$filename} = undef;
-        close ($fh);
+    if (my $fh = $lock_handles->{$$}->{$filename}->{fh}) {
+	my $refcount = --$lock_handles->{$$}->{$filename}->{refcount};
+	if ($refcount <= 0) {
+	    $lock_handles->{$$}->{$filename} = undef;
+	    close ($fh);
+	}
     }
 
     if ($err) {
-- 
2.1.4





More information about the pve-devel mailing list