一个简单文件系统的实现
static const struct super_operations gt_sops={
.alloc_inode =gt_alloc_inode,//分配一个GTFS的索引节点
.destroy_inode =gt_destroy_ino
接下来是超级块操作(定义在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 0; } 复制代码 可见,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的磁盘索引节点unix文件系统,然后根据GTFS内存索引节点去设置磁盘索引节点,最后将磁盘索引节点所在的缓冲块标记为脏,等待机会写入磁盘。gt_raw_inode将在后面介绍,我们回到超级块操作来 接下来是gt_delete_inode(定义在super.c中) static void gt_delete_inode(struct inode *inode){ truncate_inode_pages(&inode->i_data,0); GT_I(inode)->i_dtime=get_seconds(); inode->i_size=0; 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(inogs->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=0;//设置磁盘索引节点的连接数 raw_inode->i_mode=0; } if(bh){ mark_buffer_dirty(bh); brelse(bh); } clear_inode(inode);//调用VFS函数清理VFS索引节点 } 复制代码 这个函数也很简单,只是读取磁盘索引节点,然后设置连接数和模式,然后标记磁盘索引节点所在的缓冲块为脏 (编辑:海南站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |