Charles Salvia
Charles Salvia

Reputation:

Discrepancy between call to statvfs and df command

When I use the statvfs command on a Linux machine to get the available free space on a mounted file system, the number I get is slightly different than what is reported by df.

For example, one on machine I have with a 500G hard drive, I get the following output from df:

# df --block-size=1 --no-sync
Filesystem           1B-blocks      Used Available Use% Mounted on
/dev/md0             492256247808 3422584832 463828406272   1% /
tmpfs                2025721856         0 2025721856   0% /lib/init/rw
varrun               2025721856    114688 2025607168   1% /var/run
varlock              2025721856      4096 2025717760   1% /var/lock
udev                 2025721856    147456 2025574400   1% /dev
tmpfs                2025721856     94208 2025627648   1% /dev/shm

A call to statvfs gives me a block size of 4096 and 119344155 free blocks, so that there should be 488,833,658,880 bytes free. Yet, df reports there are 463,828,406,272 bytes free. Why is there a discrepancy here?

Upvotes: 10

Views: 8704

Answers (3)

Peter Whittaker
Peter Whittaker

Reputation: 162

Note that under Linux, df uses stat on the device file, not statvfs; cf the coreutils source.

However, the basic principle above applies. As to why df is so much faster and whether there are any shortcuts available for du....

The filesystem entry for any specific folder contains information about that folder only: how much space is allocated for the folder itself, and how space is allocated for the file system entries for the files and folders in that folder - it does not contain the total space occupied by that folder and all of its subfolders.

To get that information, du has to list all of the folders in the original folder, all of their folders, and so on, totalling as it goes.

So du will return very quickly for a folder without subfolders, and ever more slowly for folders with increasing numbers of subfolders.

Contrast that with df, with a call to stat(3) against a device file, or with a call to statfs(2) or statvfs(3) against any file on a device, etc., all of which return information about the specific device/filesystem immediately.

du can only rival the speed of df in the case of being called against a single file, where both du and df are making a single system call and doing very little math.

Upvotes: 0

Bruce_Warrior
Bruce_Warrior

Reputation: 1181

#include <stdio.h>
#include <sys/statvfs.h>
int main(){
    struct statvfs stat;
    int a=statvfs("/",&stat);
    printf("total free disk space of the partition: %d GB \n",(stat.f_bavail)*8/2097152);
    //512 is 2^9 - one half of a kilobyte. 
    //A kilobyte is 2^10. A megabyte is 2^20. A gigabyte is 2^30. A terabyte
    //is 2^40. And so on. The common computer units go up by 10's of powers
    //of 2 like that.
    //So you need to divide by 2^(30-9) == 2^21 == 2097152 to get gigabytes.
    //And multiply by 8 because 1 byte=8bit
    return 0;
}

I do in this form because I prefer the outcome in Gb, but you can modify the units changing the exponent.And is true the first answer, as you can see, I use that too

Upvotes: 0

ynimous
ynimous

Reputation: 5142

Since your discrepancy is close to 5% [1], which is the default percentage allocated for root, there is a possibility that you compare the df result with the ->f_bfree of statvfs and not with ->f_bavail, which is what df uses.

[1]: (488833658880 - 463828406272)/492256247808 = 0.0508

Upvotes: 11

Related Questions