系统初始化
与系统初始化的处理函数如下:
读取的数据结构体为:
- //读入的数据
-
struct fuse_init_in {
-
__u32 major;
-
__u32 minor;
-
__u32 max_readahead;
-
__u32 flags;
-
}
-
//发送的数据
-
struct fuse_init_out {
-
__u32 major;
-
__u32 minor;
-
__u32 max_readahead;
-
__u32 flags;
-
}
-
static void do_init(fuse_req_t req,fuse_ino_t nodeid,const void *inarg)
-
{
-
struct fuse_init_in *arg = (struct fuse_init_in* )arg;
-
struct fuse_init_out outarg;
-
struct fuse_ll *f = req->f;
-
size_t bufsize = fuse_chan_bufsize(req->ch);
-
-
…....
-
//初始化fuse相关的参数
-
f->conn.proto_major = arg->major;
-
f->conn.proto_minor = arg->minor;
-
f->conn.capable = 0;
-
f->conn.want = 0;
-
-
memset(&outarg,0,sizeof(outarg));
-
//发送确认的参数
-
outarg.major = FUSE_KERNEL_VERSION;
-
outarg.minor = FUSE_KERNEL_MINOR_VERSION;
-
//下面就是判断不同的版本,进行不同的参数设置
-
….....
-
}
读取数据
- 如果是读取请求则调用流程为:
-
//接收的数据
-
struct fuse_read_in {
-
__u64 fh;
-
__u64 offset;
-
__u32 size;
-
__u32 read_flags;
-
__u64 lock_owner;
-
__u32 flags;
-
__u32 padding;
-
}
请求分发
- //发送的数据
-
struct
-
static void do_read(fuse_req_t req,fuse_ino_t nodeid,const void*inarg)
-
{
-
struct fuse_read_in *arg = (struct fuse_read_in*)inarg;
-
-
if(req->f->op.read){
-
struct fuse_file_info fi;
-
-
memset(&fi,0,sizeof(fi));
-
fi.fh = arg->fh;//文件句柄
-
fi.fh_old = fi.fh;
-
if(req->f->conn.proto_minor>=9) {
-
fi.lock_owner = arg->lock_owner;
-
fi.flags = arg->flags;
-
}
-
req->f->op.read(req,nodeid,arg->size,arg->offset,&fi);
-
}else
-
fuse_reply_err(req,ENOSYS);
-
}
其中req->f->op.read()调用了fuse_lib_read函数,原型如下:
- static void fuse_lib_read(fuse_req_t req,fuse_ino_t ino,size_t size,off_t off,struct fuse_file_info *fi)
-
{
-
struct fuse *f = req_fuse_prepare(req);
-
char *path;
-
char *buf;
-
int res;
-
-
buf = (char*)malloc(size);
-
if(buf==NULL) {
-
reply_err(req,-ENOMEM);
-
return;
-
}
-
//通过ino获取文件路径
-
res = get_path_nullok(f,ino,&path);
-
if(res ==0) {
-
struct fuse_intr_data d;
-
-
fuse_prepare_interrupt(f,req,&d);
-
//转到客户端自己注册的fuse_operations的相关操作
-
res = fuse_fs_read(f->fs,path,buf,size,off,fi);
-
fuse_finish_interrupt(f,req,&d);
-
free_path(f,ino,path);
-
}
-
-
if(res>=0)
-
fuse_reply_buf(req,buf,res);
-
else
-
fuse_reply_err(req,res);
-
free(buf);
-
}
获取文件路径
这里面的get_path_nullok函数则调用了get_path_common,原型如下:
- //get_path_common(f,nodeid,NULL,path,NULL)
-
static int get_path_common(struct fuse* f,fuse_ino_t nodeid,const char* name,
-
char**path,struct node **wnode)
-
{
-
int err;
-
int ticket;
-
-
pthread_mutex_lock(&f->lock);
-
ticket = get_tickets(f);
-
//直接通过文件nodeid获取文件路径
-
err = try_get_path(f,nodeid,name,path,wnode);
-
//正在被其它线程访问
-
if(err==-EAGAIN) {
-
//定义原型:
-
//struct lock_queue_element {
-
// struct lock_queue_element *next;
-
// pthread_cond_t cond;
-
//}
-
struct lock_queue_element qe;
-
//放入等待队列
-
queue_path(f,,&qe,nodeid,name,!!wnode);
-
do {
-
//等待fuse解锁,线程阻塞
-
wait_on_path(f,&qe,nodeid,name,!!wnode);
-
//只要错误为-EAGAIN,就说明当前调用出现阻塞情况,需要等待
-
err = try_get_path(f,nodeid,name,path,wnode,ticket);
-
//唤醒下一个等待的条件变量
-
wake_up_next(&qe);
-
}while(err == -EAGAIN);
-
//操作成功后,就销毁条件变量
-
dequeue_path(f,&qe,nodeid,name,!!wnode);
-
}
-
pthread_mutex_unlock(&f->lock);
-
-
return err;
-
}
继续看其中的调用函数:
- //try_get_path(f,nodeid,NULL,path,NULL) 从nodeid(索引节点缓存)对应的缓存中取出path
-
static int try_get_path(struct fuse *f,fuse_ino_t nodeid,const char* name,
-
char **path,struct node **wnodep,int ticket)
-
{
-
unsigned bufsize=256;
-
char *buf;
-
char *s;
-
struct node *node;
-
struct node *wnode = NULL;
-
int err;
-
*path = NULL;
-
buf = malloc(bufsize);
-
…..
-
s= buf+bufsize-1;
-
*s = '\0';
-
if(name!=NULL) {
-
//add_name:转换为绝对路径,也就是在路径名前面 加上/
-
s = add_name(&buf,&bufsize,s,name);
-
err = -ENOMEM;
-
if (s == NULL) goto out_free;
-
}
-
//如果父节点不为空,则nodeid指向的是父节点
-
if(wnodep) {
-
assert(ticket);
-
wnode = lookup_node(f,nodeid,name);
-
….......
-
}
-
//逆向遍历文件夹,生成绝对路径:开始从该索引节点开始一步一步向上寻找父目录,直到/
-
err = 0;
-
for(node = get_node(f,nodeid);node->nodeid != FUSE_ROOT_ID; node = node->parent){
-
//每寻找一项,就加入到路径之中
-
s = add_name(&buf,&bufsize,s,node->name);
-
….......
-
}
-
*path = buf;
-
….......
-
return 0;
-
}
阅读(1953) | 评论(0) | 转发(0) |