[pve-devel] [PATCH 09/09] Improve performance when fetching list of zvols

mir at datanom.net mir at datanom.net
Sun Aug 25 01:29:48 CEST 2013


From: Michael Rasmussen <mir at datanom.net>

Signed-off-by: Michael Rasmussen <mir at datanom.net>
---
 PVE/Storage/ZFSPlugin.pm | 151 ++++++++++++++++++-----------------------------
 1 file changed, 57 insertions(+), 94 deletions(-)

diff --git a/PVE/Storage/ZFSPlugin.pm b/PVE/Storage/ZFSPlugin.pm
index e2404e4..60858c9 100644
--- a/PVE/Storage/ZFSPlugin.pm
+++ b/PVE/Storage/ZFSPlugin.pm
@@ -7,6 +7,7 @@ use POSIX;
 use PVE::Tools qw(run_command file_read_firstline trim dir_glob_regex dir_glob_foreach);
 use PVE::Storage::Plugin;
 use PVE::JSONSchema qw(get_standard_option);
+use Digest::MD5 qw(md5_hex);
 
 use base qw(PVE::Storage::Plugin);
 
@@ -50,6 +51,12 @@ sub zfs_request {
 	}
 	if ($luncmd->{$method}) {
 		$cmd = [@ssh_cmd, $target, $luncmd->{cmd}, $luncmd->{$method}, @params];
+	} elsif ($method =~ /^sbdadm-list$/) {
+		$cmd = '';
+		foreach (@ssh_cmd) {
+			$cmd = "$cmd $_";
+		}
+		$cmd .= " $target /usr/sbin/sbdadm list-lu | grep -w $params[0]";
 	} else {
 		if ($method =~ /^zpool-list$/) {
 			$zfs = 'zpool';
@@ -157,53 +164,10 @@ sub zfs_parse_zvol_list {
 	return $list;
 }
 
-sub zfs_parse_lu_list {
-    my ($text) = @_;
-    my @list = ();
-    my $lun;
-
-    return undef if !$text || $text eq '';
-
-    my @lines = split /\n/, $text;
-
-    foreach my $line (@lines) {
-        if ($line =~ /^\s*LU Name\s*:\s*([a-zA-Z0-9]+)$/) {
-			$lun = ();
-			$lun->{lun} = $1;
-        }
-        elsif ($line =~ /^\s*Data File\s*:\s*([a-zA-Z0-9\-\/]+)$/) {
-			$lun->{source} = $1;
-        }
-        elsif ($line =~ /^\s*Size\s*:\s*([a-zA-Z0-9]+)$/) {
-			$lun->{size} = $1;
-			push (@list, $lun);
-        }
-    }
-
-    return \@list;
-}
-
-sub zfs_get_lu_info {
-    my ($list, $source) = @_;
-    my @lu_list = ();
-
-    return \@lu_list if (!$source || !$list);
-    
-    foreach my $lun (@$list) {
-    	push (@lu_list, $lun) if $lun->{source} =~ /^$source$/;
-    }
-    
-    return \@lu_list;
-}
- 
-sub zfs_list_lun_mapping_entries {
-    my ($scfg, $zvol) = @_;
-    my $object;
-
-    my $text = zfs_request($scfg, 'list_lu', '-v');
-    my $list = zfs_parse_lu_list($text);
-	return undef if (! defined($list));
-  
+sub zfs_get_lu_name {
+	my ($scfg, $zvol) = @_;
+	my $object;
+	
     if ($zvol =~ /^.+\/.+/) {
         $object = "/dev/zvol/rdsk/$zvol";
     }
@@ -211,7 +175,10 @@ sub zfs_list_lun_mapping_entries {
         $object = "/dev/zvol/rdsk/$scfg->{pool}/$zvol";
     }
 
-    return zfs_get_lu_info($list, $object);
+    my $lun = zfs_request($scfg, 'sbdadm-list', $object);
+	$lun =~ /^(\w+)\s+.*$/;
+	
+	return ($1) ? $1 : undef;
 }
 
 sub zfs_get_zvol_size {
@@ -224,27 +191,36 @@ sub zfs_get_zvol_size {
 }
 
 sub zfs_add_lun_mapping_entry {
-    my ($scfg, $zvol) = @_;
-    
-    my $luns = zfs_list_lun_mapping_entries($scfg, $zvol);
-	die "Could not find any LUN's" if (! defined($luns));
-
-    zfs_request($scfg, 'add_view', @$luns[0]->{lun});
+    my ($scfg, $zvol, $lun) = @_;
+	
+	if (! defined($lun)) {
+    	$lun = zfs_get_lu_name($scfg, $zvol);
+		die "Could not find any LUN's" if (! defined($lun));
+	}
+	
+    zfs_request($scfg, 'add_view', $lun);
 }
 
 sub zfs_delete_lu {
     my ($scfg, $zvol) = @_;
 
-    my $luns = zfs_list_lun_mapping_entries($scfg, $zvol);
-	die "Could not find any LUN's" if (! defined($luns));
+    my $lun = zfs_get_lu_name($scfg, $zvol);
+	die "Could not find any LUN's" if (! defined($lun));
 
-    zfs_request($scfg, 'delete_lu', @$luns[0]->{lun});
+    zfs_request($scfg, 'delete_lu', $lun);
 }
 
 sub zfs_create_lu {
     my ($scfg, $zvol) = @_;
-
-    zfs_request($scfg, 'create_lu', "/dev/zvol/rdsk/$scfg->{pool}/$zvol");
+	my $prefix = '600144f';
+	
+	my $digest = md5_hex($zvol);
+	$digest =~ /(\w{7}(.*))/;
+	my $guid = "$prefix$2";
+	
+    zfs_request($scfg, 'create_lu', '-p', 'wcd=false', '-p', "guid=$guid", "/dev/zvol/rdsk/$scfg->{pool}/$zvol");
+	
+	return $guid;
 }
 
 sub zfs_import_lu {
@@ -256,10 +232,10 @@ sub zfs_import_lu {
 sub zfs_resize_lu {
 	my ($scfg, $zvol, $size) = @_;
 
-	my $luns = zfs_list_lun_mapping_entries($scfg, $zvol);
-	die "Could not find any LUN's" if (! defined($luns));
+	my $lun = zfs_get_lu_name($scfg, $zvol);
+	die "Could not find any LUN's" if (! defined($lun));
 
-	zfs_request($scfg, 'modify_lu', '-s', "${size}K", @$luns[0]->{lun});
+	zfs_request($scfg, 'modify_lu', '-s', "${size}K", $lun);
 }
 
 sub zfs_create_zvol {
@@ -279,9 +255,10 @@ sub zfs_get_lun_number {
 	my ($scfg, $name) = @_;
 	my $lunnum = undef;
 	
+	return undef unless defined($name);
+
 	my $text = zfs_request($scfg, 'list_view', '-l', $name);
 	my @lines = split /\n/, $text;
-
     foreach my $line (@lines) {
         if ($line =~ /^\s*LUN\s*:\s*(\d+)$/) {
 			$lunnum = $1;
@@ -292,20 +269,6 @@ sub zfs_get_lun_number {
 	return $lunnum;
 }
 
-sub zfs_get_lun_number_from_name {
-	my ($scfg, $list, $name) = @_;
-	my $lun;
-
-	my $path = "/dev/zvol/rdsk/$scfg->{pool}/$name";
-    	foreach my $info (@$list) {
-    		if ($info->{source} =~ /^$path$/) {
-			$lun = $info->{lun};
-			last;
-		}
-    	}
-	return zfs_get_lun_number($scfg, $lun);
-}
-
 sub zfs_list_zvol {
     my ($scfg) = @_;
     my $text;
@@ -314,9 +277,6 @@ sub zfs_list_zvol {
     my $zvols = zfs_parse_zvol_list($text);
     return undef if !$zvols;
 
-    $text = zfs_request($scfg, 'list_lu', '-v');
-    my $luns = zfs_parse_lu_list($text);
-
     my $list = ();
     foreach my $zvol (@$zvols) {
 		my @values = split('/', $zvol->{name});
@@ -336,7 +296,11 @@ sub zfs_list_zvol {
 			$parent = $1;
 		}
 
-		my $lun = zfs_get_lun_number_from_name($scfg, $luns, $image);
+		my $lu_name = zfs_get_lu_name($scfg, $image);
+		next unless defined($lu_name);
+		my $lun = zfs_get_lun_number($scfg, $lu_name);
+		next unless defined($lun);
+		
 		$list->{$pool}->{$image} = {
 			name => $image,
 			size => $zvol->{size},
@@ -429,9 +393,9 @@ sub path {
     if ($images && $images->{$scfg->{pool}}->{$name}) {
 		$lun = $images->{$scfg->{pool}}->{$name}->{lun};
     } else {
-		my $map = zfs_list_lun_mapping_entries($scfg, $name);
-		die "could not find lun number" if !$map;
-		$lun = zfs_get_lun_number($scfg, @$map[0]->{lun});
+    	my $lu_name = zfs_get_lu_name($scfg, $name);
+    	die "could not find lun number" if !$lu_name;
+    	$lun = zfs_get_lun_number($scfg, $lu_name);
     }
     die "lun is not OK\n" if (! defined($lun));
 
@@ -486,8 +450,8 @@ sub create_base {
     zfs_delete_lu($scfg, $name);
     zfs_request($scfg, 'rename', "$scfg->{pool}/$name", "$scfg->{pool}/$newname");
 
-    zfs_create_lu($scfg, $newname);
-    zfs_add_lun_mapping_entry($scfg, $newname);
+    my $guid = zfs_create_lu($scfg, $newname);
+    zfs_add_lun_mapping_entry($scfg, $newname, $guid);
 
     my $running  = undef; #fixme : is create_base always offline ?
 
@@ -512,8 +476,8 @@ sub clone_image {
 
     zfs_request($scfg, 'clone', "$scfg->{pool}/$basename\@$snap", "$scfg->{pool}/$name");
 
-    zfs_create_lu($scfg, $name);
-    zfs_add_lun_mapping_entry($scfg, $name);
+    my $guid = zfs_create_lu($scfg, $name);
+    zfs_add_lun_mapping_entry($scfg, $name, $guid);
 
     return $name;
 }
@@ -527,12 +491,10 @@ sub alloc_image {
 	if $name && $name !~ m/^vm-$vmid-/;
 
 	$name = &$find_free_diskname($storeid, $scfg, $vmid);
-    die "unable to allocate an image name for VM $vmid in storage '$storeid'\n"
-	if !$name;
 
     zfs_create_zvol($scfg, $name, $size);
-    zfs_create_lu($scfg, $name);
-    zfs_add_lun_mapping_entry($scfg, $name);
+    my $guid = zfs_create_lu($scfg, $name);
+    zfs_add_lun_mapping_entry($scfg, $name, $guid);
 
     return $name;
 }
@@ -548,8 +510,8 @@ sub free_image {
     };
     do {
         my $err = $@;
-        zfs_create_lu($scfg, $name);
-        zfs_add_lun_mapping_entry($scfg, $name);
+        my $guid = zfs_create_lu($scfg, $name);
+        zfs_add_lun_mapping_entry($scfg, $name, $guid);
         die $err;
     } if $@;
 
@@ -698,3 +660,4 @@ sub volume_has_feature {
 }
 
 1;
+
-- 
1.8.4.rc3




More information about the pve-devel mailing list