[DESCRIPTION]
也许你在测试时无意中发现虽然把/data或/cache填满了,无法再写入数据,但是透过stat查看分区文件系统状态,free blocks并不等于0.
kernel-3.10 ext4模块本身会预留2%左右的分区存储空间做reserved空间,专门为ext4自己保留。在super.c (kernel-3.10\fs\ext4)的ext4_calculate_resv_clusters()这个函数中有以下这段code:
[C/C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
/*
* By default we reserve 2% or 4096 clusters, whichever is smaller.
* This should cover the situations where we can not afford to run
* out of space like for example punch hole, or converting
* uninitialized extents in delalloc path. In most cases such
* allocation would require 1, or 2 blocks, higher numbers are
* very rare.
*/
resv_clusters = ext4_blocks_count(EXT4_SB(sb)->s_es) >>
EXT4_SB(sb)->s_cluster_bits;
do_div(resv_clusters, 50);
resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096);
|
这段code就是计算ext4预留空间大小的。EXT4_SB(sb)->s_cluster_bits的值一般为0,可以看到最终预留的空间是取分区空间的2%和4096的最小值,也就说最多会预留4096个block(4096bytes ),也就是16MB。
(1) system分区
执行busybox的stat -f /system会印出类似以下的信息:
# ./stat -f /system
File: "/system"
ID: d3609fe804970d6b Namelen: 255 Type: ext2/ext3
Block size: 4096
Blocks: Total: 380892 Free: 139835 Available: 135739
Inodes: Total: 98304 Free: 95634
这里Free - Available = 4096 blocks,即16MB,因为system分区一般size较大(大于1GB),预留2%多半会超过16MB,因此会预留最多4096个block,即16MB。
(2)cache分区
cache分区一般size比较小,100~400MB之间,目前L版本常见的是400MB,以预留2%来计算的话,应该会预留的是8MB,以下的例子就是对应这种情况。
# ./stat -f /cache
File: "/cache"
ID: d3609fe804970d6b Namelen: 255 Type: ext2/ext3
Block size: 4096
Blocks: Total: 99186 Free: 99085 Available: 97037
Inodes: Total: 25600 Free: 25585
这里Free - Available = 2048 blocks,即8MB
(3) data分区
data分区一般size较大(大于1GB),与system分区类似,按照理论分析应该也是要预留16MB才对,实际执行stat后的结果如下:
./stat -f /data
File: "/data"
ID: d3609fe804970d6b Namelen: 255 Type: ext2/ext3
Block size: 4096
Blocks: Total: 3232930 Free: 2911026 Available: 2902834
Inodes: Total: 827392 Free: 825699
Free - Available = 8192 blocks,即32MB
很奇怪,这里为什么变成了32MB呢?
为了防止data分区被普通的APP填满,MTK对/data分区额外做了空间预留,具体就是在init.mt6XXX.rc里面的以下这段:
on fs
write /proc/bootprof "INIT:Mount_START"
mount_all /fstab.mt6735
exec /system/bin/tune2fs -O has_journal -u 10010 -r 4096 /dev/block/platform/mtk-msdc.0/by-name/userdata
tune2fs会为uid <=10010的process再额外预留4096个blocks,即16MB。tune2fs这里会设置super block里面的s_r_blocks_count字段,这个字段在创建ext4 fs时默认值为0。
(4) Internal SD
在开启MTK_SHARED_SDCARD的情况下,Internal SD与/data会共享userdata的存储空间。但是////中default会预留50MB,防止APP写internal sd时把/data填满。
[C/C++]
1
|
#define DATA_FREE_SIZE_TH_DEFAULT (50UL*1024UL*1024UL)
|
如果有需求的话, 可以对这里预留的空间做客制化修改。
同样对internal sd执行stat
# ./stat -f /mnt/shell/emulated
File: "/mnt/shell/emulated"
ID: 0 Namelen: 255 Type: UNKNOWN
Block size: 4096
Blocks: Total: 3220130 Free: 2898219 Available: 2890027
Inodes: Total: 827392 Free: 825696
Free - Available = 8192 blocks,也是差32MB。
这是因为internal sd的Free和Available都是基于/data的Free和Available直接减去50MB得到的。
data Free - internal sd Free = 2911026 - 2898219 = 12807 blocks (50MB)
对于Internal SD来说,当Available为0时,这时候实际上还是可以写入数据的,直到Free为0为止。
因此建议APP call getFreeBlocks()来获取Internal SD的剩余空间,而不是getAvailableBlocks()。
而对于data来说,由于Linux Kernel会额外做限制,因此建议APP是call getAvailableBlocks()来获取/data的剩余可用空间,而不是getFreeBlocks()。