ext4 分区大小/可用空间差异

Mes*_*ion 15 filesystem partitioning ext4 gparted

在为我的数据创建 250GiB 备份分区时,我注意到 Nautilus、gParted、df、tune2fs 等中报告的分区大小和可用空间之间存在很多差异。

起初我以为是 GiB/GB 混淆。不是

然后我认为它可能是 ext4 的保留块。不是

我完全不解。这里有一些图片。以下是步骤:

  • 第一,NTFS。524288000 个扇区 x 512 字节/扇区 = 268435456000 字节 = 268.4 GB = 250 GiB。

在此处输入图片说明 在此处输入图片说明

Nautilus 说“总容量:250.0 GB ”(即使它实际上是 GiB,而不是 GB)。除了那个小小的贴错标签,到目前为止,还不错

  • 现在,使用 gparted 格式化为 ext4 的相同分区:

在此处输入图片说明

首先,Last 和 Total 扇区相同。它是相同的 250GiB 分区。使用的大小是 4.11GiB(可能是保留块?)

在此处输入图片说明

不。看起来保留块是 12.7 GiB(~5%。哎哟!)。但是......为什么总容量现在只有 246.1 GiB ???. 这种差异(有点)与 gparted 报告的 4.11 GiB 相匹配。但是......如果它不是来自保留块,它是什么?为什么 gparted 没有报告 12.7GiB 的已用空间?

$ df -h /dev/sda5
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda5             247G  188M  234G   1% /media/BACKUP
Run Code Online (Sandbox Code Playgroud)

df在报告的可用空间中匹配 Nautilus。但是..只用了188M?不应该是~12GB吗?总容量仍然是错误的。所以我跑去tune2fs寻找一些线索。(不相关的输出被省略)

$ sudo tune2fs -l /dev/sda5
tune2fs 1.41.12 (17-May-2010)
Filesystem volume name:   BACKUP
Filesystem UUID:          613d592e-47f5-4206-96a7-210090d340ef
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash 
Filesystem state:         clean
Filesystem OS type:       Linux
Block count:              65536000
Reserved block count:     3276800
Free blocks:              64459851
First block:              0
Block size:               4096
Run Code Online (Sandbox Code Playgroud)

65536000 总块 * 4096 字节/块 = 268435456000 字节 = 268.4 GB = 250 GiB。它匹配 gparted。

3276800 个保留块 = 13421772800 字节 = 13.4 GB = 12.5 GiB。它(再次,有点)匹配 Nautilus。

64459851 个空闲块 = 264027549696 字节 = 264.0 GB = 245.9 GiB。为什么?不应该是 250-12.5 = 237.5 (或 250-(12.5+4.11)=~233) 吗?

删除保留块:

$ sudo tune2fs -m 0 /dev/sda5
tune2fs 1.41.12 (17-May-2010)
Setting reserved blocks percentage to 0% (0 blocks)

$ sudo tune2fs -l /dev/sda5
tune2fs 1.41.12 (17-May-2010)
Filesystem volume name:   BACKUP
Filesystem UUID:          613d592e-47f5-4206-96a7-210090d340ef
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash 
Filesystem state:         clean
Filesystem OS type:       Linux
Block count:              65536000
Reserved block count:     0
Free blocks:              64459851
Block size:               4096
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,相同的块数,0 个保留块,但是...相同的空闲块我不是刚刚释放了 12.5 GiB 吗?

$ df -h /dev/sda5
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda5             247G  188M  246G   1% /media/BACKUP
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

看起来我做到了。可用空间从 233 GiB 增加到 245.9 GiB。gparted 根本不在乎,显示完全相同的信息!(没用发布相同的屏幕截图)

多么大的混乱啊!

我尽量把它记录下来......所以,有人能给我任何关于这里发生了什么的线索吗?

  • NTFS -> ext4 格式中缺少的那些神秘的 4.11 GiB 是什么?
  • 为什么 gparted、Nautilus、tune2fs、df 之间有这么多差异?
  • 我的数学有什么问题?(粗体问题分散了这篇文章)

任何帮助表示赞赏。虽然我无法弄清楚发生了什么,但我正在认真考虑放弃 ext4,转而支持 NTFS,除了我的 / 分区之外的所有内容。

谢谢!

psu*_*usi 14

这里发生了一些事情。gparted 报告实际使用/可用空间。内核通过保留空间减少可用计数。删除保留空间后,空闲计数没有变化,因为保留块已经空闲;只是不允许非root用户侵入该空间,以防止他们通过填满磁盘而造成麻烦。由于一个错误,侏儒数字有点不稳定。它不是报告内核报告的已用空间(和 df 显示),而是通过从总数中减去可用空间来计算它。这会导致它显示已使用的保留空间。

实际使用的缺少的 4GB 是 ext4 的 fs 开销。NTFS 最初只为 MFT 分配少量空间,然后根据需要增加空间。但是,ext 系列文件系统在格式化时为 inode 表(大致相当于 MFT)分配空间并且它不能增长。报告的总空间中缺少的空间是 inode 表。剩余的已用空间来自日志(通常为 128 mb )并调整 inode 的大小。


enz*_*tib 7

首先,保留块不是用于文件系统内部管理的块。

保留块只是为 保留root,以确保使用该分区上的文件的服务不会被某些非管理员用户填充所有空间而排除空间。

即使没有保留块 ( -m 0) 也总是有一部分空间用于文件系统内部管理,我不能说有多少,我没有这么深的知识。

此外,Gparted是作为 执行的root,因此它将保留块视为空闲块。以用户身份执行的Nautilus将它们视为非自由的。

好的,@psusi 的回答很清楚,我没有什么要补充的。


Car*_*ood 5

使用 gparted 对我的全新 8 TB 磁盘进行分区后,它报告:

  Size: 7.28 TiB
  Used: 59.76 GiB   <-- Huh?
Unused: 7.22 TiB
Run Code Online (Sandbox Code Playgroud)

这就是我最终来到这里的原因。现在让调查开始吧。

运行sudo fdisk /dev/sdc(其中 /dev/sdc 是我的新磁盘)显示:

Disk /dev/sdc: 7,3 TiB, 8001563222016 bytes, 15628053168 sectors
Units: sectors of 1 * 512 = 512 bytes
...
Disklabel type: gpt
Run Code Online (Sandbox Code Playgroud)

请注意,15628053168 * 512 = 8001563222016。

从现在开始,让我们以扇区数(512 字节)进行工作,并专门使用十六进制表示法。这给了我们,

fdisk (real values)
Disk size: 3a3812ab0
Run Code Online (Sandbox Code Playgroud)

此外,fdisk 还为我们提供了分区表:

Device     Start         End     Sectors  Size Type
/dev/sdc1   2048 15628052479 15628050432  7,3T Linux filesystem
Run Code Online (Sandbox Code Playgroud)

让我们也将其转换为十六进制(它已经在扇区中):

/dev/sdc1    800   3a38127ff   3a3812000  7.277378082275390625 TiB
Run Code Online (Sandbox Code Playgroud)

(TiB 值是精确的;但是是十进制的。它说明了为什么打印 7.3)。

前 0x800 扇区保留为主引导记录 (MBR) 和分区表(类型为 gpt,因为它是由 gparted 创建的,我选择在那里使用该类型)。

End行业具有包容性,因此确实如此

3a38127ff + 1 - 800 = 3a3812000
Run Code Online (Sandbox Code Playgroud)

但为什么选择这个呢?嗯,因为 gparted 将所有内容四舍五入到 1 MiB 边界(它说),这恰好是 0x800 扇区(十六进制 1024 * 1024 / 512)。

然而,为什么它不选择 3a3812fff 作为最后一个扇区呢?嗯,因为它不存在,所以磁盘总大小是 3a3812ab0,正如我们之前看到的。

好的,所以我们需要在 MBR 和分区表的开头留出一点空间,但只想在 0x800 边界处开始和结束分区,因此第一个扇区是 800,最后一个扇区是 3a38127ff。导致分区总大小为 3a3812000 个扇区,或 gparted 报告的 7.28 TiB(十进制为 8001561821184 字节)。

它的文件系统类型是ext4。

让我们从安装它开始,现在让我们在 DECIMAL 中的扇区中工作:

sudo mount -t ext4 /dev/sdc1 /mnt/newdisk
df -B512 | grep sdc1
/dev/sdc1 15502817864 102728 14721279848  1% /mnt/newdisk
Run Code Online (Sandbox Code Playgroud)

因此 df 以扇区和十六进制报告:

df Size: 15502817864 sectors (= 7937442746368 bytes = 7.219... TiB).
df Used: 102728 sectors (= 52596736 bytes = 50.16 MiB).
df Available: 14721279848 sectors (= 7537295282176 bytes = 6.855... TiB).
Run Code Online (Sandbox Code Playgroud)

因此,报告的大小为 8001561821184 - 7937442746368 = 64119074816 = 59.716 GiB,小于fdisk 报告的分区大小!

好的,那么 ext4 是如何工作的呢?

我们可以快速获取大量运行信息

sudo dumpe2fs -h /dev/sdc1
Run Code Online (Sandbox Code Playgroud)

最重要的输出是

Inode count:              244191232
Block count:              1953506304
Reserved block count:     97675315
Free blocks:              1937839392
Free inodes:              244191221
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      558
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         4096
Inode blocks per group:   256
Flex block group size:    16
First inode:              11
Inode size:               256
Required extra isize:     32
Desired extra isize:      32
Journal size:             1024M
Journal length:           262144
Run Code Online (Sandbox Code Playgroud)

请注意,块计数显示完整分区大小。一个块有 4096 字节,我们有 1953506304 * 4096 = 8001561821184。

很明显,我们正在寻找我们无法使用的块。根据df报告为“可用”(7537295282176 / 4096 = 1840159981 个可用块),即 113346323 个块不可用。

该日志存在 262144 个块,因此... 113346323 - 262144 = 113084179 个块。

我们有 558 个保留的 GDT 块...还有 113083621 个块。

fs 上的“组”数量为“inode 总数”/“每组 inode”= 244191232 / 4096 = 59617。

大小为 256 字节的 inode 占 244191232 * 256 / 4096 = 15261952 个块,因此还有 113083621 - 15261952 = 97821669 个块。

我们在这里没有选择,显然保留块计数也不可用,即 97675315 .. 因此,剩下 97821669 - 97675315 = 146354 个块不可用,我们还没有解释。这仍然是 571.7 MiB,或每组约 2.455 个块,但与我们必须解释的 59.76 GiB 相比并没有那么多。

运行以下命令:

cat /proc/fs/ext4/sdc1/mb_groups | sed -e 's/^#.*://' | sort | uniq -c | sort -rn | sed -e 's/^\(..............\).*/\1/' | grep -v free
Run Code Online (Sandbox Code Playgroud)

我们得到有 N 个空闲块(第二列)的组的数量(第一列):

  55860  32768
   3724  28640
     22  31743
      8  0    
      1  8958 
      1  28639
      1  27609
Run Code Online (Sandbox Code Playgroud)

显然,每组的最大空闲块数为 32768(其中大部分),这也是dumpe2fs报告的内容(每组的块数)。

因此,让我通过从 32768 中减去第二列并将其乘以 4096 字节,将此表转换为“已用”(以字节为单位)。然后我得到

   3724  16908288
     22  4198400
      8  134217728
      1  97525760
      1  16912384
      1  21131264
Run Code Online (Sandbox Code Playgroud)

3724 * 16908288 + 22 * 4198400 + 8 * 134217728 + 97525760 + 16912384 + 21131264 = 64268140544 或 59.85 GiB。

概括

Unavailable blocks      Reason
97675315                Reserved block count (5%)
15261952                inodes (0.78%)
262144                  journal (0.013%)
146354                  Unexplained (0.007%)
558                     Reserved GDT blocks (0%)
Run Code Online (Sandbox Code Playgroud)

让我们从将保留块计数更改为 0 开始,因为此 HDD 用于长期存储,我真的不关心如果它满了会发生什么(我关心,但我的系统仍然会完美运行)。

sudo umount /dev/sdc1
sudo tune2fs -r 0 /dev/sdc1
Run Code Online (Sandbox Code Playgroud)

dumpe2fs 现在报告:

Reserved block count:     0
Run Code Online (Sandbox Code Playgroud)

但更重要的是,

df -B512 | grep sdc1
/dev/sdc1 15502817864 102728 15502682368   1% /mnt/newdisk
Run Code Online (Sandbox Code Playgroud)

又名

df Available: 15502682368 sectors (= 7937373372416 bytes = 7.22... TiB)!
Run Code Online (Sandbox Code Playgroud)

我们还可以减少索引节点的数量,但只有当您确定不需要它们时,这才是明智的;例如,当您仅在磁盘上存储大文件时。inode 的数量大致就是磁盘上可以存储的文件+目录的数量。因此,拥有 244191232 将允许我在此磁盘上存储平均大小为 32kB(32504 字节)的文件。相反,我打算在其上存储大小约为 1 到 2 GB 的大部分文件...所以是的,我认为我可以安全地将 inode 数量减少 10 倍。

因此,我决定重新格式化我的分区(螺丝 gparted,我需要的只是分区表,而不是文件系统):

sudo mkfs.ext4 -b 4096 -e remount-ro -i 325040 -j -L '/opt/verylarge' -m 0 -t ext4 -T big -U 48c6a937-aea3-42a0-a69c-c24d0dc65179
Run Code Online (Sandbox Code Playgroud)

之后我结束了

Inode count:              24800672
Block count:              1953506304
Reserved block count:     0
Free blocks:              1951529866
Free inodes:              24800661
First block:              0
Block size:               4096
Fragment size:            4096
Group descriptor size:    64
Reserved GDT blocks:      1024
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         416
Inode blocks per group:   26
Flex block group size:    16
First inode:              11
Inode size:               256
Required extra isize:     32
Desired extra isize:      32
Journal size:             1024M
Journal length:           262144

df -H
Filesystem  Size  Used Avail Use% Mounted on
/dev/sdc1   8,0T   97M  8,0T   1% /mnt/newdisk
Run Code Online (Sandbox Code Playgroud)

我不知道那 1% 从何而来,但我对我的 8.0 TB 感到满意:)