Skip to content

Instantly share code, notes, and snippets.

@wyoung
Last active August 29, 2015 14:19
Show Gist options
  • Save wyoung/7c94967bb635de48d058 to your computer and use it in GitHub Desktop.
Save wyoung/7c94967bb635de48d058 to your computer and use it in GitHub Desktop.
Calculator for fsck combinations, giving the chance of two or more volumes needing to be checked at the same time
#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);
use Getopt::Std;
sub commafy { # from perlfaq5, since Number::Format is non-core
local $_ = shift;
1 while s/^([-+]?\d+)(\d{3})/$1,$2/;
return $_;
}
my $syears = 5;
my $freq = 30;
my %opts;
if (!getopts('vy:f:', \%opts) or @ARGV < 2) {
print <<USAGE;
usage: $0 [-v] [-y years] [-f frequency] <mounts>
This program models a multi-volume Linux computer running ext[234]
with the max-mount-counts for each volume set (tune2fs -c) to one of
the values passed. Pass four values for a 4-volume system, for
example; you must give at least two. The values needn't be unique
or sorted, but the program expects them to be positive integers.
It works through all of the possibilities given the reboot schedule
over the machine's service life, modified by -y and -f, defaulting
to $syears years and $freq days between reboots. You may give decimal -f
values for multiple reboots per day; e.g. 0.25 for 4 reboots per day.
It reports the percentage of reboots that two or more volumes on the
system will have to be checked. The point is to help you work out
which values to use here which will minimize the chance of a
multi-volume fsck on reboot without requiring values that are too
high. You will find that if you use prime numbers or /relatively/
prime numbers (http://goo.gl/bQbu5Z) that you will get the lowest
chances of a multi-volume fsck. You do not have to pass unique
values; you can pass "20 20 20" to see what would happen on a
3-volume system with all three set to be checked every 20 mounts.
Give -v to get a visual analog of the fsck schedule as output. It
shows a . for reboots that don't cause an fsck, * for single-volume
fsck reboots, and a list of the passed mount counts that triggered
a multi-volume fsck.
USAGE
exit 1;
}
my $verbose = $opts{v};
$freq = $opts{f} if exists $opts{f};
$syears = $opts{y} if exists $opts{y};
my $sdays = int($syears * 365.24 + 0.5);
my @vals = map { int($_) } @ARGV;
my $max = int($sdays / $freq + 0.5);
my @buckets;
for (my $i = 0; $i <= (@ARGV - 2); ++$i) { $buckets[$i] = 0; }
my $prevpctreport = 0;
my $start = time;
for (my $i = 1; $i <= $max; ++$i) {
my @divs = grep { $i % $_ == 0 } @vals;
++$buckets[@divs - 2] if @divs >= 2;
# Write out a visual analog of the simulation results if -v.
if ($verbose) {
print '.' if @divs == 0; # no fsck this time
print '*' if @divs == 1; # one volume fscks this time
print '[', join(',', @divs), ']' if @divs > 1;
}
}
print "\n\n" if $verbose;
my $total = 0;
print "Results:\n\n";
print " svc years: ", $syears, "\n";
print " frequency: $freq days between reboots\n" if $freq >= 1;
print " frequency: ", int(1/$freq+0.5), " reboots / day\n" if $freq < 1;
print " reboots: ", commafy($max), "\n";
for (my $i = 2; $i <= @vals; ++$i) {
my $mvf = $buckets[$i - 2];
if ($mvf > 0) {
my $pct = $mvf / $max * 100.0;
printf " $i-volume: $mvf incidents total, %.2f%%\n", $pct;
$total += $pct;
}
else {
printf " $i-volume: never happens\n";
}
}
printf " total: %.1f%% chance of a multi-volume fsck\n\n", $total;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment