子团兄最近在测试ext4的bigalloc特性,cluster为256K,放入了16个大文件,每个文件25GB。反馈我说碎片很多,我觉得很奇怪便问是怎么看出来碎片多的,他说是用fsck看的:

#fsck.ext4 -f -y /dev/sdi1
e4fsck 1.42 (29-Nov-2011)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/sdi1: 27/7631216 files (59.3% non-contiguous), 104148800/488377984 blocks

看起来"non-contiguous“占到了59.3%,似乎碎片很多的样子。
我翻了一下代码,这个值是在e2fsprogs包里计算出来的:

e2fsck/unix.c

static void show_stats(e2fsck_t ctx)
{
....
    frag_percent_total = ((10000 * (ctx->fs_fragmented +
                    ctx->fs_fragmented_dir))
                  / inodes_used);
....

其实就是用该文件系统中"fragmented“的文件数加上"fragmented”的目录数,再除以一共创建出来的inode数(也就是总文件数加总目录数)。但是哪种文件称为"fragmented“呢,看看扫描extent结构的代码:

e2fsck/pass1.c

static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
                             struct process_block_struct *pb,
                             blk64_t start_block, blk64_t end_block,
                             ext2_extent_handle_t ehandle)
{       
....
                if ((pb->previous_block != 0) &&
                    (pb->previous_block+1 != extent.e_pblk)) {
....
                        pb->fragmented = 1;
                }
....

只要这个extent与上一个extent物理块上不是连上的,这个文件就算是"fragmented“了(目录亦如此)。即使用上bigalloc特性,一个cluster配成256KB,那么一个block group就是4K * 8 * 256K = 8G大小,对于25G大小的文件来说,怎么都不可能连续,因为跨block group了,16个大文件那就算16个"fragmented“,除以inode总数27(这个inode总数包括了文件、目录、甚至journal本身也算一个inode)那就是59.3%了。
这样计算出来的"non-contiguous“只能反映非连续文件占总文件数的比例,不能说明磁盘的碎片多与不多。大文件几乎不可能extent相连一点空都不留,但因此就说碎片严重并不合理,因它是由几个不相连的大块组成的;比如一个25G的文件由4个8G的大块组成,我们不能因为它是"fragmented“的就说碎片很严重,毕竟才4个碎片。换个角度,我如果在该ext4里创建100个4KB的小文件,那non-contiguous就是16/127=12.6%,这并不能表示碎片情况变好了,因为多了这么多小文件,其实磁盘上碎片更多了。

要综合评估磁盘的碎片状况到底是好是坏并不容易,推荐的办法是用filefrag -v看看磁盘里某几个大文件的碎片情况,如果它们的碎片很少,而文件系统里的小文件也不多,那基本可以认为磁盘碎片不严重。当然,最彻底的办法是用dumpe2fs查看每个block group里block bitmap被分配的情况。