处理流程
当线程执行do_work操作之后,开始调用函数fuse_chan_recv读取/dev/fuse设备中的请求,接着处理的流程如下:
process:生成具体的请求
----->op():将ino转化为具体请求路径
---->user level op:用户级程序操作
------> return:返回
下面分析各个函数原型
读取请求
函数原型如下:
- //从/dev/fuse设备中读取数据,调用函数为:fuse_chan_recv(&ch,w->buf,w->bufsize)
-
//bufsize定义大小为:min(getpagsize()+0x1000,0x21000),发送协议规定包头至少8K
-
int fuse_chan_recv(struct fuse_chan **chp,char* buf,size_t size)
-
{
-
struct fuse_chan *ch=*chp;
-
if(ch->compat)
-
return ((struct fuse_chan_ops_compat24 *)&ch->op)
-
->receive(ch,buf,size);
-
else
-
return ch->op.receive(chp,buf,size);
-
}
上面的 op.receive函数则具体指向的函数如下:
- static int fuse_kern_chan_receive(struct fuse_chan **chp,char *buf,
-
size_t size)
-
{
-
….
-
restart:
-
res = read(fuse_chan_fd(ch),buf,size);
-
err = errno;
-
-
if(fuse_session_exited(se)) return 0;
-
if(res==-1) {
-
//此错误代表被中断,可以进行重启
-
if(err == ENOENT) goto restart;
-
if(err == ENODEV) {
-
fuse_session_exit(se);
-
return 0;
-
}
-
if(err!=EINTR && err !=EAGAIN)
-
perror(“fuse:reading device”);
-
return -err;
-
}
-
//数据至少有一个包头
-
if((size_t)res < sizeof(sruct fuse_in_header)) {
-
fprintf(stderr,” short read on fuse device\n”);
-
return -EIO;
-
}
-
return res;
-
}
处理请求
在数据读取完成之后,就进行处理:
fuse_session_process(mt->se,w->buf,res,ch);
函数原型如下:
- void fuse_session_process(struct fuse_session *se,const char* buf,size_t len,struct fuse_chan *ch)
-
{
-
se->op.process(se->data,buf,len,ch);
-
}
而session在进行初始化时,处理函数如下:
在该函数中使用的数据结构如下:
- //请求链表
-
struct fuse_req {
-
struct fuse_ll *f;
-
uint64_t unique;
-
int ctr;
-
pthread_mutex_t lock;
-
struct fuse_ctx ctx;
-
struct fuse_chan *ch;
-
int interrupted;
-
union {
-
struct {
-
uint64_t unique;
-
}i;
-
struct {
-
fuse_interrupt_func_t func;
-
void *data;
-
}ni;
-
}u;
-
struct fuse_req *next;
-
struct fuse_req *prev;
-
};
-
//与请求相关的上下文
-
struct fuse_ctx {
-
uid_t uid;//调用进程的用户ID
-
gid_t gid;//调用线程的组ID
-
pid_t pid;//调用线程的进程ID
-
mode_t mask;//调用线程的文件掩码
-
}
-
//与读写相关的参数
-
struct fuse_ll{
-
int debug;
-
int allow_root;
-
int atomic_o trunc;
-
int no_remote_lock;
-
int big_writes;
-
struct fuse_lowlevel_ops op;
-
int got_init;
-
struct cuse_data *cuse_data;
-
void *cuse_data;
-
uid_t owner;
-
struct fuse_conn_info conn;
-
struct fuse_req list;//一个正常操作链表
-
struct fuse_req interrupts;//一个中断操作链表
-
pthread_mutex_t lock;
-
int got_destroy;
-
}
低级处理
- static void fuse_ll_process(void*data,const char*buf,size_t len,struct fuse_chan *ch)
-
{
-
//系统初始化时,就已经设置,通过用户指定的命令参数
-
struct fuse_ll *f = (struct fuse_ll*)data;
-
//转化为读取的数据包头信息
-
struct fuse_in_header *in = (struct fuse_in_header *)buf;
-
//包头后面就是具体参数了,直接通过偏移量实现
-
const void *inarg = buf+sizeof(struct fuse_in_header);
-
struct fuse_req *req;
-
….......
-
//生成具体的请求包头
-
req = (struct fuse_req*)calloc(1,sizeof(struct fuse_req));
-
….
-
req->f = f;
-
req->unique = in->unique;
-
req->ctx.uid = in->uid;
-
req->ctx.gid = in->gid;
-
req->ctx.pid = in->pid;
-
req->ch = ch;
-
req->ctr = 1;
-
list_init_req(req);
-
fuse_mutex_init(&req->lock);
-
-
err = EIO;
-
//如果没有初始化
-
if(!f->got_init) {
-
enum fuse_opcode expected;
-
//有两种设备/dev/cuse,/dev/fuse,当打开设备或者挂载上去时,就发送初始化信息
-
expected = f->cuse_data?CUSE_INIT:FUSE_INIT;
-
if(in->opcode != expected)
-
goto reply_err;
-
} else if(in->opcode == FUSE_INIT || in->opcode ==CUSE_INIT)
-
goto reply_err;
-
err = EACCES;
-
//在允许权限中处理这些函数
-
if(f->allow_root && in->uid !=f->owner && in->uid!=0&&
-
in->opcode != FUSE_INIT && in->opcode !=FUSE_READ &&
-
in-> FUSE_WRITE && in-> FUSE_FSYNC &&
-
in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
-
in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR)
-
goto reply_err;
-
err = ENOSYS;
-
//判断操作码是否合法
-
if(in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
-
goto reply_err;
-
//如果没有被中断,就从中断的链表中删除,同时添加到正常的链表中去
-
if(in->opcode != FUSE_INTERRUPT) {
-
struct fuse_req *intr;
-
pthread_mutex_lock(&f->lock);
-
-
intr = check_interrrupt(f,req);
-
list_add_req(req,&f->list);
-
pthread_mutex_unlock(&f->lock);
-
if(intr)
-
fuse_reply_err(intr,EAGAIN);
-
}
-
//转发到具体的操作函数
-
fuse_ll_ops[in->opcode].func(req,in->nodeid,inarg);
-
return;
-
reply_err:
-
fuse_reply_err(req,err);
-
}
中断处理
当正在操作fuse文件系统的程序被中断后,fuse内核模块就接收到INTERRUPT信号,该模块立即将此请求转发至客户端,处理模块如下:
- static void do_interrupt(fuse_req_t req,fuse_ino_t nodeid,const void* inarg)
-
{
-
//struct fuse_interrupt_in 中只有一个参数:__u64 unique
-
struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *)inarg;
-
//提取与请求相关的数据
-
struct fuse_ll *f = req->f;
-
-
(void) nodeid;
-
if(f->debug)
-
fprintf(stderr,”INTERRUPT: %llu\n”,(unsigned long long)arg->unique);
-
//设置得到的需要被中断请求标识符
-
req->u.i.unique = arg->unique;
-
-
pthread_mutex_lock(&f->lock);
-
//如果在正常的链表中找到对应的请求,删除该请求,如果出现在中断链表中,就简单返回
-
if(find_interrupt(f,req))
-
destroy_req(req);
-
else
-
//没有查找到就加入中断链表中
-
list_add_req(req,&f->interrupts);
-
-
//不用进行回复
-
pthread_mutex_unlock(&f->lock);
-
}
阅读(3290) | 评论(0) | 转发(0) |