FreeBSD 9.0 文件系统的默认 fragment size 是 4096

今天发现在一台小硬盘的 FreeBSD 9.0 虚拟机上启动 vi 时报错:

% vi

/: create/symlink failed, no inodes free
ex/vi: Error: Unable to create temporary file: No space left on device

检查了一下硬盘容量,貌似这个虚拟机只用了53%的硬盘,应该还有足够的空间啊:

% df -h
Filesystem     Size    Used   Avail Capacity  Mounted on
/dev/ada0p3    5.7G    2.8G    2.4G    53%    /
devfs          1.0k    1.0k      0B   100%    /dev

仔细看错误信息发现是文件系统 no inodes free,应该是文件系统的 inode 不够了,df -i 查看 inode 用了100%,没了可用的 inode 也就不能创建文件了。

% df -i
Filesystem  1K-blocks    Used   Avail Capacity iused ifree %iused  Mounted on
/dev/ada0p3   5939036 2916144 2547772    53%  378873     5  100%   /
devfs               1       1       0   100%       0     0  100%   /dev

用 newfs 查看当前文件系统设置发现 fragment size 4096. 查看 newfs 命令的帮助文件得知 FreeBSD 9.0 下的 fragment size 和 block size 默认分别为32768和4096字节,是 FreeBSD 8.2(8192和1024字节)时的4倍(难怪以前在小硬盘上用 FreeBSD 8.2 的时候没遇到这个问题):

# newfs -N /dev/ada0p3
/dev/ada0p3: 5892.9MB (12068736 sectors) block size 32768, fragment size 4096
	using 8 cylinder groups of 740.00MB, 23680 blks, 47360 inodes.
super-block backups (for fsck -b #) at:
 192, 1515712, 3031232, 4546752, 6062272, 7577792, 9093312, 10608832

% man newfs
...
EXAMPLES
           newfs /dev/ad3s1a

     Creates a new ufs file system on ad3s1a.  The newfs utility will use a
     block size of 32768 bytes, a fragment size of 4096 bytes and the largest
     possible number of blocks per cylinders group.  These values tend to pro‐
     duce better performance for most applications than the historical
     defaults (8192 byte block size and 1024 byte fragment size).  This large
     fragment size may lead to much wasted space on file systems that contain
     many small files.
...

查看源码 freebsd/sbin/newfs/newfs.h 再次确认了 FreeBSD 9.0 下文件系统的 fragment size 和 block size 默认大小:

/*
 * The following two constants set the default block and fragment sizes.
 * Both constants must be a power of 2 and meet the following constraints:
 *      MINBSIZE <= DESBLKSIZE <= MAXBSIZE
 *      sectorsize <= DESFRAGSIZE <= DESBLKSIZE
 *      DESBLKSIZE / DESFRAGSIZE <= 8
 */
#define DFL_FRAGSIZE    4096
#define DFL_BLKSIZE     32768

现在要想办法改变 block size, fragment size,增加 inode 数目,/dev/ada0p3 分区刚好是 root 分区,只能重装了,分区的时候记得在分区格式化步骤的时候带上初始化参数,在动手之前 man newfs 仔细看看帮助文件里对 -b -f -i 等参数的说明:

# man newfs

# newfs -U -b 4096 -f 512 -i 2048 /dev/ada0p3

Linux 文件系统从 ext3 升级到 ext4

尽管 ext4 出来已经有一段时间了,由于有一些 bug 还没被大量应用到服务器生产环境中,不过对于桌面用户来说 ext4 已经足够成熟了。去年发布的最新 RHEL 5.4 版本默认文件系统依然是 ext3。 最近 Linux 内核开发人员、ext4 文件系统的维护者 Ted Ts’o 跳槽到 Google,并在 Google 继续从事 ext4 的研发和 Linux kernel 方面的工作。在一篇 mailing list 里,Google 工程师 Michael Rubin 也提到了一些 Google 内部使用 ext4 的情况。经过 Google 内部测试,ext4 和高性能的 xfs 文件系统性能很接近,Google 选择 ext4 而不是 xfs 的主要原因是因为他们的现有系统是 ext2,这样升级到 ext4 会更容易一些。还有一个有意思的地方是,大多数人对 dbench 很信任,选用 dbench 来做文件系统的测试工具。

如何从 ext3 升级到 ext4?首先需要确保 Linux kernel 是支持 ext4 的,其次要注意 /boot 分区最好使用 ext3,因为现在系统上的 grub 很可能不支持 ext4,需要有这个 commit 的特别版本 grub 才能支持 ext4. 用下面的命令转换:

# cd /; umount /dev/sda1
# tune2fs -O extents,uninit_bg,dir_index /dev/sda1

记住,转换成 ext4 后必须用 fsck 扫描,否则不能 mount,-p 参数说明 “自动修复” 文件系统:

# fsck -pf /dev/sda1

挂载 ext4 文件系统:

# mount -t ext4 /dev/sda1 /path/to/