fileystem_stat is not working correctly with NFS filesystems under Linux (at least kernel v2.6, glibc 2.3.4). Specifically block size is not correct. In my case I get
blocksize 4096 while in actuality the block size is 32768. The 4096 is, according to the Linux statvfs manual page, the fragment size. I don't know if this is a Linux specific issue, but it might be (google says this field is "fundamental block size" in various UNIX flavors, but it's unclear to me what that means). Anyhow, the app below works correctly under Linux, but I don't know if it works on other systems.
#include <sys/vfs.h> /* or <sys/statfs.h> */ #include <sys/statvfs.h> #include <stdio.h>
int main(int argc, char *argv[]) { struct statvfs st; if(argc != 2) { return 1; } statvfs(argv[1], &st); printf("Free blocks: %d, Blocksize: %ld, fragment size: %ld, Free GB: %f\n", (int)st.f_bavail, st.f_bsize, st.f_frsize, ((float)st.f_bavail * st.f_bsize) / (1024.0 * 1024.0 * 1024.0)); return 0; }
In the last episode (Feb 01), David Hedbor @ Pike developers forum said:
fileystem_stat is not working correctly with NFS filesystems under Linux (at least kernel v2.6, glibc 2.3.4). Specifically block size is not correct. In my case I get
blocksize 4096 while in actuality the block size is 32768. The 4096 is, according to the Linux statvfs manual page, the fragment size. I don't know if this is a Linux specific issue, but it might be (google says this field is "fundamental block size" in various UNIX flavors, but it's unclear to me what that means). Anyhow, the app below works correctly under Linux, but I don't know if it works on other systems.
#include <sys/vfs.h> /* or <sys/statfs.h> */ #include <sys/statvfs.h> #include <stdio.h>
int main(int argc, char *argv[]) { struct statvfs st; if(argc != 2) { return 1; } statvfs(argv[1], &st); printf("Free blocks: %d, Blocksize: %ld, fragment size: %ld, Free GB: %f\n", (int)st.f_bavail, st.f_bsize, st.f_frsize, ((float)st.f_bavail * st.f_bsize) / (1024.0 * 1024.0 * 1024.0)); return 0; }
f_bavail should be multiplied by f_frsize, not f_bsize, I think. Solaris, Linux, FreeBSD, and Tru64 all agree that f_blocks, f_bavail, and f_bfree are in f_frsize units. The statfs() function uses a slightly different (better imho) naming convention:
uint64_t f_bsize; /* filesystem fragment size */ uint64_t f_iosize; /* optimal transfer block size */
where all the other block-count fields are in f_bsize units, and f_iosize is what you would use when creating a database, for example.
The problem is, if I multiply with m_f_frsize, I get the incorrect value for the NFS mounted partitions (this is the value Pike is providing as the blocksize). It's possible a special condition is needed under Linux to rectify this issue locally.
It's definitely invalid to do as my test program does on Solaris, but it IS required to get the correct value in Linux.
pike-devel@lists.lysator.liu.se