在分析linux的VFS时, 常常要牵涉到具体的文件系统, minix文件可以说是相当小的, 对于我们分析VFS具有相当的优势.
minix文件系统的物理结构:
- minix文件系统是一种简单而又朴素的文件系统, ext2文件系统可看成是对minix的改进,可以将每一个ext2块组看成一个微型的minix文件系统.
- minix文件系统的块长只允许为1k(系统磁盘块为1k), 第1块为启动块, 第2块为超级块, 从第3块开始,依次为inode位图块组, 数据块位图块组, inode块组, 最后为数据块组.
- minix文件系统的目录项由16位inode编号和定长的文件名区域组成, inode从1开始编号,编号0标记删除的目录项, 编号1为根目录项. 目录项分为16字节版和32字节版,最长文件名分别为14和30.
- minix文件系统的inode分为32字节版(minix_inode)和64字节版(minix2_inode).minix_inode只有1个时戳标记, 用户组号(i_gid)为8位,它包含由9个16位字组成的二重文件索引表. minix2_inode则使用3个文件时戳,16位gid和10个32位字组成的三重文件块索引表.
- 根据目录项和inode尺寸的不同, minix文件系统盘分为4种格式化版本,其s_magic分别为0x137F, 0x138F, 0x2468, 0x2478.
/*
* This is the original minix inode layout on disk.
* Note the 8-bit gid and atime and ctime.
*/
struct minix_inode {
__u16 i_mode;
__u16 i_uid;
__u32 i_size;
__u32 i_time;
__u8 i_gid;
__u8 i_nlinks;
__u16 i_zone[9]; /* 文件所占用的盘上逻辑块号数组, 7,8分别表示一次和二次间接块 */
};
/*
* The new minix inode has all the time entries, as well as
* long block numbers and a third indirect block (7+1+1+1
* instead of 7+1+1). Also, some previously 8-bit values are
* now 16-bit. The inode is now 64 bytes instead of 32.
*/
struct minix2_inode {
__u16 i_mode;
__u16 i_nlinks;
__u16 i_uid;
__u16 i_gid;
__u32 i_size;
__u32 i_atime;
__u32 i_mtime;
__u32 i_ctime;
__u32 i_zone[10];
};
/*
* minix super-block data on disk
*/
struct minix_super_block {
__u16 s_ninodes;
__u16 s_nzones;
__u16 s_imap_blocks;
__u16 s_zmap_blocks;
__u16 s_firstdatazone;
__u16 s_log_zone_size;
__u32 s_max_size;
__u16 s_magic;
__u16 s_state;
__u32 s_zones;
};
/*
* V3 minix super-block data on disk
*/
struct minix3_super_block {
__u32 s_ninodes;
__u16 s_pad0;
__u16 s_imap_blocks;
__u16 s_zmap_blocks;
__u16 s_firstdatazone;
__u16 s_log_zone_size;
__u16 s_pad1;
__u32 s_max_size;
__u32 s_zones;
__u16 s_magic;
__u16 s_pad2;
__u16 s_blocksize;
__u8 s_disk_version;
};
struct minix_dir_entry {
__u16 inode;
char name[0];
};
struct minix3_dir_entry {
__u32 inode;
char name[0];
};
/*块读写*/
#include <linux/buffer_head.h>
struct buffer_head *sb_read(struct super_block *sb, sector_t block);
//return __bread(sb->s_bdev, block, sb->s_blocksize);
// __bread_slow(bh)
// __getblk(bdev, block, size) ->
// __find_get_block
/*
find_get_page
map_bh: 表示此buffer_head与磁盘上的blocknr, size映射.
*/
sb_bread(sb, block) ->
__bread(sb->s_bdev, block, sb->s_blocksize) ->
bh=__getblk(bdev, block, size) ->
__find_get_block(bdev, block, size) ->
lookup_bh_lru(bdev, block, size) //从当前CPU的lru链表中查找@bdev,@block,@size匹配的bh
__find_get_block_slow(bdev, block) //从@bdev设备的所有buffer_head中查找是否有@block匹配的bh
__getblk_slow(bdev, block, size) ->
__find_get_block(bdev, block, size) //再次查找
grow_buffers(bdev, block, size) ->
grow_dev_page(bdev, block, index, size) //为设备增加page及对应的bh,
__bread_slow(bh) ->
submit_bh(bh)
wait_on_buffer(bh)