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

2020-05-22 00:00:00 索引 节点 目录 调用 内存

然后是gt_look_up(在namei.c中定义)

static struct dentry *gt_lookup(struct inode *dir,struct dentry *dentry,struct nameidata *nd){
struct inode *inode=NULL;
ino_t ino=;
dentry->d_op=dir->i_sb->s_root->d_op;
if(dentry->d_name.len>GT_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
struct page *page;

struct gt_dir_entry *de=gt_find_entry(dentry,&page);
if(de){
ino=de->ino;
gt_put_page(page);
}
if(ino){
inode=gt_iget(dir->i_sb,ino);
if(IS_ERR(inode))
return ERR_CAST(inode);
}
d_add(dentry,inode);
return NULL;
}

顾名思义,这个函数就是要在dir目录里寻找名为dentry->d_name.name的目录项,只不过这个寻找的过程由gt_find_entry完成,如果寻找到的话,则调用gt_iget,读入该目录项对应的索引节点。并且调用d_add函数将该目录项链入索引节点。

gt_find_entry(在dir.c中定义)

struct gt_dir_entry * gt_find_entry(struct dentry *dentry,struct page **res_page){
const char *name=dentry->d_name.name;
int namelen=dentry->d_name.len;
struct inode *dir=dentry->d_parent->d_inode;//父目录

unsigned long n;
unsigned long npages=gt_dir_pages(dir);
struct page *page=NULL;
char *p;

char *namx;
__u32 inumber;
*res_page=NULL;

for(n=;n<npages;n++){
char *kaddr,*limit;
page=gt_get_page(dir,n); //获取到父目录代表文件在内存中的第n页
if(IS_ERR(page))
continue;
kaddr=(char *)page_address(page);
limit=kaddr+gt_last_byte(dir,n)-sizeof(struct gt_dir_entry);
for(p=kaddr;p<=limit;p=gt_next_entry(p)){
struct gt_dir_entry *de=(struct gt_dir_entry *)p;
namx=de->name;
inumber=de->ino;
if(!inumber)//如果该目录项没有被使用,跳过
continue;
if(namecompare(namelen,GT_NAME_LEN,name,namx))//判断是否匹配
goto found;//如果匹配则调到found处
}
gt_put_page(page);
}
return NULL;
found:
*res_page=page;//设置参数返回值
return (struct gt_dir_entry *)p;
}

这段代码和我们之前看过的代码很象,都是循环遍历,所以也没什么好讲的
接下来是
gt_iget(在inode.c中定义) 

struct inode *gt_iget(struct super_block *sb,unsigned long ino){

struct gt_inode_info *gi;
struct buffer_head *bh;
struct gt_inode *raw_inode;

long ret=-EIO;

struct inode *inode=iget_locked(sb,ino);

if(!inode)
return ERR_PTR(-ENOMEM);
if(!(inode->i_state &I_NEW))
return inode;
gi=GT_I(inode);

raw_inode=gt_raw_inode(inode->i_sb,ino,&bh);
if(!raw_inode){
iput(inode);
return NULL;
}

inode->i_mode=raw_inode->i_mode;
inode->i_uid=(uid_t)raw_inode->i_uid;
inode->i_gid=(gid_t)raw_inode->i_gid;
inode->i_size=raw_inode->i_size;
inode->i_nlink=raw_inode->i_nlinks;
inode->i_rdev=raw_inode->i_dev;
inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = raw_inode->i_ctime;
inode->i_mtime.tv_nsec = ;
inode->i_atime.tv_nsec = ;
inode->i_ctime.tv_nsec = ;

gi->i_dtime=raw_inode->i_dtime;

if(inode->i_nlink== && (inode->i_mode==||gi->i_dtime)){

brelse(bh);
ret=-ESTALE;
goto bad_inode;
}

inode->i_blocks=raw_inode->i_blocks;
gi->i_dtime=;
gi->i_start_block=raw_inode->i_start_block;
gi->i_end_block=raw_inode->i_end_block;
gi->i_blocks=raw_inode->i_blocks;
gi->i_reserved=raw_inode->i_reserved;

gt_set_inode(inode,inode->i_rdev);
brelse(bh);
unlock_new_inode(inode);

return inode;
bad_inode:
iget_failed(inode);
return ERR_PTR(ret);
}

这个函数首先调用iget_locked来在内存中寻找超级块sb中索引节点号是ino的索引节点,如果找到就返回,如果找不到就在内存中分配一个inode结构,并且设置其索引节点号和状态,如果iget_locked返回的VFS索引节点的状态为新,说明这个VFS索引节点是在iget_locked中新分配的,需要从磁盘读入磁盘索引节点来填充VFS索引节点和内存索引节点,于是接着调用gt_raw_inode,对VFS索引节点和内存索引节点进行设置,于是,这个函数通过参数指定的超级块和索引节点号,返回在代表这个索引节点的VFS索引节点 

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

 


相关文章