[文件系统] 一个简单文件系统的实现(5)
接下来是超级块操作(定义在super.c中)
static const struct super_operations gt_sops={
.alloc_inode =gt_alloc_inode,//分配一个GTFS的索引节点
.destroy_inode =gt_destroy_inode,//销毁索引节点
.write_inode =gt_write_inode,//写入索引节点
.delete_inode =gt_delete_inode,//删除索引节点
.write_super =gt_write_super,//将超级块写入磁盘
.put_super =gt_put_super,//释放超级块
.statfs =gt_statfs,//获取文件系统状态
.write_inode =gt_write_inode,//将索引节点写入磁盘
};
下面我们挨个介绍
gt_alloc_inode(定义在super.c中)
static struct inode *gt_alloc_inode(struct super_block *sb){
struct gt_inode_info *gi;
gi=(struct gt_inode_info *)kmem_cache_alloc(gt_inode_cachep,GFP_KERNEL);//在缓冲池分配一个GTFS的内存索引节点
if(!gi)
return NULL;
return &gi->vfs_inode;
}
函数gt_destroy_inode(定义在super.c中)
static void gt_destroy_inode(struct inode *inode){
kmem_cache_free(gt_inode_cachep,GT_I(inode));
}
从缓冲池中释放GTFS的内存中索引节点
GT_I是定义在gt.h中的一个inline函数,根据VFS索引节点返回GTFS的内存索引节点
static inline struct gt_inode_info *GT_I(struct inode *inode){
return container_of(inode,struct gt_inode_info,vfs_inode);
}
然后是gt_write_inode(定义在super.c中)
static int gt_write_inode(struct inode *inode,int wait){
brelse(gt_update_inode(inode));
return ;
}
可见,gt_write_inode函数调用gt_update_inode来将内存中的索引节点写入磁盘
gt_update_inode(定义在inode.c中)
struct buffer_head *gt_update_inode(struct inode *inode){
struct gt_inode_info *gi=GT_I(inode);
struct super_block *sb=inode->i_sb;
ino_t ino=inode->i_ino;
uid_t uid=inode->i_uid;
gid_t gid=inode->i_gid;
struct buffer_head *bh;
struct gt_inode *raw_inode =gt_raw_inode(sb,ino,&bh);//根据超级块和索引节点号从磁盘读入GTFS的磁盘索引节点
if(!raw_inode)
return NULL;
/*更新*/
raw_inode->i_mode=inode->i_mode;
raw_inode->i_uid=uid;
raw_inode->i_gid=gid;
raw_inode->i_nlinks=inode->i_nlink;
raw_inode->i_size=inode->i_size;
raw_inode->i_atime=inode->i_atime.tv_sec;
raw_inode->i_mtime=inode->i_mtime.tv_sec;
raw_inode->i_ctime=inode->i_ctime.tv_sec;
//raw_inode->i_dtime=inode->i_dtime.tv_sec;
if(S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
raw_inode->i_dev=old_encode_dev(inode->i_rdev);
else{
raw_inode->i_start_block=gi->i_start_block;
raw_inode->i_end_block=gi->i_end_block;
raw_inode->i_blocks=gi->i_blocks;
raw_inode->i_reserved=gi->i_reserved;
}
mark_buffer_dirty(bh);//将磁盘索引节点所在的缓冲块标记为脏
return bh;
}
gt_update_inode很简单,通过调用gt_raw_inode来读入GTFS的磁盘索引节点,然后根据GTFS内存索引节点去设置磁盘索引节点,后将磁盘索引节点所在的缓冲块标记为脏,等待机会写入磁盘。gt_raw_inode将在后面介绍,我们回到超级块操作来
接下来是gt_delete_inode(定义在super.c中)
static void gt_delete_inode(struct inode *inode){
truncate_inode_pages(&inode->i_data,);
GT_I(inode)->i_dtime=get_seconds();
inode->i_size=;
gt_truncate(inode);//清空文件
gt_free_inode(inode);//释放索引节点
}
让我们来看看gt_truncate(定义在inode.c中)
void gt_truncate(struct inode *inode){
if(!(S_ISREG(inode->i_mode)||S_ISDIR(inode->i_mode)||S_ISLNK(inode->i_mode)))
return;
struct gt_inode_info *gi=GT_I(inode);
block_truncate_page(inode->i_mapping,inode->i_size,gt_get_block);
gi->i_reserved+=gi->i_end_block-gi->i_start_block+1;//设置预留块数
gi->i_end_block=gi->i_start_block;//清空
inode->i_mtime=inode->i_ctime=CURRENT_TIME_SEC;
mark_inode_dirty(inode);
}
这个函数主要是设置内存索引节点的块使用状况
还有gt_free_inode(定义在inode.c中)
void gt_free_inode(struct inode *inode){
struct super_block *sb=inode->i_sb;
struct gt_super_block *gs=GT_SB(inode->i_sb)->s_gs;
struct buffer_head *bh;
unsigned long ino;
ino=inode->i_ino;
struct gt_inode *raw_inode=NULL;
if(ino<1||ino>gs->s_inodes_count){
printk("gt_free_inode: inode 0 or nonexistent inode\n");
return;
}
raw_inode=gt_raw_inode(sb,ino,&bh);
if(raw_inode){
raw_inode->i_nlinks=;//设置磁盘索引节点的连接数
raw_inode->i_mode=0;
}
if(bh){
mark_buffer_dirty(bh);
brelse(bh);
}
clear_inode(inode);//调用VFS函数清理VFS索引节点
}
这个函数也很简单,只是读取磁盘索引节点,然后设置连接数和模式,然后标记磁盘索引节点所在的缓冲块为脏
文章来源CU社区:[文件系统] 一个简单文件系统的实现
相关文章