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