#!/usr/bin/perl # show the distribution of LVs/LEs in the systems PVs # # Copyright 2005, 2008, 2009 Uli Martens # 2009 Peter Palfrader # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # ChangeLog: # 2009-05-30 Peter Palfrader # * teach it about striped logical volumes # 2009-01-05 Uli Martens # * right-justify #PE, fixes ragged output for large slices # 2008-01-20 Uli Martens # * fix off-by-two error for lv slice sizes # 2005-04-11 Uli Martens # * written # Example Output: # $ ~/bin/pvinfo # first/last PE #PE device first/last LE # vg: vg # pv: /dev/md5 # ( 0 .. 295 ( 296 )) -- /dev/vg/backup ( 0 .. 295 ) # ( 296 .. 807 ( 512 )) -- /dev/vg/kyra ( 0 .. 511 ) # [...] use strict; use warnings; # ---- vv config ---- my $pvdisplay_file = "pvdisplay |"; my $lvdisplay_file = "lvdisplay -m |"; my $lvname_width = 25; # ------------------- my $all; my $pv; my $lv; my $vg; open PVD, $pvdisplay_file or die "can't get pvdisplay info: $!"; while () { if ( m/^ PV Name\s+(.*)$/ ) { $pv = $1; next; } if ( m/^ VG Name\s+(.*)$/ ) { $vg = $1; next; } if ( m/^ Total PE\s+(.*)$/ ) { $all->{$vg}->{$pv}->{size} = $1 -1; undef $vg; undef $pv; next; } # print; } close PVD; open LVD, $lvdisplay_file or die "can't get lvdisplay info: $!"; VG: while () { if ( m/^ LV Name\s+(.*)$/ ) { $lv = $1; next; } if ( m/^ VG Name\s+(.*)$/ ) { $vg = $1; next; } if ( m/^ --- Segments ---$/ ) { my $from; my $to; my $pfrom; my $pto; my $pv; LE: while () { if ( m/^ --- Logical volume ---/ ) { next VG; } if ( m/^ Logical extent (\d+) to (\d+):$/ ) { $from = $1; $to = $2; next; } if ( m/^ Type\s+linear$/ ) { while () { if ( m/^ Physical volume\s+(.*)$/ ) { $pv = $1; next; } if ( m/^ Physical extents\s+(\d+) to (\d+)$/ ) { $pfrom = $1; $pto = $2; next; } if ( m/^\s*$/ and defined $pv ) { #print "GOT: $pv / $from / $to\n"; $all->{$vg}->{$pv}->{lvs}->{$pfrom} = { from => $pfrom, to => $pto, lv => $lv, pv => $pv, pfrom => $from, pto => $to, }; undef $pv; undef $from; undef $to; next LE; } #print ">> $_"; } } elsif ( m/^ Type\s+striped$/ ) { my $numstripes; my $curstripe; while () { if ( m/^ Stripes\s+(.*)$/ ) { $numstripes = $1; next; } while () { if ( m/^ Physical volume\s+(.*)$/ ) { $pv = $1; next; } if ( m/^ Physical extents\s+(\d+) to (\d+)$/ ) { $pfrom = $1; $pto = $2; next; } if ((m/^\s*$/ or m/ Stripe\s+(\d+):/) and defined $pv ) { #print "GOT: $pv / $from / $to\n"; $all->{$vg}->{$pv}->{lvs}->{$pfrom} = { from => $pfrom, to => $pto, lv => $lv." ($curstripe/$numstripes)", pv => $pv, pfrom => $from, pto => $to, }; undef $pv; undef $pfrom; undef $pto; } if (m/ Stripe\s+(\d+):/) { $curstripe = $1; } if ( m/^\s*$/) { undef $pv; undef $from; undef $to; next LE; } } } } elsif ( m/^ Type\s+(.*)$/ ) { warn "Do not understand type $1 for $lv"."'s extend $from - $to.\n"; next LE; } } } #print "XX $_"; } close LVD; printf " %17s %5s %*s %17s\n", "first/last PE", "#PE", -$lvname_width, "device", "first/last LE"; for my $vg ( sort keys %{$all} ) { print "vg: $vg\n"; for my $pv ( sort keys %{$all->{$vg}} ) { print " pv: $pv\n"; my $pelast = -1; for my $x ( sort { $a <=> $b } keys %{$all->{$vg}->{$pv}->{lvs}} ) { if ( $pelast + 1 != $all->{$vg}->{$pv}->{lvs}->{$x}->{from} ) { printf " (%7i ..%7i (%6i))\n", $pelast+1, $all->{$vg}->{$pv}->{lvs}->{$x}->{from} -1, $all->{$vg}->{$pv}->{lvs}->{$x}->{from} - $pelast -1; } printf " (%7i ..%7i (%6i)) -- %*s (%7i ..%7i )\n", $all->{$vg}->{$pv}->{lvs}->{$x}->{from}, $all->{$vg}->{$pv}->{lvs}->{$x}->{to}, $all->{$vg}->{$pv}->{lvs}->{$x}->{to} - $all->{$vg}->{$pv}->{lvs}->{$x}->{from} +1, -$lvname_width, $all->{$vg}->{$pv}->{lvs}->{$x}->{lv}, $all->{$vg}->{$pv}->{lvs}->{$x}->{pfrom}, $all->{$vg}->{$pv}->{lvs}->{$x}->{pto}; $pelast = $all->{$vg}->{$pv}->{lvs}->{$x}->{to}; } if ( $pelast != $all->{$vg}->{$pv}->{size} ) { printf " (%7i ..%7i (%6i))\n", $pelast +1, $all->{$vg}->{$pv}->{size}, $all->{$vg}->{$pv}->{size} - $pelast; } } }