ino(nodeid)缓存
数据结构
nodeid具体包含在fuse请求的包头中:
- //用户读取包头
-
struct fuse_in_header{
-
__u32 len;//包含数据头包长度
-
__u32 opcode;//包的请求操作码
-
__u64 unique;//请求id
-
__u64 nodeid;//与操作相关的节点id
-
__u32 uid;//请求用户的user id
-
__u32 gid;//请求用户所在组id
-
__u32 pid;//请求的进程id
-
__u32 pidding;//填充字符
-
-
}
在fuse中用于缓存的对象定义如下:
- struct node {
-
struct node *name_next;//按name进行hash
-
struct node *id_next;//按nodeid(ino)进行hash
-
fuse_ino_t nodeid;//索引节点号
-
unsigned int generation;
-
int refctr;//!!是否删除该节点的关键所在
-
struct node *parent;//父节点(ino)形式产生
-
char *name;//文件名
-
uint64_t nlookup;//查看次数,每find一次自增,unlink一次自减
-
int open_count;//打开次数,open,create自增,release自减
-
struct timespec stat_updated;//mtime修改,更新时间
-
struct timespec mtime;//每次有关文件属性操作时都将该文件属性设置为属性修改时间参数
-
off_t size;//相关联文件的大小
-
struct lock*locks;//文件锁,具体到起始位置,偏移量,配合操作setlk,getlk
-
unsigned int is_hidden:1;//当节点被重命名或者删除时,需要使用此项
-
unsigned int cache_valid:1;//是否缓存有效
-
//同步访问标志
-
int treelock;
-
int ticket;
-
}
内核inode分配
在fuse内核模块中,当需要分配一个索引节点时,就会出现nodeid初始化(VFS需要分配索引节点时,就会调用此函数):
- static struct inode *fuse_alloc_inode(struct super_block* sb)
-
{
-
struct inode *inode;
-
struct fuse_inode *fi;
-
//通过slab分配器获取一个inode节点(大小实际为fuse_inode)
-
inode = kmem_cache_alloc(fuse_inode_cachep,GFP_KERNEL);
-
if(!node)
-
return NULL;
-
//获取fuse_inode
-
fi = get_fuse_inode(inode);
-
//文件属性有效的时间
-
fi->i_time = 0;
-
//用于区别inode,全局唯一
-
fi->nodeid = 0;
-
//在该索引节点查看的次数
-
fi->nlookup = 0;
-
//上一次版本修改时间
-
fi->attr_version = 0;
-
//文件数据页
-
LIST_INIT_HEAD(&fi->write_files);
-
fi->forget_req = fuse_request_alloc();
-
if(!fi->forget_req) {
-
kmem_cache_free(fuse_inode_cachep,inode);
-
return NULL;
-
}
-
return inode;
-
}
其实这里只是进行最低级的初始化,具体的赋值操作还需要等到客户端去完成,在fuse挂载时,服务器需要生成root索引节点,VFS通过函数fuse_fill_super实现:
- static int fuse_fill_super(struct super_block *sb,void *data,int silent)
-
{
-
struct inode *root;
-
…............
-
//分配根节点:root.ino = FUSE_ROOT_ID
-
root = get_root_inode(sb,d.rootmate);
-
if(!root)
-
goto err;
-
//将根节点存入缓存
-
root_dentry = d_alloc_root(root);
-
if(!root_dentry) {
-
iput(root);
-
goto err;
-
}
-
sb->s_root = root_dentry;
-
…....
-
//向客户端发送初始化请求
-
fuse_send_init(fc,init_req);
-
}
客户端nodeid
客户端方向在新建一个fuse对象(运行程序时就进行创建),通过调用函数 fuse_new_common实现:
- struct fuse *fuse_new_common(/*参数省略*/)
-
{
-
…......
-
root = (struct node *)calloc(1,sizeof(struct node));
-
….......
-
root ->name = strdup(“/”);
-
…......
-
//进行初始化,同时写入缓存中
-
root ->parent = NULL;
-
root ->nodeid = FUSE_ROOT_ID;
-
root ->generation = 0;
-
root -> refctr = 1;
-
root -> nlookup = 1;
-
hash_id(f,root);
-
return f;
-
}
添加nodeid
当内核出现调用lookup调用请求时lookup请求时,就生成nodeid,并进入缓存中:
op():session调用op
--->do_lookup:fuse_lowlevel.c do_lookup
---->fuse_lib_lookup:fuse.c
原型如下:
- //在父节点parent中查找文件name
-
static void fuse_lib_lookup(fuse_req_t req,fuse_ino_t parent,const char* name)
-
{
-
//从req中提取出fuse文件结构
-
struct fuse *f = req_fuse_prepare(req);
-
struct fuse_entry_param e;//用于回复的数据
-
char *path;
-
int err;
-
struct node *dot = NULL;
-
if(name[0]=='.') {//指向本身,parent则表示文件本身
-
int len = strlen(name);
-
if(len ==1|| (name[1]=='.'&&len==2)) { //或者指向父文件夹,parent则表示文件本身
-
pthread_mutex_lock(&f->lock);
-
if(len==1) {
-
//如果指向的是本身
-
…...
-
//在本身节点nodeid中查找node
-
dot = get_node_nocheck(f,parent);
-
if(dot==NULL) {
-
pthread_mutex_unlock(&f->lock);
-
reply_entry(req,&e,-ESTALE);
-
return;
-
}
-
//引用自增
-
dot->refctr++;
-
} else {
-
…..
-
//获取该节点的父节点nodeid
-
parent = get_node(f,parent)->parent->nodeid;
-
}
-
pthread_mutex_unlock(&f->lock);
-
name = NULL;
-
}}
-
//通过在父索引节点parent中查找name文件,并返回绝对路径
-
err = get_path_name(f,parent,name,&path);
-
if(!err) {
-
struct fuse_intr_data d;
-
….....
-
//检查是否产生中断并注册中断回调处理函数
-
fuse_prepare_interrupt(f,req,&d);
-
//获取name属性,并加入两个缓存中
-
err = lookup_path(f,parent,name,path,&e,NULL);
-
…....
-
//同样检查是否产生中断,处理回调,不同的是,一个没有在完成之前,一个完成之后
-
fuse_finish_interrupt(f,req,&d);
-
free_path(f,parent,path);
-
}
-
if(dot) {
-
pthread_mutex_lock(&f->lock);
-
//上面计数增加,现在计数自减,如果为0从缓存中删除该节点,这里删除只是假设assert(!node->name),这个
-
//用于保证unhash_name必须在这之前调用
-
unref_node(f,dot);
-
pthread_mutex_unlock(&f->lock);
-
}
-
//回复至内核
-
reply_entry(req,&e,err);
-
}
查找节点
静态查找node节点:static struct node* lookup_node(struct fuse*
f,fuse_ino_t parent,const char* name);
动态查找node节点(查找失败就装入缓存):static struct node* find_node(struct fuse*
f,fuse_ino_t parent,const char* name);同时写入两个缓存name_table,id_table
修改节点
nodeid部分:
增加引用(使用)计数:
hash_name(struct
fuse* f,struct node* node,fuse_ino_t parentid,const char* name)
减少引用(使用)计数:
unref_node(struct
fuse*f,struct node*node)//如果计数为0,删除该节点
从name_table删除节点(调用unhash_name实现)
static void
unlink_node(struct fuse *f,struct node* node)
从node父节点中删除该node选项
unhash_name(struct
fuse *f,struct node *node);
生成nodeid
static fuse_ino_t
nexid(struct fuse *f)
阅读(2683) | 评论(0) | 转发(0) |