5
0
mirror of git://git.proxmox.com/git/pve-common.git synced 2025-03-08 08:58:43 +03:00

Tools::df: fork and use Filesys::Df

Instead of depending on the 'df' commandline tool do a
fork() to create a killable process and run Filesys::Df,
returning the data over a pipe.
This commit is contained in:
Wolfgang Bumiller 2015-10-29 14:16:59 +01:00 committed by Dietmar Maurer
parent d8ade58f3a
commit 97c8c8577d
2 changed files with 38 additions and 18 deletions

2
debian/control vendored
View File

@ -7,6 +7,6 @@ Standards-Version: 3.8.4
Package: libpve-common-perl
Architecture: all
Depends: ${perl:Depends} ${misc:Depends}, libclone-perl, libdevel-cycle-perl, libwww-perl, libjson-perl, liblinux-inotify2-perl, libio-stringy-perl, liburi-perl, libstring-shellquote-perl, libnet-ip-perl
Depends: ${perl:Depends} ${misc:Depends}, libclone-perl, libdevel-cycle-perl, libwww-perl, libjson-perl, liblinux-inotify2-perl, libio-stringy-perl, liburi-perl, libstring-shellquote-perl, libnet-ip-perl, libfilesys-df-perl
Description: Proxmox VE base library
This package contains the base library used by other Proxmox VE components.

View File

@ -8,6 +8,8 @@ use Socket qw(AF_INET AF_INET6 AI_ALL AI_V4MAPPED);
use IO::Select;
use File::Basename;
use File::Path qw(make_path);
use Filesys::Df (); # don't overwrite our df()
use IO::Pipe;
use IO::File;
use IO::Dir;
use IPC::Open3;
@ -790,33 +792,51 @@ sub next_spice_port {
# NOTE: NFS syscall can't be interrupted, so alarm does
# not work to provide timeouts.
# from 'man nfs': "Only SIGKILL can interrupt a pending NFS operation"
# So the spawn external 'df' process instead of using
# Filesys::Df (which uses statfs syscall)
# So fork() before using Filesys::Df
sub df {
my ($path, $timeout) = @_;
my $cmd = [ 'df', '-P', '-B', '1', $path];
my $res = {
total => 0,
used => 0,
avail => 0,
};
my $parser = sub {
my $line = shift;
if (my ($fsid, $total, $used, $avail) = $line =~
m/^(\S+.*)\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+%\s.*$/) {
$res = {
total => $total,
used => $used,
avail => $avail,
};
}
};
eval { run_command($cmd, timeout => $timeout, outfunc => $parser); };
warn $@ if $@;
my $pipe = IO::Pipe->new();
my $child = fork();
if (!defined($child)) {
warn "fork failed: $!\n";
return $res;
}
if (!$child) {
$pipe->writer();
eval {
my $df = Filesys::Df::df($path, 1);
print {$pipe} "$df->{blocks}\n$df->{used}\n$df->{bavail}\n";
$pipe->close();
};
if (my $err = $@) {
warn $err;
POSIX::_exit(1);
}
POSIX::_exit(0);
}
$pipe->reader();
my $readvalues = sub {
$res->{total} = int(<$pipe>);
$res->{used} = int(<$pipe>);
$res->{avail} = int(<$pipe>);
};
eval {
run_with_timeout($timeout, $readvalues);
};
warn $@ if $@;
$pipe->close();
kill('KILL', $child);
waitpid($child, 0);
return $res;
}