Why does GNU Core Utilities stat (including du and ls) report the following sizes (ext4 in GNU/Linux)?

@WumpusQ.Wumbley pointed out the cause in a comment: extended attributes.

For completeness sake the answers are presented below.

Extended attributes, in this case applied by Dropbox (getfattr returns user.com.dropbox.attributes), uses additional blocks for storage. Without these extended attributes ls (and the other commands) returns:

$ ls -Gghs
total 136K
4,0K drwxr-xr-x 2 4,0K dec 22 20:11 empty_dir
   0 -rw-r--r-- 1    0 dec 22 20:11 empty_file
4,0K -rw-r--r-- 1    1 dec 22 20:12 one_char
128K -rw-r--r-- 1 127K dec 22 20:13 several_blocks

As expected.

In addition, stat for the only interesting case of several_blocks returns:

$ stat several_blocks 
  File: several_blocks
  Size: 129760          Blocks: 256        IO Block: 4096   regular file
  ...

Which is also as expected, since 256 * 512 - 129760 = 1312 < 4096, i.e., no extra block used.

  1. Due to extended attributes.
  2. Due to extended attributes.
  3. Due to extended attributes.
  4. No, but be aware of extended attributes added by applications.
  5. Incorrect assumption.

The "additional blocks" are not due to some inconsistency in configuration. (Hypothetically, it could always be wrong for some other reason though. Like cosmic rays that corrupted your kernel code :-)).

I say this because there is no option to manually tweak details of the calculation of the disk usage for these commands. The commands only convert the disk usage to different units, by multiplying or dividing. The disk usage is obtained by calling the stat() system call. The kernel returns a number of synthetic "blocks", which are always 512 bytes. Nor is there any kernel option that affects how stat() calculates the number of blocks.

I can tell you the block which contains the inode is not supposed to be counted on your ext4 filesystem. In general, Giles says it is not counted on any filesystem that he is aware of. Perhaps in part due to the point you raise :-). Inodes tend to be smaller than the 512-byte blocks reported by stat. ext4 defaults to 256-byte inodes; ext3 defaulted to 128 bytes.

If we look through the related questions (right sidebar), we notice one case where there can be additional blocks. The extent tree (or indirect blocks, if extents are disabled) is counted on ext4. (Why is the difference in file size and it's size on disk bigger than 4 KiB?)

A second answer to the linked question suggests another case. Some uses of fallocate() might allow creating files with an arbitrarily large difference between their size, and the number of blocks allocated to them.

That said, I suspect the above is not sufficient to explain any of your examples.