resizing reiserfs on top of LVM
Hi,
I am very fond of resizing filesystems on top of LVM (having worked with and loving IBM AIX a lot too :-) therefore I wrote a little tool to integrate resize_reiserfs and lv{reduce|extend} similar to e2fsadm wrote by Tytso. This is a first approach which works as designed for me. Please beat the shit out of it to find design errors, flaws and bugs.
Thanks for all your good work ...
Ciao,
hm
Signature · 4 lines
Harald Milz | [email protected] | "Acting is an art Linux Magazin | phone +49 (0) 89 993411-20 | which consists of Stefan-George-Ring 24 | fax +49 (0) 89 993411-99 | keeping the audience D-81929 Muenchen | http://www.linux-magazin.de | from coughing."
#!/usr/bin/perl
# resize_rfs V0.02 # Copyright (C) 2000 Harald Milz ([email protected]) # This file is distributed under the GPL V2 or any later version...
# 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.
#@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;
Quoted 7 lines · Harald Milz
Hi,
I am very fond of resizing filesystems on top of LVM (having worked with and loving IBM AIX a lot too :-) therefore I wrote a little tool to integrate
resize_reiserfsand lv{reduce|extend} similar to e2fsadm wrote by Tytso. This is a first approach which works as designed for me. Please beat the shit out of it to find design errors, flaws and bugs.
Did you actually try to shrink a FS ? AFAIK resize_reiserfs does not support it yet (only growing)
-Andi
Quoted 7 lines · Harald Milz
Quoted 7 lines
Hi,
I am very fond of resizing filesystems on top of LVM (having worked with and loving IBM AIX a lot too :-) therefore I wrote a little tool to integrate
resize_reiserfsand lv{reduce|extend} similar to e2fsadm wrote by Tytso. This is a first approach which works as designed for me. Please beat the shit out of it to find design errors, flaws and bugs.
AK> Did you actually try to shrink a FS ? AFAIK resize_reiserfs does not AK> support it yet (only growing)
The resize_reiserfs supports off-line shrinking since 3.5.19. This is still APLHA version of fs shrinker.
AK> -Andi
Best regards,
Alex.
Signature · 1 line
Alexander Zarochentcev, mailto:[email protected]