do_open() 手続き

午前中お休み頂いてたりします。だらだらしつつ読む。
それにしても手続きの中身の理解が微妙。
ざっくりな条件分岐的には以下?

  • block_device なオブジェクトの bd_openers 属性が 0
    • デバイス番号の範囲の先頭か (part が 0)
    • それ以外
  • block_device なオブジェクトの bd_openers 属性が 0 でない

みたいな分岐になっている模様。
# 本当かなぁ。なんとなく微妙なカンジ ...

block_device オブジェクトの bd_openers 属性

これって 3rd Edition によれば _ブロック型デバイスがオープンされている回数_ って記述がありますが、このカウンタを操作してるのはどこなんだ、と find|xargs grep 中ですが、どうなる事やら。

$ find|xargs grep bd_openers
./drivers/block/rd.c:   if (bdev->bd_openers <= 2) {
./drivers/block/rd.c:           bdev->bd_openers++;
./drivers/block/aoe/aoe.h:      u16 nopen;              /* (bd_openers isn't available without sleeping) */
./include/linux/fs.h:   int                     bd_openers;
./fs/block_dev.c:       if (!bdev->bd_openers) {
./fs/block_dev.c:                       if (!bdev->bd_openers) {
./fs/block_dev.c:       bdev->bd_openers++;
./fs/block_dev.c:       if (!--bdev->bd_openers) {
./fs/block_dev.c:       if (!bdev->bd_openers) {
./block/ioctl.c:                        if (bdevp->bd_openers) {
$

む。++ しとるのは do_open() の中か。-- しとるのは __blkdev_put() の中ですな。ちょっとこちらは保留で。
そりゃええんですが、基本的に mount 時の動作を見てる、という意味では

  • そのデバイスを最初の mount したのであれば bd_openers は 0
  • 既に mount 済みのデバイスを別なマウントポイントに mount したのであれば、bd_openers は 0 ではない

ってコトになるのかなぁ。bd_contains 属性に着目してみると 3rd Edition では _パーティションの場合にはディスク全体のブロック型デバイスディスクリプタを指し、パーティション以外の場合は、このブロック型ディスクリプタ自身を指す。_ とあって、確かに

  • 最初に bdev を bdev->bd_contains に代入
		bdev->bd_contains = bdev;
  • パーティションの場合 (part が 0 以外)、全体を取得して bdev->bd_contains に代入
			struct block_device *whole;
			whole = bdget_disk(disk, 0);
			ret = -ENOMEM;
			if (!whole)
				goto out_first;
			BUG_ON(for_part);
			ret = __blkdev_get(whole, file->f_mode, file->f_flags, 1);
			if (ret)
				goto out_first;
			bdev->bd_contains = whole;

つーのはなんとなく分かりますな。

そろそろ

お昼なので出勤準備。