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();
24 # Discover whether or not we have GNU df.
26 `df -P / 2>/dev/null >/dev/null`;
32 look_at_disk_usage
($gnu_df);
35 # shut ourselves down if our parent mogstored
38 exit(0) unless $ppid == $start_ppid && kill(0,$ppid);
42 sub look_at_disk_usage
{
43 my $err = sub { warn "$_[0]\n"; };
44 my $path = $ENV{MOG_DOCROOT
};
48 # find all devices below us
50 if (opendir(D
, $path)) {
51 @devnum = grep { /^dev\d+$/ } readdir(D
);
54 return $err->("Failed to open $path: $!");
57 foreach my $devnum (@devnum) {
58 my $rval = `df $gnu_df -l -k $path/$devnum`;
59 my $uperK = ($rval =~ /512-blocks/i) ?
2 : 1; # units per kB
60 foreach my $l (split /\r?\n/, $rval) {
61 next unless $l =~ /^(.+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(.+)\s+(.+)$/;
62 my ($dev, $total, $used, $avail, $useper, $disk) = ($1, $2, $3, $4, $5, $6);
64 unless ($disk =~ m!$devnum/?$!) {
65 $disk = "$path/$devnum";
68 # FIXME: We're stupidly throwing away the 'avail' value here.
69 # This causes mogilefs to run aground when used with ext
70 # partitions using reserved space. Drop the reserved space from
71 # the total, and in the future add available to the device table
73 $total = $used + $avail;
75 # create string to print
79 device
=> $dev, # /dev/sdh1
80 total
=> int($total / $uperK), # integer: total KiB blocks
81 used
=> int($used / $uperK), # integer: used KiB blocks
82 available
=> int($avail / $uperK), # integer: available KiB blocks
83 'use' => $useper, # "45%"
84 disk
=> $disk, # mount point of disk (/var/mogdata/dev8), or path if not a mount
87 if ($ENV{MOG_DEV_USAGE_VIA_DU
}) {
88 my $size = `du -k -c -s $path/$devnum`;
89 if ($size =~ /^(\d+)/) {
94 # size of old file we'll be overwriting in place (we'll want
95 # to pad with newlines/spaces, before we truncate it, for
97 my $ufile = "$disk/usage";
98 my $old_size = (-s
$ufile) || 0;
99 my $mode = $old_size ?
"+<" : ">";
101 # string we'll be writing
103 foreach (sort keys %$output) {
104 $new_data .= "$_: $output->{$_}\n";
107 my $new_size = length $new_data;
108 my $pad_len = $old_size > $new_size ?
($old_size - $new_size) : 0;
109 $new_data .= "\n" x
$pad_len;
111 # write the file, all at once (with padding) then remove padding
112 my $rv = open(my $fh, $mode, $ufile);
114 $err->("Unable to open '$ufile' for writing: $!");
117 unless (syswrite($fh, $new_data)) {
119 $err->("Error writing to '$ufile': $!");
122 truncate($fh, $new_size) if $pad_len;