ext[23] 関連

追いかける深さが増していくにつれ、中身の理解が必要になってきつつある。直前エントリで出てきた ext3_count_free_blocks() 手続き (fs/ext3/balloc.c) の中身を確認してみます。
この手続きは以下のコメントにある通り

/**
 * ext3_count_free_blocks() -- count filesystem free blocks
 * @sb:		superblock
 *
 * Adds up the number of free blocks from each block group.
 */

super block なオブジェクトが渡されて free blocks の数を戻すはず。

色々見てて super block なオブジェクトと ext3 な super block オブジェクトが混濁。参考書で super_block はファイルシステムというある意味抽象化された_mount されたファイルシステムの情報_で、ext3_super_block はこの_mount されたファイルシステムの disk 上の情報_を表現してるって理解で良いのかな。
とりあえず ext3 なファイルシステムの場合

  • super_block の s_fs_info が指しているのは ext3_sb_info オブジェクト
    • このオブジェクトはいくつかのオブジェクトを持っている
  • s_fs_info->s_es が指しているのは ext3_super_block オブジェクト
    • ext3_super_block オブジェクトは ext3 のディスクスーパーブロックな情報

あ、3rd Edition には ext3_sb_info (3rd edition では ext2 なんですが) のメンバな情報が盛り込まれてないのかな。

閑話休題

処理を見ます。とりあえず先頭でブロックグループの数を取得。

ext3_fsblk_t ext3_count_free_blocks(struct super_block *sb)
{
	ext3_fsblk_t desc_count;
	struct ext3_group_desc *gdp;
	int i;
	unsigned long ngroups = EXT3_SB(sb)->s_groups_count;

あと、ext3_group_desc 構造体は ext3 なグループディスクリプタをオブジェクトにしたもの、なはず。定義は include/linux/ext3_fs.h にて以下。

/*
 * Structure of a blocks group descriptor
 */
struct ext3_group_desc
{
	__le32	bg_block_bitmap;		/* Blocks bitmap block */
	__le32	bg_inode_bitmap;		/* Inodes bitmap block */
	__le32	bg_inode_table;		/* Inodes table block */
	__le16	bg_free_blocks_count;	/* Free blocks count */
	__le16	bg_free_inodes_count;	/* Free inodes count */
	__le16	bg_used_dirs_count;	/* Directories count */
	__u16	bg_pad;
	__le32	bg_reserved[3];
};

(+ (* 4 3) (* 4 2) (* 4 3)) なので 32 bytes ですか。これが区画に存在するブロックグループが N 個あれば、という事ですね。で、これが disk のグループディスクリプタな部分に直列に配置されている、という理解で良いのかな。
あるいはこのオブジェクトは ext3_sb_info なオブジェクトの s_group_desc な属性が指す buffer_head 型のポインタ配列の要素が指すのが、上記のオブジェクトなんスか。

続き

これキッツいですね。直前エントリにて核心、という事で引用したコードが以下。

	desc_count = 0;
	smp_rmb();
	for (i = 0; i < ngroups; i++) {
		gdp = ext3_get_group_desc(sb, i, NULL);
		if (!gdp)
			continue;
		desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
	}

	return desc_count;

基本的に繰り返しの中でグループディスクリプタを取り出して ext3_group_desc なオブジェクトの属性な bg_free_blocks_count (空きブロック数) を積算しているのは分かります。以下に ext3_get_group_desc() の主処理な部分を引用。

	unsigned long group_desc;
	unsigned long offset;
	struct ext3_group_desc * desc;
	struct ext3_sb_info *sbi = EXT3_SB(sb);

	group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(sb);
	offset = block_group & (EXT3_DESC_PER_BLOCK(sb) - 1);
	if (!sbi->s_group_desc[group_desc]) {
		ext3_error (sb, "ext3_get_group_desc",
			    "Group descriptor not loaded - "
			    "block_group = %d, group_desc = %lu, desc = %lu",
			     block_group, group_desc, offset);
		return NULL;
	}

	desc = (struct ext3_group_desc *) sbi->s_group_desc[group_desc]->b_data;
	if (bh)
		*bh = sbi->s_group_desc[group_desc];
	return desc + offset;

むむ。(EXT3_SB(s)->s_desc_per_block_bits) とかって見れるはずだな。Debug Hacks 見てみよ。もう日を跨いでるので止めます。