/proc/sys/vm/block_dump
/proc/sys/vm/block_dumpは、パブリック変数block_dumpを更新します。block_dump!=0だと、bioの入出力/inodeのdirtyを、カーネルログとして出力します。
検証結果です。/dev/sdc0はext2です。
echo hoge > hoge.txtとするだけですが、かなりのブロックが参照されています。hoge.txtのinodeだけでなく、/のinodeのデータブロックにhoge.txtのinode情報を書き込んだり、データブロックだけでなく、かかるinodeを管理するinodeビットマップ/inodeテーブル/とか、使用有無を管理するデータブロック等も更新しなければなりません。
[ 6181.136832] bash(1785): READ block 10 on sbd0 (2 sectors)で、bashがブロック10をsyncでreadしているようです。たぶん/mntのinodeを取得し、立て続けにhoge.txtのinodeを作成するためではと・・・ 後はカーネルスレッドのflushで、dirtyなpageをbioで書き出しています。
まあ、/proc/sys/vm/block_dumpとは、こういう物だということで、fsの構造を調べてみようとされる方は、かかるセクタをbreadして検証されたらと思います。
検証結果です。/dev/sdc0はext2です。
[root@localhost lkm]# echo 1 > /proc/sys/vm/block_dump [root@localhost lkm]# mount /dev/sdc0 /mnt4 [root@localhost lkm]# echo hoge > /mnt4/hoge.txt [root@localhost lkm]# dmesg | grep sbd0 [ 6181.136832] bash(1785): READ block 10 on sbd0 (2 sectors) [ 6181.137088] bash(1785): dirtied inode 12 (hoge.txt) on sbd0 [ 6181.137099] bash(1785): dirtied inode 12 (hoge.txt) on sbd0 [ 6184.016616] sync_supers(17): WRITE block 2 on sbd0 (2 sectors) [ 6211.185818] flush-252:0(1890): WRITE block 4 on sbd0 (2 sectors) [ 6211.185874] flush-252:0(1890): WRITE block 10 on sbd0 (2 sectors) [ 6211.185889] flush-252:0(1890): WRITE block 12 on sbd0 (2 sectors) [ 6211.185900] flush-252:0(1890): WRITE block 14 on sbd0 (2 sectors) [ 6211.185914] flush-252:0(1890): WRITE block 28 on sbd0 (2 sectors) [ 6211.186152] flush-252:0(1890): READ block 8 on sbd0 (2 sectors) [ 6211.186431] flush-252:0(1890): WRITE block 56 on sbd0 (2 sectors) [ 6214.017662] sync_supers(17): WRITE block 2 on sbd0 (2 sectors) [ 6241.230564] flush-252:0(1890): WRITE block 4 on sbd0 (2 sectors) [ 6241.230621] flush-252:0(1890): WRITE block 8 on sbd0 (2 sectors) [ 6241.230636] flush-252:0(1890): WRITE block 14 on sbd0 (2 sectors)submit_bioログフォーマット:プロセス名(プロセスID): WRITE/READ: 参照セクター位置: デバイス名: 参照セクタ数
void submit_bio(int rw, struct bio *bio) { int count = bio_sectors(bio); bio->bi_rw |= rw; if (bio_has_data(bio) && !(rw & REQ_DISCARD)) { if (rw & WRITE) { count_vm_events(PGPGOUT, count); } else { task_io_account_read(bio->bi_size); count_vm_events(PGPGIN, count); } if (unlikely(block_dump)) { char b[BDEVNAME_SIZE]; printk(KERN_DEBUG "%s(%d): %s block %Lu on %s (%u sectors)\n", current->comm, task_pid_nr(current), (rw & WRITE) ? "WRITE" : "READ", (unsigned long long)bio->bi_sector, bdevname(bio->bi_bdev, b), count); } } generic_make_request(bio); } EXPORT_SYMBOL(submit_bio);mark_inode_dirtyログフォーマット:プロセス名(プロセスID): WRITE/READ: inode番号: ファイル名: デバイス名
void __mark_inode_dirty(struct inode *inode, int flags) { struct super_block *sb = inode->i_sb; struct backing_dev_info *bdi = NULL; if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { if (sb->s_op->dirty_inode) sb->s_op->dirty_inode(inode, flags); } smp_mb(); if ((inode->i_state & flags) == flags) return; if (unlikely(block_dump)) block_dump___mark_inode_dirty(inode); spin_lock(&inode->i_lock); if ((inode->i_state & flags) != flags) { const int was_dirty = inode->i_state & I_DIRTY; inode->i_state |= flags; if (inode->i_state & I_SYNC) goto out_unlock_inode; if (!S_ISBLK(inode->i_mode)) { if (inode_unhashed(inode)) goto out_unlock_inode; } if (inode->i_state & I_FREEING) goto out_unlock_inode; if (!was_dirty) { bool wakeup_bdi = false; bdi = inode_to_bdi(inode); if (bdi_cap_writeback_dirty(bdi)) { WARN(!test_bit(BDI_registered, &bdi->state), "bdi-%s not registered\n", bdi->name); if (!wb_has_dirty_io(&bdi->wb)) wakeup_bdi = true; } spin_unlock(&inode->i_lock); spin_lock(&bdi->wb.list_lock); inode->dirtied_when = jiffies; list_move(&inode->i_wb_list, &bdi->wb.b_dirty); spin_unlock(&bdi->wb.list_lock); if (wakeup_bdi) bdi_wakeup_thread_delayed(bdi); return; } } out_unlock_inode: spin_unlock(&inode->i_lock); } EXPORT_SYMBOL(__mark_inode_dirty); static noinline void block_dump___mark_inode_dirty(struct inode *inode) { if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) { struct dentry *dentry; const char *name = "?"; dentry = d_find_alias(inode); if (dentry) { spin_lock(&dentry->d_lock); name = (const char *) dentry->d_name.name; } printk(KERN_DEBUG "%s(%d): dirtied inode %lu (%s) on %s\n", current->comm, task_pid_nr(current), inode->i_ino, name, inode->i_sb->s_id); if (dentry) { spin_unlock(&dentry->d_lock); dput(dentry); } } }__mark_inode_dirty()が2度コールされていることが分かります。新規にinodeを作成時のext2_new_inode()と、データ(hoge)を書き込んだ時(サイズが更新)とで処理かと思います。
echo hoge > hoge.txtとするだけですが、かなりのブロックが参照されています。hoge.txtのinodeだけでなく、/のinodeのデータブロックにhoge.txtのinode情報を書き込んだり、データブロックだけでなく、かかるinodeを管理するinodeビットマップ/inodeテーブル/とか、使用有無を管理するデータブロック等も更新しなければなりません。
[ 6181.136832] bash(1785): READ block 10 on sbd0 (2 sectors)で、bashがブロック10をsyncでreadしているようです。たぶん/mntのinodeを取得し、立て続けにhoge.txtのinodeを作成するためではと・・・ 後はカーネルスレッドのflushで、dirtyなpageをbioで書き出しています。
まあ、/proc/sys/vm/block_dumpとは、こういう物だということで、fsの構造を調べてみようとされる方は、かかるセクタをbreadして検証されたらと思います。