ceph存储 FUSE队列管理浅析
2015-04-02 15:22
549 查看
fuse通过fuse_session_loop来启动守护程序,守护程序最终会调用fuse_dev_readv,fuse_dev_readv调用request_wait,使得进程在fc的waitq队列上睡眠。
代码片段1
static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
unsigned long nr_segs, loff_t *off)
{
…..
request_wait(fc);
….
}
/* Wait until a request is available on the pending list */
static void request_wait(struct fuse_conn *fc)
{
//定义一个队列节点变量wait,其与当前进程相关联
DECLARE_WAITQUEUE(wait, current);
//将wait加入到fc->waitq等待队列中,当有请求发到fuse文件系统时(通过request_send),这个等待队列上的进程会被唤醒,某一个进程会被赋予CPU使用权
add_wait_queue_exclusive(&fc->waitq, &wait);
//不断的检查fc的pending队列及interrupts队列,看是否有请求,没有请求会一直while循环
while (fc->connected &&
!request_pending(fc)) {
set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current))
break;
spin_unlock(&fc->lock);
schedule(); //选择一个进程运行
spin_lock(&fc->lock);
}
//有请求,将进程设为TASK_RUNNING状态
set_current_state(TASK_RUNNING);
//将wait从等待队列中移除
remove_wait_queue(&fc->waitq, &wait);
}
static int request_pending(struct fuse_conn *fc)
{
return !list_empty(&fc->pending) || !list_empty(&fc->interrupts);
}
request_send是用户请求经过vfs,再到fuse operation中被调用的,它向/dev/fuse发送请求
代码片段2
void request_send(struct fuse_conn *fc, struct fuse_req *req)
{
……
queue_request(fc, req);
request_wait_answer(fc, req);
……
}
static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
{
//将请求加入到pending队列
list_add_tail(&req->list, &fc->pending);
req->state = FUSE_REQ_PENDING;
if (!req->waiting) {
req->waiting = 1;
atomic_inc(&fc->num_waiting);
}
//唤醒等待等列
wake_up(&fc->waitq);
kill_fasync(&fc->fasync, SIGIO, POLL_IN);
}
/* Called with fc->lock held. Releases, and then reacquires it. */
static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
{
//该调用会在req的waitq上睡眠,fuse守护程序处理完请求后,会将其唤醒
}
fuse守护程序处理完请求,最终通过fuse_dev_writev写回/dev/fuse,它将唤醒相应req中waitq的等待队列元素,从而让文件系统请求完成request_wait_answer,获取到结果。
/*
Write a single reply to a request. First the header is copied from the write buffer. The request is then searched on the processing list by the unique
ID found in the header. If found, then remove it from the list and copy the rest of the buffer to the request. The request is finished by calling request_end()
*/
static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
unsigned long nr_segs, loff_t *off)
{
req = request_find(fc, oh.unique);
request_end(fc, req);
}
/*
* This function is called when a request is finished. Either a reply
* has arrived or it was aborted (and not yet sent) or some error
* occurred during communication with userspace, or the device file
* was closed. The requester thread is woken up (if still waiting),
* the 'end' callback is called if given, else the reference to the
* request is released
*
* Called with fc->lock, unlocks it
*/
static void request_end(struct fuse_conn *fc, struct fuse_req *req)
{
//唤醒req上的等待队列
wake_up(&req->waitq);
}
fuse设备其的主要工作其实就是进行队列的管理,对fuse设备的读(写)其实就是从相应的队列移除(添加)请求(或响应),request_send将请求加入pending队列,唤醒fuse守护程序,并在req的waitq上等待请求结果,守护程序通过fuse_dev_readv从pending队列中移除请求并处理,处理完成后,守护程序唤醒req的waitq上的进程,该进程读取结果,并返回给用户。总的来说,一个请求从发起到完成会经过4步:
0. fuse守护程序在fc的waitq上等待请求;
1. 用户的请求唤醒fc的waitq,从该waitq上移除一个请求进行处理,并在req的waitq上等待请求结果;
2. fuse守护程序被唤醒,读取请求,处理请求,返回结果,唤醒对应req上的waitq队列。
3. 请求被唤醒,读取fuse守护程序返回的结果,返回给用户。
代码片段1
static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
unsigned long nr_segs, loff_t *off)
{
…..
request_wait(fc);
….
}
/* Wait until a request is available on the pending list */
static void request_wait(struct fuse_conn *fc)
{
//定义一个队列节点变量wait,其与当前进程相关联
DECLARE_WAITQUEUE(wait, current);
//将wait加入到fc->waitq等待队列中,当有请求发到fuse文件系统时(通过request_send),这个等待队列上的进程会被唤醒,某一个进程会被赋予CPU使用权
add_wait_queue_exclusive(&fc->waitq, &wait);
//不断的检查fc的pending队列及interrupts队列,看是否有请求,没有请求会一直while循环
while (fc->connected &&
!request_pending(fc)) {
set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current))
break;
spin_unlock(&fc->lock);
schedule(); //选择一个进程运行
spin_lock(&fc->lock);
}
//有请求,将进程设为TASK_RUNNING状态
set_current_state(TASK_RUNNING);
//将wait从等待队列中移除
remove_wait_queue(&fc->waitq, &wait);
}
static int request_pending(struct fuse_conn *fc)
{
return !list_empty(&fc->pending) || !list_empty(&fc->interrupts);
}
request_send是用户请求经过vfs,再到fuse operation中被调用的,它向/dev/fuse发送请求
代码片段2
void request_send(struct fuse_conn *fc, struct fuse_req *req)
{
……
queue_request(fc, req);
request_wait_answer(fc, req);
……
}
static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
{
//将请求加入到pending队列
list_add_tail(&req->list, &fc->pending);
req->state = FUSE_REQ_PENDING;
if (!req->waiting) {
req->waiting = 1;
atomic_inc(&fc->num_waiting);
}
//唤醒等待等列
wake_up(&fc->waitq);
kill_fasync(&fc->fasync, SIGIO, POLL_IN);
}
/* Called with fc->lock held. Releases, and then reacquires it. */
static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
{
//该调用会在req的waitq上睡眠,fuse守护程序处理完请求后,会将其唤醒
}
fuse守护程序处理完请求,最终通过fuse_dev_writev写回/dev/fuse,它将唤醒相应req中waitq的等待队列元素,从而让文件系统请求完成request_wait_answer,获取到结果。
/*
Write a single reply to a request. First the header is copied from the write buffer. The request is then searched on the processing list by the unique
ID found in the header. If found, then remove it from the list and copy the rest of the buffer to the request. The request is finished by calling request_end()
*/
static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
unsigned long nr_segs, loff_t *off)
{
req = request_find(fc, oh.unique);
request_end(fc, req);
}
/*
* This function is called when a request is finished. Either a reply
* has arrived or it was aborted (and not yet sent) or some error
* occurred during communication with userspace, or the device file
* was closed. The requester thread is woken up (if still waiting),
* the 'end' callback is called if given, else the reference to the
* request is released
*
* Called with fc->lock, unlocks it
*/
static void request_end(struct fuse_conn *fc, struct fuse_req *req)
{
//唤醒req上的等待队列
wake_up(&req->waitq);
}
fuse设备其的主要工作其实就是进行队列的管理,对fuse设备的读(写)其实就是从相应的队列移除(添加)请求(或响应),request_send将请求加入pending队列,唤醒fuse守护程序,并在req的waitq上等待请求结果,守护程序通过fuse_dev_readv从pending队列中移除请求并处理,处理完成后,守护程序唤醒req的waitq上的进程,该进程读取结果,并返回给用户。总的来说,一个请求从发起到完成会经过4步:
0. fuse守护程序在fc的waitq上等待请求;
1. 用户的请求唤醒fc的waitq,从该waitq上移除一个请求进行处理,并在req的waitq上等待请求结果;
2. fuse守护程序被唤醒,读取请求,处理请求,返回结果,唤醒对应req上的waitq队列。
3. 请求被唤醒,读取fuse守护程序返回的结果,返回给用户。
相关文章推荐
- FUSE队列管理浅析
- FUSE队列管理浅析
- FUSE队列管理浅析
- FUSE 内核实现代码分析(二) 队列管理
- ceph存储 "ceph集群浅析一"前言
- 浅析存储管理函数
- ceph分布式存储实战(5)——ceph存储配置(RBD镜像日常管理)
- ceph存储 fuse_operations与fuse_lowlevel_ops
- ceph存储 FUSE的big_writes与direct_io选项分析
- ceph存储 "ceph集群浅析二"Ceph概况
- ceph存储 "ceph集群浅析七"关于Ceph的若干想法
- ceph存储 "ceph集群浅析六"Ceph与OpenStack
- ceph存储 Git中tag标签管理
- ceph存储 ceph-fuse源码分析一
- ceph存储 "ceph集群浅析五"Ceph的工作原理及流程
- ceph存储 Ceph管理平台Calamari的架构与功能分析
- 架构设计:系统存储(29)——分布式文件系统Ceph(管理)
- ceph存储 FUSE调用流程代码分析
- openstack 管理三十九 - cinder 连接多个 ceph 存储方法
- ceph存储 "ceph集群浅析四"Ceph的结构