[文件系统] 一个简单文件系统的实现(3)

2020-05-21 00:00:00 函数 磁盘 文件系统 根目录 读入

文件系统的实现还需要对超级块的操作,对文件的操作,索引节点操作等等
我们就先从挂载一个文件系统开始
挂载文件系统时候,VFS会通过mount命令中的文件系统类型或超级块魔数来寻找file_system_type结构
下面就是GTFS的file_system_type结构(定义在super.c中)

static struct file_system_type gt_fs_type ={
.owner =THIS_MODULE,
.name ="gt",//文件系统名称
.get_sb =gt_get_sb,//读取超级块方法
.kill_sb =kill_block_super,
.fs_flags =FS_REQUIRES_DEV,
};

我们只需要完成gt_get_sb(定义在super.c中)方法即可

static int gt_get_sb(struct file_system_type *fs_type,
int flags,const char *dev_name,void *data,struct vfsmount *mnt){
return get_sb_bdev(fs_type,flags,dev_name,data,gt_fill_super,mnt);
}

从gt_get_sb函数可以看出,这个函数调用了get_sb_bdev函数,get_sb_bdev又调用了gt_fill_super函数
gt_fill_super函数才是正真用来读取超级块的方法

static int gt_fill_super(struct super_block *sb,void *data,int silent){

struct buffer_head *bh;
struct gt_super_block *gs;
struct gt_sb_info *sbi;
struct inode *root;//设备的根目录

unsigned long sb_block=1;//超级块的块号为1,第块为启动块

long ret=-EINVAL;

int blocksize=BLOCK_SIZE;//BLOCK_SIZE为1024

sbi=kzalloc(sizeof(struct gt_sb_info),GFP_KERNEL);
if(!sbi)
return -ENOMEM;

if(!sb_set_blocksize(sb,BLOCK_SIZE))//设置VFS超级块的块大小
goto out_bad_hblock;
if(!(bh=sb_bread(sb,sb_block))){//将GTFS超级块所在的块读入内存
printk("GT-fs:unable to read superblock\n");
goto failed_sbi;
}

gs=(struct gt_super_block *)(bh->b_data);
sbi->s_sbh=bh;//指向从磁盘读入的GTFS超级块所在的缓冲区
sbi->s_gs=gs;//将内存中的GTFS超级块和从磁盘读入的GTFS超级块联系起来
sb->s_fs_info=sbi;//将VFS超级块和GTFS的超级块联系起来
sb->s_magic=gs->s_magic;//设置魔数

if(sb->s_magic !=GT_SUPER_MAGIC)
goto cantfind_gt;

blocksize=GT_BLOCK_SIZE;

sb->s_op=>_sops;

root=gt_iget(sb,GT_ROOT_INO);//GT_ROOT_INO为1,读入文件系统的根目录
if(IS_ERR(root)){
ret=PTR_ERR(root);
printk(KERN_ERR "GT-fs: can't find root inode\n");
goto failed_mount;
}
if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
iput(root);
printk(KERN_ERR "isdir?%d,root->i_blocks=%d,root->i_size=%d\n",S_ISDIR(root->i_mode) , root->i_blocks, root->i_size);
printk(KERN_ERR "GT-fs: corrupt root inode\n");
goto failed_mount;
}

sb->s_root = d_alloc_root(root);//设置超级块的根目录
if (!sb->s_root) {
iput(root);
printk(KERN_ERR "GT: get root inode failed\n");
ret = -ENOMEM;
goto failed_mount;
}

return ;
cantfind_gt:
printk("VFS: Can't find an gt filesystem on dev %s.\nmagic on dev is %d and magic of GT is %d\n",sb->s_id,sb->s_magic,GT_SUPER_MAGIC);
failed_mount:
brelse(bh);
out_bad_hblock:
printk("GT-fs:blocksize too small for device\n");
failed_sbi:
sb->s_fs_info=NULL;
kfree(sbi);
return ret;
}

这段函数主要是从磁盘读入文件系统的超级块,用来填充内存中的GTFS超级块,和VFS超级块
调用gt_iget函数读入指定文件系统的根目录。

文章来源CU社区:[文件系统] 一个简单文件系统的实现

相关文章