IBM Support

Why Numbers from "du -s" and "df" Disagree

Technote (FAQ)


Question

Why Numbers from "du -s" and "df" Disagree

Answer

This document describes why numbers returned by du -s and df are inconsistent. The document applies to AIX Versions 5L and above.

About du -s and df
The problem
Why the numbers do not add up
The ls command

About du -s and df

Notice du and df report on only the blocks allocated for data actually written. The ls command reports slightly different results depending on the type of file. See the section in this document, "The ls command".

NOTE: Both df and du default to 512-byte units. All units in following discussion are in 512-byte blocks.


The problem

Sometimes du and df are used to get a free block value: df is used to report the total block count, and then the value returned by du -s /filesystem_path is subtracted from that total to calculate the free block value. However, this method of calculation yields a value that is greater than the free block value reported by df.

For example, sample output from executing du -s /tmp is as follows:

   12920   /tmp
Sample output from executing df /tmp on the same system is as follows:
Filesystem    512-blocks      Free  %Used    Iused  %Iused  Mounted on
/dev/hd3           57344     42208    26%      391      4%  /tmp

Here, the <total from df> - <used from du> = <false free block count>: 57344 - 12920 = 44424.

44424 is greater than 42208. The reason for this discrepancy involves the implementation of du and df.

du -s

du -s traverses the file tree, adding up the number of blocks allocated to each directory, symlink, and file as reported by the stat() system call. This is how du arrives at its total value.

df

df looks at the file system disk block allocation maps to arrive at its total and free values.


Why the numbers do not add up

The file system allocates some of the disk blocks in the file system to record its data. This data is referred to as meta data. Meta data is not visible to most user-level programs. Examples of meta data are inodes, disk maps, indirect blocks, and super blocks.

  1. du is an example of a user-level program that is not aware of file system meta data, while df looks at the file system disk allocation maps and is aware of file system meta data. df obtains the true file system statistics, whereas du sees only a partial picture. For example, an empty 4MB JFS file system created with frag=4096 and nbpi=4096 has the following meta data allocated:
       1  4k block for the LVM
       2  4k super blocks
       2  4k blocks for disk maps
       2  4k blocks for inode maps
       2  4k blocks for .indirect
       32 4k blocks for inodes
       -------------------------
       41 4k blocks for meta data on an empty 4MB file system
    

    Executing du /foo returns output like the following:

       8       /foo/lost+found
       16      /foo
    

    The sixteen 512-byte blocks reported by du on this empty file system are the blocks used by the root directory.

    To get the output from du to match that from df, we must add in the meta data. First, convert 41 4K blocks to 512-byte units:

        41 * 8 = 328
        328(meta data) + 16(from du) = 344
    
    So there are 344 512-byte blocks allocated on this empty file system. For example:
        8192(total blocks) - 344(used from du + meta data) = 7848
    

    This value does match the output from the free column reported by df /foo.

      Filesystem  512-blocks  Free   %Used   Iused   %Iused   Mounted on
      /dev/lv01         8192  7848      5%      16       2%   /foo
    

    This calculation was easy to perform on an empty file system. However, on a non-empty file system, the meta data for file indirect blocks comes into play and such calculations are tedious and impractical.

    In conclusion, du -s produces a value that reflects the number of disk blocks that are allocated to files and directories. df reports on the actual allocation state of the file system. The true allocation state includes both user data (files and directories) plus meta data.

  2. Another example that contributes to a difference between du and df is the following:

    If someone is running an application with a file open in a directory and the open file is removed, the du output reflects a reduced size for this directory. However, df does not show a reduced size because all blocks in the file system remain allocated until the application that has the file open closes the file. After the file closure, df shows reduced usage for the file system.

  3. One last example that can account for a difference between df and du is shown with the fuser command:

    # fuser -dV /mntpt will give you information about files that have been deleted, but for whatever reason AIX still has a process holding onto the inode number. This space will be reclaimed after the process has closed the inode. This can be done by stopping the process or killing it.

    Ex:  # fuser -dV /var
    /var:
    inode=880    size=2348561      fd=1      344238
    # ps -ef | grep 344238
    root  344238       1   0   Feb 06      -  0:22 /usr/lpp/veritas
    # kill 344238
    # fuser -dV /var  
    /var:
    

    So with the process killed off, the space should be allocated back and df should show up differently.


The ls command

The following compares ls output with that of du and df for sparse files.

  • ls gives data on individual files based on the difference between the end-of-file (the largest offset where data is written) and the beginning-of-file, whether or not blocks were actually allocated to the file. A 32MB file (as reported by ls) may not have 32MB of data written to it if the data is not written sequentially.
  • du shows the blocks actually allocated to an individual file.
  • df shows the blocks allocated in the entire file system, including inodes and other meta data.

An example sparse file can be created fairly easily. To do so, open the file, seek to a large address, and write some data. This can be demonstrated with the dd command, as follows:

  1. Create a regular file.
        date > notsparse
        ls -l
    

    The output of the ls command will be similar to the following:

        total 8
        -rw-r--r--   1 root     sys         29 Dec 21 08:12 notsparse
    
  2. Use the fileplace command to see how many allocated and unallocated blocks are included in the file notsparse.

    NOTE: The Base Performance Tools fileset (bos.perf.tools) contains this command.

        fileplace notsparse
    

    The output for AIX Version 4.x will look similar to the following:

        File: notsparse  Size: 29 bytes  Vol: /dev/lv03
        Bkl Size: 4096  Frag size: 4096 Nfrags: 1 Compress: no
        Logical Fragment
        ----------------
        00716                   1 frags        4096 bytes,  100.0%
    
  3. The du command also reflects how many 512-byte blocks a file occupies.
        du -rs *
    

    Example output looks similar to the following:

        8 notsparse
    
  4. Now create a sparse file using the regular file notsparse as input, as shown in the following:
        touch sparse.1
        dd if=notsparse of=sparse.1 seek=100
    

    Example output looks similar to the following:

        dd: 0+1 records in.
        dd: 0+1 records out.
    

    The dd command takes the data from the regular file and places it, in 100 512-byte blocks, into the sparse.1 file. Nothing is written to the initial 99 512-byte blocks. The following steps show the characteristics of the resulting file.

  5. The ls command reports the distance from block zero to the last block in the file:
        ls -l
    

    Example output looks similar to the following:

        total 16
        -rw-r--r--  1 root   sys       29 Dec 21 08:12 notsparse
        -rw-r--r--  1 root   sys    51229 Dec 21 08:13 sparse.1
    
  6. The fileplace command accurately reports what blocks are unallocated and allocated. For example:
        fileplace sparse.1
    

    Example output for AIX Version 4.1 looks similar to the following:

        File: sparse.1  Size: 51229 bytes Vol: /dev/lv03
        Blk Size: 4096  Frag Size: 4096  Nfrags: 1  Compress: no
        Logical Fragment
        ----------------
        unallocated               12 frags  49152 Bytes,  0.0%
        0000769                    1 frags   4096 Bytes, 100.0%
    

    The du command reports the number of allocated blocks the file takes. For example:

        du -rs *
    

    The example output looks similar to the following:

        8 notsparse
        8 sparse.1
    

    Each command correctly reports the data that is specific to its intended purpose. ls shows the range of offsets where data can be read from or written to a file. Reading from an offset where no data is written makes it appear to be zero-filled. du and df report only blocks allocated for data actually written.

NOTE: For more information about sparse files refer to the document, "About Sparse Files," located at the following URL:
http://www.ibm.com/support/docview.wss?uid=isg3T1000145.


Known defects

There is a defect that affects JFS2 filesystems that have NFS-exported a directory to NFS clients.
IV92529: SPACE NOT FREED WHEN NFS ACCESSED FILE IS DELETED
This APAR only affects JFS2 filesystems on AIX 7.2 only.

Historical Number

isg1pTechnote0705

Document information

More support for: AIX family

Software version: 6.1, 7.1

Operating system(s): AIX

Reference #: T1000401

Modified date: 20 June 2007


Translate this page: