|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2007-03-22 14:59 UTC] andrew at digicol dot de
Description:
------------
disk_total_space, disk_free_space reports wrong total and free space for NFS-mounted filesystems on RedHat Linux.
This bug seems to be the related to #39520, if not the same. #39520 has been rated as 'bogus' which I think is a mistake. Please re-consider.
The bug shows on RedHat Linux, but not SuSE Linux. This might ultimately be considered as a RedHat bug or of the libraries used there, but other commands (df) that use the statfs system call show the correct file system size / free space.
It may be argued (like in #39520) that the wrong block size parameter is used to calculate total or free disk space. strace df -h shows RedHat and SuSE report different f_frsize, but same f_bsize on the same NFS share, but df reports the correct size on both.
Reproduce code:
---------------
Test: Mount a NFS share on a RedHat system and on a SuSE Linux system.
1) RedHat 2.6.9-34.EL, 32-bit
[root@dc5ora10gr2 /]# mount -t nfs 10.20.0.178:/dot/oracle_dump /mnt
[root@dc5ora10gr2 /]# df -h
Filesystem Size Used Avail Use% Mounted on
...
10.20.0.178:/dot/oracle_dump 280G 125G 156G 45% /mnt
[root@dc5ora10gr2 /]# /dot/dc/bin/php/bin/php -r 'echo_number_format(disk_total_space("/mnt")) . "\n";'
37,512,204,288 ==> Wrong size, seems to be real size / 8
2) SuSE Linux 9.3 32-bit
suse:/ # mount -t nfs 10.20.0.178:/dot/oracle_dump /mnt
suse:/ # df -h
Filesystem Size Used Avail Use% Mounted on
...
10.20.0.178:/dot/oracle_dump 280G 125G 156G 45% /mnt
suse:/ # php -r 'echo number_format(disk_total_space("/mnt")) . "\n";'
300,097,634,304 ==> Correct.
Expected result:
----------------
I would expect the result to be 300G on both systems.
Actual result:
--------------
Reports 300G on SuSE Linux, around 35G only on RedHat.
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Nov 21 15:00:01 2025 UTC |
RedHat Linux: strace /dot/dc/bin/php/bin/php -r 'echo number_format(disk_total_space("/mnt")) . "\n";' ... statfs("/mnt", {f_type="NFS_SUPER_MAGIC", f_bsize=32768, f_blocks=9158253, f_bfree=5093458, f_bavail=5093458, f_files=0, f_ffree=0, f_fsid={0, 0}, f_namelen=255, f_frsize=4096}) = 0 ... SuSE Linux: strace php -r 'echo number_format(disk_total_space("/mnt")) . "\n";' ... statfs("/mnt", {f_type="NFS_SUPER_MAGIC", f_bsize=32768, f_blocks=9158253, f_bfree=5093458, f_bavail=5093458, f_files=0, f_ffree=0, f_fsid={0, 0}, f_namelen=255, f_frsize=32768}) = 0 ... Just in case this helps, "df -h" seems to invoke the a different system call (statfs64, both systems are 32-bit, I am not an expert regarding system calls). They result in the same f_bsize and fr_size values. Unlike php, df draws the correct conclusions regarding total / free space on both systems: RedHat Linux: strace df -h ... statfs64("/mnt", 84, {f_type="NFS_SUPER_MAGIC", f_bsize=32768, f_blocks=9158253, f_bfree=5093460, f_bavail=5093460, f_files=0, f_ffree=0, f_fsid={0, 0}, f_namelen=255, f_frsize=4096}) = 0 ... SuSE Linux: strace df -h ... statfs64("/mnt", 84, {f_type="NFS_SUPER_MAGIC", f_bsize=32768, f_blocks=9158253, f_bfree=5093460, f_bavail=5093460, f_files=0, f_ffree=0, f_fsid={0, 0}, f_namelen=255, f_frsize=32768}) = 0 ...I have no solution, but an explanation: Looking at the code for PHP's filestat.c we see: When statfs is called, size is bytestotal = f_blocks * f_bsize When statvfs is called, size is bytestotal = f_blocks * f_frsize Looking at the system trace, which shows statfs, indicates f_bsize is used, looking at what PHP actually shows for disk_total_space indicates f_frsize is used in the calculation. The problem with RedHat Linux seems to be that is has statvfs, but this calls statfs internally. This is a problem, it confuses PHP about what block size parameter to use for space calculations. I add the following lines to the function disk_total_space in ext/standard/filestat.c and re-compiled php: #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS) syslog(LOG_INFO, "# include <sys/statvfs.h>\n"); #elif defined(HAVE_SYS_STATFS_H) && defined(HAVE_STATFS) syslog(LOG_INFO, "# include <sys/statfs.h>\n"); #elif defined(HAVE_SYS_MOUNT_H) && defined(HAVE_STATFS) syslog(LOG_INFO, "# include <sys/mount.h>\n"); #endif The following command: strace /dot/dc/bin/php-5.2.0-logging/bin/php -r 'echo number_format(disk_total_space("/mnt")) . "\n";' will show: .. statfs("/mnt", {f_type="NFS_SUPER_MAGIC", f_bsize=32768, f_blocks=9158253, f_bfree=5093336, f_bavail=5093336, f_files=0, f_ffree=0, f_fsid={0, 0}, f_namelen=255, f_frsize=4096}) = 0 .. and the this appears in /var/log/messages: Mar 24 14:02:20 dc5ora10gr2 php: # include <sys/statvfs.h> I haven't looked at the source code for df but somehow it is able to cope with it.