ext3_fill_super() 手続き (2)

帰宅後、着手したら lookup_bdev() が隣りの emacs で開かれている。関数定義直上に記述されているコメントが以下。

/**
 * lookup_bdev  - lookup a struct block_device by name
 *
 * @path:	special file representing the block device
 *
 * Get a reference to the blockdevice at @path in the current
 * namespace if possible and return it.  Return ERR_PTR(error)
 * otherwise.
 */

渡される path はext3_get_sb() に渡される dev_name な模様。デバイスファイルのパスと類推。
処理的には

  • path_lookup() で nameidata 構造体オブジェクトを取得
  • nameidata オブジェクトの dentry 属性なオブジェクトの inode 属性を使ってエラーチェック
  • bd_acquire() 手続きで block_devide 構造体オブジェクトを取得して戻す

みたいなカンジ。
とりあえず path_lookup() はリキが必要な模様なので 3rd Edition に詳細な説明があるんで今回はスルーで。とりあえず include/linux/namei.h に定義されている nameidata 構造体の定義を以下に。

struct nameidata {
	struct dentry	*dentry;
	struct vfsmount *mnt;
	struct qstr	last;
	unsigned int	flags;
	int		last_type;
	unsigned	depth;
	char *saved_names[MAX_NESTED_LINKS + 1];

	/* Intent data */
	union {
		struct open_intent open;
	} intent;
};

bd_acquire() を掘ってみます。inode オブジェクトを渡して block_device オブジェクトが戻される模様。inode 構造体の i_bdev とか i_rdev って何でしょ。
処理の流れ的には

  • inode オブジェクトの i_bdev 属性 (ブロックデバイス情報) が NULL ではなかったら そのブロックデバイスに対応する inode の参照カウントを上げて return
  • 上記 i_bdev 属性が NULL な場合、i_rdev 属性を bdget() 手続きに渡して block_device オブジェクトを取得
    • i_rdev 属性は dev_t 型でデバイス番号との注釈が入っている
    • bdget() は i_rdev から block_device なオブジェクトを (生成できれば) 生成して適度に属性を設定して戻す手続きと勝手読み

次は blkdev_get() 手続き

一連の記述を以下に引用。

static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags,
			int for_part)
{
	/*
	 * This crockload is due to bad choice of ->open() type.
	 * It will go away.
	 * For now, block device ->open() routine must _not_
	 * examine anything in 'inode' argument except ->i_rdev.
	 */
	struct file fake_file = {};
	struct dentry fake_dentry = {};
	fake_file.f_mode = mode;
	fake_file.f_flags = flags;
	fake_file.f_path.dentry = &fake_dentry;
	fake_dentry.d_inode = bdev->bd_inode;

	return do_open(bdev, &fake_file, for_part);
}

int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags)
{
	return __blkdev_get(bdev, mode, flags, 0);
}
EXPORT_SYMBOL(blkdev_get);

do_open() は fs/block_dev.c の do_open() かなぁ。あ、おなじファイルだな。直上だ。ちょっとこれ、現時点で意味不明。
なんとなくな類推ですが、do_open() に渡される block_device オブジェクトの属性なデバイス番号を get_gendisk() 手続きに渡して gendisk なオブジェクトを戻してもらって、それを block_device オブジェクトの bd_disk 属性に設定?
このあたり、細部を掘りすぎると微妙な気もしてますが本当かどうかは微妙。
明日もあるので中途半端ですが、今日はこれで終わり。