为什么 GNU Core Utilities stat(包括 du 和 ls)报告以下大小(GNU/Linux 中的 ext4)?

Klo*_*rax 6 ls filesystems disk-usage coreutils stat

如果我在目录中有以下内容:

  • empty_dir: 空目录。
  • empty_file: 空的文件。
  • one_char: 由一个字符组成的文件。
  • several_blocks:由几个块组成的文件(但不是“太大”或“稀疏”)。

然后,ls将显示以下†:

$ ls -Gghs
total 152K
8,0K drwxr-xr-x 2 4,0K dec 21 23:34 empty_dir
4,0K -rw-r--r-- 1    0 dec 21 23:21 empty_file
8,0K -rw-r--r-- 1    1 dec 21 23:22 one_char
132K -rw-r--r-- 1 127K dec 22 00:14 several_blocks
Run Code Online (Sandbox Code Playgroud)

其次,stat显示以下内容:

$ stat empty_dir/
  File: empty_dir/
  Size: 4096            Blocks: 16         IO Block: 4096   directory
  ...

$ stat empty_file 
  File: empty_file
  Size: 0               Blocks: 8          IO Block: 4096   regular empty file
  ...

$ stat one_char 
  File: one_char
  Size: 1               Blocks: 16         IO Block: 4096   regular file
  ...

$ stat several_blocks 
  File: several_blocks
  Size: 129760          Blocks: 264        IO Block: 4096   regular file
  ...
Run Code Online (Sandbox Code Playgroud)

第三,du显示以下内容:

$ du -h empty_dir/
8,0K    empty_dir/

$ du -h empty_file 
4,0K    empty_file

$ du -h one_char 
8,0K    one_char

$ du -h several_blocks 
132K    several_blocks
Run Code Online (Sandbox Code Playgroud)

最后:

$ tune2fs /dev/nvme0n1p2 -l
...
Block size:               4096
...
Inode size:               256
...
Run Code Online (Sandbox Code Playgroud)

通过报告块的大小stat为512 B,这意味着之间的输出statlsdu是一致的:

  • empty_dir:16 * 512 / 1024 = 4096 + 4096 = 8 KiB。
  • empty_file:8 * 512 / 1024 = 0 + 4096 = 4 KiB。
  • one_char:16 * 512 / 1024 = 4096 + 4096 = 8 KiB。
  • several_blocks: 264 * 512 / 1024 = 129760 + 5408 = 129760 + 1312 + 4096 = 131072 + 4096 = 32 * 4096 + 4096 = 132 KiB。

问题

  1. 为什么分配的大小empty_dirone_char两块(4096尺寸B的),而不是一个?
  2. 为什么分配的大小是empty_file一个块而不是零?
  3. 为什么为several_blocks(以及一般较大的文件)分配的大小比表观大小((264 * 512) - 129760 = 5408 > 4096)大一个以上的块?

我怀疑附加块是包含 的块inode,就像这个提问者所问的那样(但没有得到答复)。类似地,这个提问者观察到了双倍大小,但它在问题中被错误地表述并收到了问题另一部分的答案。然而,这个对不同问题的回答表明不应该有额外的块(这是我的直觉)。

  1. 我们的系统是否配置不正确?
  2. 假设包含的块inode被计数:当du在多个文件上使用时,它是否会补偿inode多次计算块,多个块应该inodes在同一个块中(因为一个块可以包含 16 inodes(4096 / 256 = 16))?

附录

@WumpusQ.Wumbley 推测它可能是扩展属性,事实证明确实如此!

getfattr返回user.com.dropbox.attributes。原来测试目录是一个目录深处的子目录,该目录象征性地链接到我的Dropbox文件夹中。请参阅下面接受的答案。


这在 GNU/Linux 上使用 GNU Core Utilities 8.30,在 NVME SSD 上的 ext4 上使用内核 4.19.1 (Manjaro)。

Klo*_*rax 4

@WumpusQ.Wumbley 在评论中指出了原因:扩展属性

为了完整起见,答案如下。

扩展属性,在本例中由Dropbox应用(getfattr返回user.com.dropbox.attributes),使用额外的块进行存储。如果没有这些扩展属性 ls(和其他命令),则返回:

$ 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
Run Code Online (Sandbox Code Playgroud)

正如预期的那样。

此外,stat对于唯一有趣的several_blocks回报情况:

$ stat several_blocks 
  File: several_blocks
  Size: 129760          Blocks: 256        IO Block: 4096   regular file
  ...
Run Code Online (Sandbox Code Playgroud)

这也符合预期,因为 256 * 512 - 129760 = 1312 < 4096,即没有使用额外的块。

  1. 由于扩展属性
  2. 由于扩展属性
  3. 由于扩展属性
  4. 否,但请注意应用程序添加的扩展属性
  5. 错误的假设。