Re: lvm_queryvg() and AIX 5.3



#!/usr/bin/perl

# resize_rfs V0.02
#

# ohmygod. someone invented lvextend, lvreduce, and resize_reiserfs,
# but did not think of integrating them. This is an UGLY HACK
# which does exactly that, while at the same time attempting to
# perform some sanity checks before actually messing with the
# filesystems. Better is that ...

# BUGS:
# 1. BAD UGLY SPAGHETTI CODE
# 2. no proper documentation yet
# 3. works as designed.

###################################################################
# Parameter
# --size [+|-]<size><kKmMgGtT>
# --lv lvname
# --pv pvname optional - makes only sense when growing
# --verbose
# --dry-run and don't actually do something
# --help
###################################################################

###################################################################
# Exit codes
# 0 success or nothing to do
# 1 wrong syntax
# 2 VG not found
# 3 VG not read/write
# 4 VG not available/resizable
# 5 can't shrink FS while mounted
# 6 not enough free PE's left on VG
# 7 PV not valid
# 8 not enough free PE's left on PV
# 9 can't shrink FS - not enough space left
# 10 program not run as root
# 11 LV does not exist
###################################################################

use Getopt::Long;
GetOptions ("size=s" => \$size,
"lv=s" => \$lv,
"pv=s" => \$pv,
"dry-run!" => \$dryrun,
"verbose!",
"help!");

sub usage () {
print ("usage: $0 --size [+|-]<size><kKmMgGtT> --lv <logical volume> \\
[--pv <pvname>] [--dry-run] [--verbose] [--help]\n");
exit 1;
}

if ($< != 0) {
warn ("$0 must be run as root\n");
exit 10;
}

# size and lv must be there, else usage();
if (!$size || !$lv || $opt_help) {
usage();
}

# find out size parameter
usage() unless $size =~ m/^(.)(\d*)([K|M|G|T])$/i;
($sign, $num, $exp) = ($1, $2, $3);

# more elegant: quit if 1st char != 0-9, -, +
if ($sign eq "+") {
$grow = 1;
} elsif ($sign eq "-") {
$grow = -1;
} elsif ($sign =~ /[0-9]+/) {
$grow = 0;
} else {
usage ();
}

# scale everything to kBytes
$mysize = $sign . $num;
$mysize *= 1024 if (uc $exp eq "M");
$mysize *= 1024*1024 if (uc $exp eq "G");
$mysize *= 1024*1024*1024 if (uc $exp eq "T"); # ohmygod ...

###################################################################
# check VG if exists, R/W and active. get VG parameter from LV data
# vgdisplay -c -> split ":"
# access:status must be 3:5
# else die (warning);
###################################################################

chomp ($lvdata = `lvdisplay -c $lv 2>&1`);

($lvname, $vgname, $lvwrite, $lvstatus, $lvno, $noopen,
$lvsize, $currentle, $allocle, $allocstrat, $readahead,
$blockdev) = split (/:/, $lvdata);

if ($lvname ne $lv) {
warn ("$lvdata");
exit 11;
}

$vg = $vgname;
chomp ($vgdata = `vgdisplay -c $vg 2>&1`);
chop $vgdata; # 2 trailing \n -...

($vgname, $vgaccess, $vgstatus, $vgno, $maxlv, $curlv,
$openlv, $maxlvsize, $maxpv, $curpv, $actpv, $vgsize,
$pesize, $totalpe, $allocpe, $freepe) = split (/:/, $vgdata);

if ($vgname ne $vg) {
warn ("$vgdata");
exit 2;
} elsif ($vgaccess != 3) {
warn ("VG $vgname not read/write\n");
exit 3;
} elsif ($vgstatus != 5) {
warn ("VG $vgname not available/resizable\n");
exit 4;
}

###################################################################
# if no + or -: absolute size change.
# determine grow or shrink
###################################################################

$lvsize /= 2; # size in K
$mysize -= $lvsize if ($grow == 0);

if ($mysize == 0) {
warn ("nothing to do.\n");
exit 0;
}

###################################################################
# if shrink && mounted: die (warning);
###################################################################

$mount = `mount | grep $lv`;
if ($mount ne "" && $mysize < 0) {
warn ("can't shrink fs $lv while mounted\n");
exit 5;
}

# STRATEGY DISCUSSION
# we always use absolute growth/shrink here to prevent
# LV and FS size from differing.

if ($mysize > 0) { # grow

###################################################################
# if grow: enough space left on VG?
# free kBytes = free PE's * 4K
# if $pv: check whether valid pvname (pvdisplay)
# and enough space left on PV
# lvextend [$pvname], resize_reiserfs -f
###################################################################

$freekb = $freepe * 4096;
if ($mysize > $freekb) {
warn ("only $freepe free PE's ($freekb K) left on VG $vg\n");
exit 6;
}
if ($pv) {
# pvdisplay of LVM 0.8 has a bug which prevents the use of "-c":
# merlin:~ # pvdisplay -c /dev/hda4
# pvdisplay -- option v not allowed with option c
# this ugly stuff needs a rewrite as soon as this is fixed. Bah.
chomp ($pvdata = `pvdisplay -vc $pv 2>&1`);

($pvname, $vgname, $pvsize, $pvno, $pvstat, $allocatable, $curlv,
$pesize, $totalpe, $freepe, $allocpe) = split (/:/, $pvdata);

if ($pvname ne $pv) { # ERROR
warn ("$pvdata");
exit 7;
}
$freekb = $freepe * 4096;
if ($mysize > $freekb) {
warn ("only $freepe free PE's ($freekb K) left on PV $pv\n");
exit 8;
}
}

$newsize = $lvsize + $mysize;

# now comes the moment where the cow the water lets.
$cmd = sprintf ("lvextend -L %dK %s %s\n", $newsize, $lv, $pv);
print $cmd if $opt_verbose;
system ($cmd) unless $dryrun;
$cmd = sprintf ("resize_reiserfs -s%dK -f %s\n", $newsize, $lv);
print $cmd if $opt_verbose;
system ($cmd) unless $dryrun;

} else { # shrink

###################################################################
# if shrink: enough free space left on FS?
# mount temporary! $tmpdir = `mktemp -d /tmp/temp.XXXXXX`;
# df -k --sync
# umount ; rmdir $tmpdir ;
# resize_reiserfs -f , lvreduce -f
###################################################################

$mysize = abs ($mysize);
chomp ($tmpdir = `mktemp -d /tmp/temp.XXXXXX`);
`mount -t reiserfs $lv $tmpdir`;
$df = `df -k --sync $lv | sed 1d`;
`umount $tmpdir`;
rmdir $tmpdir;
$df =~ m/\S+\s+(\S+)\s+\S+\s+(\S+).*/;
($fssize, $available) = ($1, $2);
if ($available < $mysize) {
# should we add a minimum free size here?
warn ("can't shrink $lv by $mysize K: only $available K left.\n");
exit 9;
}
$newsize = $fssize - $mysize;
# now comes the moment where the cow the water lets.

# at the time of this writing, reducing a reiserfs requires a Y or N
# works though.
$cmd = sprintf ("resize_reiserfs -s%dK -f %s\n", $newsize, $lv);
print $cmd if $opt_verbose;
system ($cmd) unless $dryrun;
# we're allowed use the "-f" parameter because we hopefully made
# all necessary sanity checks.
$cmd = sprintf ("lvreduce -f -L %dK %s %s\n", $newsize, $lv);
print $cmd if $opt_verbose;
system ($cmd) unless $dryrun;

}

print "Now you may want to restore your backup.
Err - you did make a backup before, no?\n";
exit 0;






--- On Tue, 1/13/09, Flavien L <flavien-aix@xxxxxxxxxxx> wrote:
From: Flavien L <flavien-aix@xxxxxxxxxxx>
Subject: lvm_queryvg() and AIX 5.3
To: aix-l@xxxxxxxxxxxxx
Date: Tuesday, January 13, 2009, 11:20 AM

Hello,


I'm developping an application in C and I'd like to get the total
available space on a LV (the TOTAL PPs field in lsvg output).

I'm using the lvm_queryvg() API. I can correctly get the
"freespace"
on all AIX versions that I tried (5.2, 5.3 & 6.1). As for the total
space, I am looking at the total_pps field.

On AIX = 5.2 => The total_pps field does not exist => *OOPS*
On AIX = 6.1 => The total_pps field is correctly set => Good
On AIX = 5.3 => The field is set to 0. => *BUG ?*

Is it a known issue ? Is there a workaround ?

BTW, what's the recommended way to get this info elsewere ?
popen(lsvg) is an option that I would like not to have to consider. :)


Attached is a minimal test program.

Thanks !

Flavien.
#include
#include

/* xlc -o vgsize vgsize.c -qlanglvl=extc99 -llvm */

int main(void)
{
struct queryvgs *vgs;
struct queryvg *queryvg;
long vg_total, vg_free;
int i;

if (lvm_queryvgs(&vgs, 0) != 0)
return 0;

for (i = 0; i < vgs->num_vgs; i++) {

if (lvm_queryvg(&vgs->vgs[i].vg_id, &queryvg, NULL))
continue;

/* Before AIX 5.3, total_pps does not exist.
* On AIX 5.3 it's always 0 (WHY ???)
* On AIX 6.1 it's value is correct */
vg_total = queryvg->total_pps;
vg_free = queryvg->freespace;

printf("VG[%d]: vg_total = %d vg_free %d\n", i, vg_total, vg_free);
}
return 0;
}

Relevant Pages

  • Re: [PATCH #2] Re: SATA and 2.6.0-test9
    ... The 4th port seems to ... ata_bus_reset: EXIT ... ata_exec_command_mmio: ata1: cmd 0xEC ... ata_device_add: ata4: probe-wait begin ...
    (Linux-Kernel)
  • Re: Check if a process will auto-terminate
    ... then exit when called like this: ... But I want CMD to wait for CMD_SUB when called like this: ... $ spawn @CMD ... $ IF THEN GOTO PART1 ...
    (comp.os.vms)
  • Re: beginTrans without commitTrans or rollbackTrans
    ... A better way to deal with this is to raise your own error and exit via the ... instead of using Exit Function: ... > what if there's beginTrans without commitTrans or rollbackTrans? ... > Dim cmd As ADODB.Command ...
    (microsoft.public.vb.general.discussion)
  • Re: Seeding Randomization on CMD (WinXP Pro)
    ... However since my script takes exactly the ... >>real random number on CMD? ... > Returns an exit code of a pseudo-random number based on ... Thanks Mark! ...
    (microsoft.public.win2000.cmdprompt.admin)