X-Git-Url: http://git.apps.os.sepia.ceph.com/?p=xfstests-dev.git;a=blobdiff_plain;f=tools%2Fag-wipe;h=f580b9dc28377298920604656b5ca36d97587b92;hp=2fcac987c0273f169a358980d3dfdbbb59fb31ad;hb=de6d86177ff8499dc365c0c0d56abf0e66be4672;hpb=69042199859e144b41172450f3e046057a169631 diff --git a/tools/ag-wipe b/tools/ag-wipe index 2fcac987..f580b9dc 100755 --- a/tools/ag-wipe +++ b/tools/ag-wipe @@ -2,39 +2,8 @@ use strict; use IO::File; use Getopt::Std; - -# -# Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of version 2 of the GNU General Public License as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it would be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# -# Further, this software is distributed without any warranty that it is -# free of the rightful claim of any third person regarding infringement -# or the like. Any license provided herein, whether implied or -# otherwise, applies only to this software file. Patent licenses, if -# any, provided herein do not apply to combinations of this program with -# other software, or any other product whatsoever. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write the Free Software Foundation, Inc., 59 -# Temple Place - Suite 330, Boston MA 02111-1307, USA. -# -# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, -# Mountain View, CA 94043, or: -# -# http://www.sgi.com -# -# For further information regarding this notice, see: -# -# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ # - +# Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved. # # Modify a filesystem's superblock and AGF metadata structures # so that only a subset of the allocation groups will be used. @@ -44,38 +13,40 @@ use Getopt::Std; # the block addresses are large). # -my @sbprint = ( '"print fdblocks"', '"print agcount"' ); -my @agfprint = ( '"print freeblks"' ); -my @agfcommands = ( '"write freeblks 0"', - '"write longest 0"', '"write flcount 0"', - '"write bnolevel 1"', '"write cntlevel 1"', - '"write flfirst 0"', '"write fllast 0"' ); -my @bnoprint = ( '"addr bnoroot"', '"print numrecs"' ); -my @bnocommands = ( '"addr bnoroot"', '"write numrecs 0"', - '"write leftsib -1"', '"write rightsib -1"' ); -my @cntprint = ( '"addr cntroot"', '"print numrecs"' ); -my @cntcommands = ( '"addr cntroot"', '"write numrecs 0"', - '"write leftsib -1"', '"write rightsib -1"' ); - my %opt; -getopts('f:l:v', \%opt); -die "Usage: ag-wipe [-f firstAG] [-l lastAG] [-v] device\n" unless (@ARGV == 1); +getopts('cf:l:qr:v', \%opt); + +die "Usage: $0 [-f AG] [-l AG] [-r bytes] [-cqv] device\n" unless (@ARGV == 1); my $device = shift @ARGV; die "$device: no such file\n" unless (-e $device); + +my $clearall = defined($opt{'c'}) ? 1 : 0; +my $retain = defined($opt{'r'}) ? $opt{'r'} : -1; +my $quiet = defined($opt{'q'}) ? 1 : 0; my $verbose = defined($opt{'v'}) ? 1 : 0; my $nagfirst = defined($opt{'f'}) ? $opt{'f'} : 0; my $naglast = defined($opt{'l'}) ? $opt{'l'} : 0; +# +# "clearall" means clear everything barring the final AG. +# "retain" means clearall and retain a specified amount in the +# second-from-last AG as well (value is the number of bytes). +# [NB: retain with a value of zero is now the same as clearall]. +# +if ($retain >= 0) { + $clearall = 1; +} + sub xfs_db { - my $xfsdb = "xfs_db -x $device"; + my $xfsdb = 'xfs_db -x'; my %hash; foreach (@_) { $xfsdb .= ' -c ' . $_; } - print $xfsdb, "\n" if ($verbose); + print $xfsdb, ' ', $device, "\n" if ($verbose); - die unless open(DB, "$xfsdb 2>/dev/null |"); + die unless open(DB, "$xfsdb $device 2>/dev/null |"); while () { if (/^(\S+) = (.*)$/) { print if ($verbose); @@ -85,49 +56,114 @@ sub xfs_db { return %hash; } + +# +# Stage 1: Get control information from the superblock +# + +my @sbprint = ( '"print fdblocks"', '"print agcount"', '"print blocksize"' ); +my @agffree = ( '"print freeblks"' ); + my %sb = xfs_db 'sb', @sbprint; print "=== Initially ", $sb{'fdblocks'}, " blocks free across ", - $sb{'agcount'}, " AGs\n"; + $sb{'agcount'}, " AGs\n" unless $quiet; +if ($clearall && ($nagfirst || $naglast)) { + print STDERR " o Clearall/retain specified with first/last AG\n"; + exit(1); +} if ($nagfirst >= $sb{'agcount'}) { - print " o First AG number is too large, quiting\n"; - exit(0); + print STDERR " o First AG number is too large\n"; + exit(1); } if ($naglast >= $sb{'agcount'}) { - print " o Last AG number is too large, quiting\n"; - exit(0); + print STDERR " o Last AG number is too large\n"; + exit(1); } if ($naglast - $nagfirst < 0) { - print " o No AGs to clear, quiting\n"; - exit(0); + print STDERR " o No AGs to clear\n"; + exit(1); +} +if ($clearall) { + $naglast = $sb{'agcount'} - 2; + if ($retain > 0) { + my %check; + + $naglast--; + $retain /= $sb{'blocksize'}; # convert to fsblocks + %check = xfs_db "'agf $naglast'", @agffree; + if ($check{'freeblks'} < $retain) { + print STDERR " o Insufficient space to retain\n"; + exit(1); + } + } } -print "=== Wiping ", $naglast - $nagfirst, - " AGs starting from AG #", $nagfirst, "\n"; + +# +# Stage 2: Wipe out all completely masked allocation groups. +# + +my @agfprint = ( '"print freeblks"', '"print flcount"' ); +my @agfcommands = ( '"write freeblks 0"', + '"write longest 0"', '"write flcount 0"', + '"write bnolevel 1"', '"write cntlevel 1"', + '"write flfirst 0"', '"write fllast 0"' ); +my @bnoprint = ( '"addr bnoroot"', '"print numrecs"' ); +my @bnocommands = ( '"addr bnoroot"', '"write numrecs 0"', + '"write leftsib -1"', '"write rightsib -1"' ); +my @cntprint = ( '"addr cntroot"', '"print numrecs"' ); +my @cntcommands = ( '"addr cntroot"', '"write numrecs 0"', + '"write leftsib -1"', '"write rightsib -1"' ); + +print "=== Wiping ", $naglast - $nagfirst + 1, + " AGs starting from AG #", $nagfirst, "\n" unless $quiet; my $ag = $nagfirst; while ($ag <= $naglast) { - my %btree; - my %agf; - - print " o AG#", $ag, " AGF fields\n"; + print " o AG#", $ag, " AGF fields\n" unless $quiet; - %agf = xfs_db "'agf $ag'", @agfprint; + my %agf = xfs_db "'agf $ag'", @agfprint; xfs_db "'agf $ag'", @agfcommands; - $sb{'fdblocks'} -= $agf{'freeblks'}; - print " cleared ", $agf{'freeblks'}, " blocks from AG#", $ag, "\n"; + my $blockcnt = $agf{'freeblks'} + $agf{'flcount'}; + $sb{'fdblocks'} -= $blockcnt; + print " cleared ", $blockcnt, " blocks from AG#", $ag, "\n" + unless $quiet; - %btree = xfs_db "'agf $ag'", @bnoprint; - xfs_db "'agf $ag'", @bnocommands; - print " cleared ", $btree{'numrecs'}, " BNO btree records in AG#", - $ag, "\n"; + my %btree = xfs_db "'agf $ag'", @bnoprint; + xfs_db "'agf $ag'", @bnocommands, "'agf $ag'", @cntcommands; + print " cleared ", $btree{'numrecs'}, " BNO/CNT btree recs in AG#", + $ag, "\n" unless $quiet; - %btree = xfs_db "'agf $ag'", @cntprint; - xfs_db "'agf $ag'", @cntcommands; - print " cleared ", $btree{'numrecs'}, " CNT btree in AG#", - $ag, "\n"; $ag++; } -print "=== Updating final freespace count, ", $sb{'fdblocks'}, " blocks\n"; + +# +# Stage 3: Wipe out any partially masked allocation group. +# + +if ($retain > 0) { + print " o AG#", $ag, " AGF fields (partial)\n" unless $quiet; + + my %ragf = xfs_db "'agf $ag'", '"print freeblks"', + '"addr bnoroot"', '"print recs[1].startblock"'; + my $maskblks = $ragf{'freeblks'} - $retain; + my $newstart = $ragf{'recs[1].startblock'} + $maskblks; + xfs_db "'agf $ag'", + "'write freeblks $retain'", "'write longest $retain'", + "'agf $ag'", '"addr bnoroot"', + "'write recs[1].startblock $newstart'", + "'write recs[1].blockcount $retain'", + "'agf $ag'", '"addr cntroot"', + "'write recs[1].startblock $newstart'", + "'write recs[1].blockcount $retain'"; + + $sb{'fdblocks'} -= $maskblks; + print " cleared ", $maskblks, " blocks from AG#", $ag, "\n" + unless $quiet; +} + +print "=== Updating final freespace count, ", $sb{'fdblocks'}, " blocks\n" + unless $quiet; xfs_db "'sb 0'", "'write fdblocks $sb{'fdblocks'}'"