searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Ceph文件系统Fuse客户端实现介绍

2023-08-29 08:44:49
84
0

一、Fuse框架及流程简介

    Fuse(Filesystem in Userspace)就是用户空间的文件系统。传统的文件系统一般在内核中实现,而Fuse的出现让非内核开发者开发自己的文件系统成为可能。

    对于开发者而言,Fuse更多是一个开发框架。这个框架主要分为三个部分:内核模块、Fuse库(libfuse)和Fuse文件系统守护进程。它们之间以及其上下游的交互关系如下图所示:

    结合上图,一个简单的Fuse访问处理流程如下:

    1、应用在Fuse文件系统上执行一些系统调用;

    2、VFS将这些操作路由至Fuse driver;

    3、Fuse driver创建一个Fuse请求结构体,并把请求保存在请求队列中,此时执行操作的进程会被阻塞;

    4、Fuse文件系统守护进程通过读取/dev/fuse将请求从内核队列中取出,并进行处理;

    5、当请求处理完成后,Fuse文件系统守护进程会将响应写回/dev/fuse;

    6、Fuse driver把请求标记为完成状态,并最终唤醒用户进程。

 

二、Ceph文件系统Fuse客户端初始化流程

    Ceph文件系统客户端(ceph-fuse)依赖libfuse项目,在初始化的流程中很多都是调用的libfuse提供的接口:

|- main (ceph_fuse.cc)

    |-global_init (global/global_init.cc)  // 生成ceph context

    |-Preforker::prefork (common/Preforker.h)  // 成为守护进程

    |-MonClient::build_initial_monmap (mon/MonClient.cc)  // 初始化mon client及monmap

    |-Messenger::create_client_messenger (msg/Messenger.cc)  // 创建client messenger

    |-CephFuse::init (client/fuse_ll.cc)  // 初始化CephFuse对象

        |-CephFuse::Handle::init (client/fuse_ll.cc)  // 初始化CephFuse::Handle对象

            |-fuse_parse_cmdline (libfuse api)  // 解析libfuse需要的参数

    |-Messenger::start (msg/Messenger.cc)  // 启动messenger线程,开始接收消息

    |-StandaloneClient::init (client/Client.cc)  // 初始化client,用来收发用户I/O请求

        |-SafeTimer::init (common/Timer.cc)  // 初始化client的定时器

        |-ObjecterCacher::init (osdc/ObjecterCacher.cc)  // 启动object cacher(对象缓存管理)

        |-Objecter::init (osdc/Objecter.cc)  // 初始化objecter并启动(objecter是跟osd打交道的client)

    |-Client::mount (client/Client.cc)  // 与mds建立交互

        |-Client::subscribe_mdsmap (client/Client.cc)  // 与mon完成认证,并订阅mdsmap

        |-Client::tick (client/Client.cc)  // 启动client定时任务

        |-Client::make_request (client/Client.cc)  // 发送请求给mds,获取mount目录属性

    |-CephFuse::start (client/fuse_ll.cc)

        |-CephFuse::Handle::start (client/fuse_ll.cc)

            |-fuse_mount (libfuse api)  // 调用libfuse接口完成目录挂载,此处创建一个通道,与/dev/fuse交互

            |-fuse_lowlevel_new (libfuse api)  // 调用libfuse接口创建lowlevel fuse session,其中需传入参数fuse_ll_oper(函数注册,包括各种posix接口的用户态实现)

            |-fuse_session_add_chan(se, ch)  // 调用libfuse接口将目录挂载时创建的通道与lowlevel fuse session关联

    |-CephFuse::loop (client/fuse_ll.cc)

        |-CephFuse::Handle::loop (client/fuse_ll.cc)

            |-fuse_session_loop_mt (libfuse api)  // 调用libfuse接口,开始监听处理I/O请求

 

三、Ceph文件系统Fuse客户端请求处理流程

3.1、元数据访问请求处理

    以用户在cephfs挂载目录下执行mkdir命令为例,完成内核及libfuse的处理流程后,libfuse将调用到ceph-fuse通过fuse_lowlevel_new注册的mkdir接口用户态实现:fuse_ll_mkdir,核心流程如下:

|-fuse_ll_mkdir (client/fuse_ll.cc)

    |-Client::ll_mkdir (client/Client.cc)

        |-Client::_mkdir(client/Client.cc)

            |-……  // 一系列的权限、配额等检查

            |-Client::make_request (client/Client.cc)  // 发送请求给mds,执行创建目录操作

    |-fuse_reply_entry (libfuse api)  // 成功则调用libfuse接口返回结果,包含目录entry

    其中make_request方法将实现向MDS发送请求,流程如下:

|-Client::make_request (client/Client.cc)

    |-Client::choose_target_mds (client/Client.cc)

    |-Client::_get_or_open_mds_session (client/Client.cc)  // 与选中的mds未有open状态的session时,将尝试打开一个session,有则跳过此步骤

        |-Client::_open_mds_session (client/Client.cc)

            |-Connection::send_message2 (msg/Connection.h)  // 向mds打开session消息

    |-Client::wait_on_context_list (client/Client.cc)  // 尝试打开一个session后,对于刚打开的处于opening状态的session,将等待其变更为open状态,如session已处于open状态则跳过此步骤

    |-Client::send_request (client/Client.cc)  // 向mds发送业务请求

        |-Cond::Wait (common/Cond.h)  // 等待mds响应

    |-Client::put_request (client/Client.cc)

3.2、数据读写请求处理

    以用户在cephfs挂载目录下写入文件为例,完成内核及libfuse的处理流程后,libfuse将调用到ceph-fuse通过fuse_lowlevel_new注册的write接口用户态实现:fuse_ll_write,核心流程如下:

|-fuse_ll_write (client/fuse_ll.cc)

    |-Client::ll_write (client/fuse_ll.cc)

        |-Client::_write (client/fuse_ll.cc)

            |-……  // 一系列的权限、配额等检查

            |-ObjectCacher::file_write (osdc/ObjectCacher.h)

            |-Objecter::write_trunc (osdc/Objecter.h)

                |-Objecter::op_submit (osdc/Objecter.cc)

                    |-Objecter::_op_submit_with_budget (osdc/Objecter.cc)

                        |-Objecter::_op_submit (osdc/Objecter.cc)

                            |-Objecter::_send_op (osdc/Objecter.cc)

                                |-PrimaryLogPG::send_message (osd/PrimaryLogPG.h)  // 发送对象写消息给osd

    |-fuse_reply_write (libfuse api)  // 成功则调用libfuse接口返回结果,包含写入的字节数

0条评论
0 / 1000
CD
15文章数
0粉丝数
CD
15 文章 | 0 粉丝
原创

Ceph文件系统Fuse客户端实现介绍

2023-08-29 08:44:49
84
0

一、Fuse框架及流程简介

    Fuse(Filesystem in Userspace)就是用户空间的文件系统。传统的文件系统一般在内核中实现,而Fuse的出现让非内核开发者开发自己的文件系统成为可能。

    对于开发者而言,Fuse更多是一个开发框架。这个框架主要分为三个部分:内核模块、Fuse库(libfuse)和Fuse文件系统守护进程。它们之间以及其上下游的交互关系如下图所示:

    结合上图,一个简单的Fuse访问处理流程如下:

    1、应用在Fuse文件系统上执行一些系统调用;

    2、VFS将这些操作路由至Fuse driver;

    3、Fuse driver创建一个Fuse请求结构体,并把请求保存在请求队列中,此时执行操作的进程会被阻塞;

    4、Fuse文件系统守护进程通过读取/dev/fuse将请求从内核队列中取出,并进行处理;

    5、当请求处理完成后,Fuse文件系统守护进程会将响应写回/dev/fuse;

    6、Fuse driver把请求标记为完成状态,并最终唤醒用户进程。

 

二、Ceph文件系统Fuse客户端初始化流程

    Ceph文件系统客户端(ceph-fuse)依赖libfuse项目,在初始化的流程中很多都是调用的libfuse提供的接口:

|- main (ceph_fuse.cc)

    |-global_init (global/global_init.cc)  // 生成ceph context

    |-Preforker::prefork (common/Preforker.h)  // 成为守护进程

    |-MonClient::build_initial_monmap (mon/MonClient.cc)  // 初始化mon client及monmap

    |-Messenger::create_client_messenger (msg/Messenger.cc)  // 创建client messenger

    |-CephFuse::init (client/fuse_ll.cc)  // 初始化CephFuse对象

        |-CephFuse::Handle::init (client/fuse_ll.cc)  // 初始化CephFuse::Handle对象

            |-fuse_parse_cmdline (libfuse api)  // 解析libfuse需要的参数

    |-Messenger::start (msg/Messenger.cc)  // 启动messenger线程,开始接收消息

    |-StandaloneClient::init (client/Client.cc)  // 初始化client,用来收发用户I/O请求

        |-SafeTimer::init (common/Timer.cc)  // 初始化client的定时器

        |-ObjecterCacher::init (osdc/ObjecterCacher.cc)  // 启动object cacher(对象缓存管理)

        |-Objecter::init (osdc/Objecter.cc)  // 初始化objecter并启动(objecter是跟osd打交道的client)

    |-Client::mount (client/Client.cc)  // 与mds建立交互

        |-Client::subscribe_mdsmap (client/Client.cc)  // 与mon完成认证,并订阅mdsmap

        |-Client::tick (client/Client.cc)  // 启动client定时任务

        |-Client::make_request (client/Client.cc)  // 发送请求给mds,获取mount目录属性

    |-CephFuse::start (client/fuse_ll.cc)

        |-CephFuse::Handle::start (client/fuse_ll.cc)

            |-fuse_mount (libfuse api)  // 调用libfuse接口完成目录挂载,此处创建一个通道,与/dev/fuse交互

            |-fuse_lowlevel_new (libfuse api)  // 调用libfuse接口创建lowlevel fuse session,其中需传入参数fuse_ll_oper(函数注册,包括各种posix接口的用户态实现)

            |-fuse_session_add_chan(se, ch)  // 调用libfuse接口将目录挂载时创建的通道与lowlevel fuse session关联

    |-CephFuse::loop (client/fuse_ll.cc)

        |-CephFuse::Handle::loop (client/fuse_ll.cc)

            |-fuse_session_loop_mt (libfuse api)  // 调用libfuse接口,开始监听处理I/O请求

 

三、Ceph文件系统Fuse客户端请求处理流程

3.1、元数据访问请求处理

    以用户在cephfs挂载目录下执行mkdir命令为例,完成内核及libfuse的处理流程后,libfuse将调用到ceph-fuse通过fuse_lowlevel_new注册的mkdir接口用户态实现:fuse_ll_mkdir,核心流程如下:

|-fuse_ll_mkdir (client/fuse_ll.cc)

    |-Client::ll_mkdir (client/Client.cc)

        |-Client::_mkdir(client/Client.cc)

            |-……  // 一系列的权限、配额等检查

            |-Client::make_request (client/Client.cc)  // 发送请求给mds,执行创建目录操作

    |-fuse_reply_entry (libfuse api)  // 成功则调用libfuse接口返回结果,包含目录entry

    其中make_request方法将实现向MDS发送请求,流程如下:

|-Client::make_request (client/Client.cc)

    |-Client::choose_target_mds (client/Client.cc)

    |-Client::_get_or_open_mds_session (client/Client.cc)  // 与选中的mds未有open状态的session时,将尝试打开一个session,有则跳过此步骤

        |-Client::_open_mds_session (client/Client.cc)

            |-Connection::send_message2 (msg/Connection.h)  // 向mds打开session消息

    |-Client::wait_on_context_list (client/Client.cc)  // 尝试打开一个session后,对于刚打开的处于opening状态的session,将等待其变更为open状态,如session已处于open状态则跳过此步骤

    |-Client::send_request (client/Client.cc)  // 向mds发送业务请求

        |-Cond::Wait (common/Cond.h)  // 等待mds响应

    |-Client::put_request (client/Client.cc)

3.2、数据读写请求处理

    以用户在cephfs挂载目录下写入文件为例,完成内核及libfuse的处理流程后,libfuse将调用到ceph-fuse通过fuse_lowlevel_new注册的write接口用户态实现:fuse_ll_write,核心流程如下:

|-fuse_ll_write (client/fuse_ll.cc)

    |-Client::ll_write (client/fuse_ll.cc)

        |-Client::_write (client/fuse_ll.cc)

            |-……  // 一系列的权限、配额等检查

            |-ObjectCacher::file_write (osdc/ObjectCacher.h)

            |-Objecter::write_trunc (osdc/Objecter.h)

                |-Objecter::op_submit (osdc/Objecter.cc)

                    |-Objecter::_op_submit_with_budget (osdc/Objecter.cc)

                        |-Objecter::_op_submit (osdc/Objecter.cc)

                            |-Objecter::_send_op (osdc/Objecter.cc)

                                |-PrimaryLogPG::send_message (osd/PrimaryLogPG.h)  // 发送对象写消息给osd

    |-fuse_reply_write (libfuse api)  // 成功则调用libfuse接口返回结果,包含写入的字节数

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0