[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