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:
parent
d8ade58f3a
commit
97c8c8577d
2
debian/control
vendored
2
debian/control
vendored
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user