From mboxrd@z Thu Jan 1 00:00:00 1970 Date: Thu, 20 Apr 2000 11:10:09 +0200 From: Harald Milz Subject: [linux-lvm] resizing reiserfs on top of LVM Message-ID: <20000420111009.A2418@linux-magazin.de> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="Dxnq1zWXvFF0Q93v" Sender: owner-linux-lvm Errors-To: owner-linux-lvm List-Id: To: reiser@idiom.com, linux-lvm@msede.com Cc: tw@suse.de, mge@suse.de, afx@suse.de, mm@suse.de --Dxnq1zWXvFF0Q93v Content-Type: text/plain; charset=us-ascii 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 -- Harald Milz | hm@linux-magazin.de | "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." --Dxnq1zWXvFF0Q93v Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=resize_rfs #!/usr/bin/perl # resize_rfs V0.02 # Copyright (C) 2000 Harald Milz (hm@linux-magazin.de) # 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 [+|-] # --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 [+|-] --lv \\ [--pv ] [--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; --Dxnq1zWXvFF0Q93v--