mirror of
git://git.proxmox.com/git/pve-common.git
synced 2025-05-30 05:05:36 +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
|
Package: libpve-common-perl
|
||||||
Architecture: all
|
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
|
Description: Proxmox VE base library
|
||||||
This package contains the base library used by other Proxmox VE components.
|
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 IO::Select;
|
||||||
use File::Basename;
|
use File::Basename;
|
||||||
use File::Path qw(make_path);
|
use File::Path qw(make_path);
|
||||||
|
use Filesys::Df (); # don't overwrite our df()
|
||||||
|
use IO::Pipe;
|
||||||
use IO::File;
|
use IO::File;
|
||||||
use IO::Dir;
|
use IO::Dir;
|
||||||
use IPC::Open3;
|
use IPC::Open3;
|
||||||
@ -790,33 +792,51 @@ sub next_spice_port {
|
|||||||
# NOTE: NFS syscall can't be interrupted, so alarm does
|
# NOTE: NFS syscall can't be interrupted, so alarm does
|
||||||
# not work to provide timeouts.
|
# not work to provide timeouts.
|
||||||
# from 'man nfs': "Only SIGKILL can interrupt a pending NFS operation"
|
# from 'man nfs': "Only SIGKILL can interrupt a pending NFS operation"
|
||||||
# So the spawn external 'df' process instead of using
|
# So fork() before using Filesys::Df
|
||||||
# Filesys::Df (which uses statfs syscall)
|
|
||||||
sub df {
|
sub df {
|
||||||
my ($path, $timeout) = @_;
|
my ($path, $timeout) = @_;
|
||||||
|
|
||||||
my $cmd = [ 'df', '-P', '-B', '1', $path];
|
|
||||||
|
|
||||||
my $res = {
|
my $res = {
|
||||||
total => 0,
|
total => 0,
|
||||||
used => 0,
|
used => 0,
|
||||||
avail => 0,
|
avail => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
my $parser = sub {
|
my $pipe = IO::Pipe->new();
|
||||||
my $line = shift;
|
my $child = fork();
|
||||||
if (my ($fsid, $total, $used, $avail) = $line =~
|
if (!defined($child)) {
|
||||||
m/^(\S+.*)\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+%\s.*$/) {
|
warn "fork failed: $!\n";
|
||||||
$res = {
|
return $res;
|
||||||
total => $total,
|
}
|
||||||
used => $used,
|
|
||||||
avail => $avail,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
eval { run_command($cmd, timeout => $timeout, outfunc => $parser); };
|
|
||||||
warn $@ if $@;
|
|
||||||
|
|
||||||
|
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;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user