1 package Mogstored
::ChildProcess
::DiskUsage
;
3 use base
'Mogstored::ChildProcess';
9 $SIG{TERM
} = 'DEFAULT'; # override custom one from earlier
10 $ENV{MOG_DOCROOT
} = Perlbal
->service('mogstored')->{docroot
};
14 $docroot = $ENV{MOG_DOCROOT
};
15 die "\$ENV{MOG_DOCROOT} not set" unless $docroot;
16 die "\$ENV{MOG_DOCROOT} not set to a directory" unless -d
$docroot;
18 # (runs in exec'd child process)
19 $0 = "mogstored [diskusage]";
20 select((select(STDOUT
), $|++)[0]);
22 my $start_ppid = getppid();
28 # shut ourselves down if our parent mogstored
31 exit(0) unless $ppid == $start_ppid && kill(0,$ppid);
35 sub look_at_disk_usage
{
36 my $err = sub { warn "$_[0]\n"; };
37 my $path = $ENV{MOG_DOCROOT
};
40 # find all devices below us
42 if (opendir(D
, $path)) {
43 @devnum = grep { /^dev\d+$/ } readdir(D
);
46 return $err->("Failed to open $path: $!");
49 foreach my $devnum (@devnum) {
50 my $rval = `df -P -l -k $path/$devnum`;
51 my $uperK = ($rval =~ /512-blocks/i) ?
2 : 1; # units per kB
52 foreach my $l (split /\r?\n/, $rval) {
53 next unless $l =~ /^(.+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(.+)\s+(.+)$/;
54 my ($dev, $total, $used, $avail, $useper, $disk) = ($1, $2, $3, $4, $5, $6);
56 unless ($disk =~ m!$devnum/?$!) {
57 $disk = "$path/$devnum";
60 # FIXME: We're stupidly throwing away the 'avail' value here.
61 # This causes mogilefs to run aground when used with ext
62 # partitions using reserved space. Drop the reserved space from
63 # the total, and in the future add available to the device table
65 $total = $used + $avail;
67 # create string to print
71 device
=> $dev, # /dev/sdh1
72 total
=> int($total / $uperK), # integer: total KiB blocks
73 used
=> int($used / $uperK), # integer: used KiB blocks
74 available
=> int($avail / $uperK), # integer: available KiB blocks
75 'use' => $useper, # "45%"
76 disk
=> $disk, # mount point of disk (/var/mogdata/dev8), or path if not a mount
79 if ($ENV{MOG_DEV_USAGE_VIA_DU
}) {
80 my $size = `du -k -c -s $path/$devnum`;
81 if ($size =~ /^(\d+)/) {
86 # size of old file we'll be overwriting in place (we'll want
87 # to pad with newlines/spaces, before we truncate it, for
89 my $ufile = "$disk/usage";
90 my $old_size = (-s
$ufile) || 0;
91 my $mode = $old_size ?
"+<" : ">";
93 # string we'll be writing
95 foreach (sort keys %$output) {
96 $new_data .= "$_: $output->{$_}\n";
99 my $new_size = length $new_data;
100 my $pad_len = $old_size > $new_size ?
($old_size - $new_size) : 0;
101 $new_data .= "\n" x
$pad_len;
103 # write the file, all at once (with padding) then remove padding
104 my $rv = open(my $fh, $mode, $ufile);
106 $err->("Unable to open '$ufile' for writing: $!");
109 unless (syswrite($fh, $new_data)) {
111 $err->("Error writing to '$ufile': $!");
114 truncate($fh, $new_size) if $pad_len;