毎日コードリーディング: ADFS の inode.c

Linux の fs/ 直下にある 78 ディレクトリを巡る企画です。今回も ADFS を取り上げます。

前回fs/adfs/file.c を読みました。そこでは、通常ファイルの読み書きに Linux カーネルの汎用関数が使われていました。一方、inode の属性を変更する setattr には、ADFS 固有の名前を持つ adfs_setattr が登録されていました。そこで、adfs_setattr が定義されている fs/adfs/inode.c を見ていこうと思います。

使用した Linux は、2026 年 8 月 2 日時点で手元にチェックアウトしていた v7.1-2727-g8b308f96484e です。

まず目に入ったのは、adfs_aops です。

static const struct address_space_operations adfs_aops = {
	.dirty_folio	= block_dirty_folio,
	.invalidate_folio = block_invalidate_folio,
	.read_folio	= adfs_read_folio,
	.writepages	= adfs_writepages,
	.write_begin	= adfs_write_begin,
	.write_end	= generic_write_end,
	.migrate_folio	= buffer_migrate_folio,
	.bmap		= _adfs_bmap,
};

address_space_operations は、ページキャッシュの読み書きなどに使う処理を登録する構造体です。

関数名だけを見ると、adfs_read_folioadfs_writepagesadfs_write_begin など、前回の file.c より ADFS 固有の処理が多そうです。中身を追うのはまた今度にします。また今度、が多いですね。まあ Linux という巨大なソフトウェアを追っている以上しゃーなし。

次に、前回の file.c で気になっていた adfs_setattr を見ます。

関数の先頭は次のようになっています。

int
adfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr)
{
	struct inode *inode = d_inode(dentry);
	struct super_block *sb = inode->i_sb;
	unsigned int ia_valid = attr->ia_valid;
	int error;

struct super_block はスーパーブロックを表し、ファイルシステム全体の管理情報を保持します。一方、inode はファイルごとのメタデータを保持します。このスーパーブロックと inode についても後日記事にします。(やるやる詐欺万歳)

さらに、その次に attr->ia_valid をコピーした ia_valid という変数があります。この ia_valid は、その後のコードを見ると、

	if (ia_valid & ATTR_SIZE)
		truncate_setsize(inode, attr->ia_size);

のように使われています。 この ATTR_SIZE がどこで定義されているのかを見ると、include/linux/fs.h に以下のように書かれています。

#define ATTR_MODE	(1 << 0)
#define ATTR_UID	(1 << 1)
#define ATTR_GID	(1 << 2)
#define ATTR_SIZE	(1 << 3)
#define ATTR_ATIME	(1 << 4)
#define ATTR_MTIME	(1 << 5)
#define ATTR_CTIME	(1 << 6)

これらは、ビット演算で扱うフラグです。attr には変更する属性の値が入り、そのうちどの値が有効なのかを ia_valid が表します。ia_validATTR_SIZE が立っていたら、「ファイルサイズを変えるよー」という指定が来たと判断し、attr->ia_size の値を使って inode のサイズを変更します。

なお、ADFS では、ファイルごとに異なる UID や GID を設定できません。各ファイルの UID と GID には、スーパーブロックに保持されたファイルシステム共通の値が使われます。

adfs_setattr が扱っている属性は、次のとおりです。

  • size
  • mtime(ADFS のタイムスタンプを持つ inode のみ)
  • atime
  • ctime
  • mode

ファイルごとには変更できない属性は、次のとおりです。

  • uid
  • gid

ただし、size には、実際のディスク上の切り詰め処理が一部未実装というコメントがあります。また、atimectimeinode 上では更新されますが、ADFS 上には表現できないとコメントされています。

そして最後に、ia_validATTR_SIZEATTR_MTIMEATTR_MODE のいずれかの変更指定が含まれていた場合のみ、

	if (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MODE))
		mark_inode_dirty(inode);

inode を dirty としてマークし、後の書き戻し対象にします。

今日はここまでです。

今日見たファイルは fs/adfs/inode.c です。

次はメモリか、ADFS の続きを見ていこうかな。