nfs-ganesha路径梳理

Ethereal Lv4

1. 结构及组成

1.1 FSAL

FSAL(File System Abstraction Layer),文件系统抽象层,将后端存储抽象为统一的、命名空间独立的API,供应用层来调用。

命名空间是什么?内核命名空间?

FSAL provides a namespace independent

API

4ab501d475f973bcb0b48f6b6465a012

1.2 ntirpc

一个nfs ganesha的组件,与GRPC相比?

为什么内核中喜欢使用RPC?(OpenHarmony内核中使用了大量的RPC,几乎每个组件都具有client与server)
Ganesha 的核心模块

1.3 Memory Manager

负责 Ganesha 的内存管理。

1.4 RPCSEC_GSS

负责使用 RPCSEC_GSS 的数据传输,通常使用 krb5, SPKM3 或 LIPKEY 来管理安全。

1.5 NFS 协议模块

负责 NFS 消息结构的管理Metadata(Inode)

1.6 Cache

负责元数据缓存管理

1.7 File Content Cache

负责数据缓存管理

1.8 Hash Tables

提供了基于红黑树的哈希表,这个模块在 Ganesha 里用到很多。

1.9 LTTNG

用于追踪应用程序路径,通过编译时-DUSE_LTTNG=ON激活

2. 调用链

2.1 启动

  1. 由src/MainNFSD/nfs_main.c或src/MainNFSD/nfs_lib.c中的main函数,启动后台服务进程(编译好的文件为/usr/bin/ganesha.nfsd,服务文件为src/scripts/systemd/nfs-ganesha.service.el7)。

  2. Main函数中做参数解析操作后,转入nfs_prereq_init,初始化tirpc。

  3. 之后进入nfs_init_init,初始化Init的mutex和cond,之后进行初始化操作。

  4. 屏蔽SIGPIPE信号(由sig handler处理(sig handler里只是简单忽略并标记client已经关闭))

  5. 启动start_fsals,主要包括mdcache(CEPH)和pseudofs.

    • start_fsals->load_config_from_parse->proc_block->do_block_init(载入FASL)
  6. init_server_pkgs,初始化mdcache_pkginit

  7. nfs_start_grace/nfs_wait_for_grace_enforcement,恢复

  8. nfs_start,正式启动

    1. nfs_Init,包括exports_pkginit,初始化clientid(通过hashtable存储)和state_id(通过hashtable存储),owner(hashtable),session_id(hash_table)以及session_pool(提前分配空间,用于memalloc时将数据存储在一起,避免碎片),dupreq2_pkginit,create_pseudofs,nfs_Init_svc,nfs_rpc_cb_pkginit

    2. nfs_Start_threads,包括delayed executor(多个线程),sigmgr_thrid(信号处理),admin_thrid(主线程),reaper thread,fridgethr_init(类似idle)

    3. delayed_get_work:通过avltree_container_of

    4. nfs_Init_svc中创建Create_SVCXPRTs,即创建Create_udp和Create_tcp,绑定处理方式,为nfs_rpc_dispatch_udp_NFS和nfs_rpc_dispatch_tcp_NFS,其中均绑定为nfs_rpc_valid_NFS,并通过Register_program将handler注册到ntirpc中,在nfs_rpc_valid_NFS其中由nfs_rpc_process_request进行处理。其中通过svc_auth_authenticate鉴权(ntirpc中成员),最终移交给service_function,即nfs4_Compound,其中process_one_op进行处理(client发送可以发送多个请求,但是处理将一个一个处理),其中通过optabv4分发到具体操作,例如nfs4_op_access等。nfs4_op_setclientid等也是其中成员

2.2 操作

  1. 按照上述,当请求到来时会分发到nfs4_op_create等操作中。

  2. 以nfs4_op_create为例,先进行check_quota,然后移交给fsal_create

  3. 统一文件处理结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
struct compound_data {
nfs_fh4 currentFH; /*< Current filehandle */
nfs_fh4 savedFH; /*< Saved filehandle */
stateid4 current_stateid; /*< Current stateid */
bool current_stateid_valid; /*< Current stateid is valid */
stateid4 saved_stateid; /*< Saved stateid */
bool saved_stateid_valid; /*< Saved stateid is valid */
unsigned int minorversion; /*< NFSv4 minor version */
struct fsal_obj_handle *current_obj; /*< Current object handle */
struct fsal_obj_handle *saved_obj; /*< saved object handle */
struct fsal_ds_handle *current_ds; /*< current ds handle */
struct fsal_ds_handle *saved_ds; /*< Saved DS handle */
object_file_type_t current_filetype; /*< File type of current obj */
object_file_type_t saved_filetype; /*< File type of saved entry */
struct gsh_export *saved_export; /*< Export entry related to the
savedFH */
struct fsal_pnfs_ds *saved_pnfs_ds; /*< DS related to the savedFH */
struct export_perms saved_export_perms; /*< Permissions for export for
savedFH */
struct svc_req *req; /*< RPC Request related to the compound */
struct timespec op_start_time;
nfs_argop4 *argarray;
nfs_res_t *res;
nfs_resop4 *resarray;
uint32_t argarray_len;
nfs_client_cred_t credential; /*< Raw RPC credentials */
nfs_client_id_t *preserved_clientid; /*< clientid that has lease
reserved, if any */
struct nfs41_session_slot__ *slot; /*< NFv41: pointer to the
session's slot */
nfsstat4 cached_result_status; /* <NFv41: save the
slot->cached_result->status for reply request */
bool sa_cachethis; /*< True if cachethis was specified in
SEQUENCE op. */
nfs_opnum4 opcode; /*< Current NFS4 OP */
uint32_t oppos; /*< Position of the operation within the
request processed */
const char *opname; /*< Name of the operation */
char *tagname;
void *op_data; /*< operation specific data for resume */
nfs41_session_t *session; /*< Related session
(found by OP_SEQUENCE) */
sequenceid4 sequence; /*< Sequence ID of the current compound
(if applicable) */
slotid4 slotid; /*< Slot ID of the current compound
(if applicable) */
uint32_t resp_size; /*< Running total response size. */
uint32_t op_resp_size; /*< Current op's response size. */
};
  1. 请求为一组有序的操作,第一个为getrootfh。getrootfh会设置全局的file handler和data中的current_obj。这些都是fsal定义的统一类型。后续操作中,会获取当前的current_obj,然后转换为自己的file handler(例如VFS使用container of和偏移量来计算得到自己的file handler),然后调用文件系统接口获得fd,进行实际操作。

  2. NFS存在一系列的exports,这些exports例如文件路径/etc/nfs,首先通过getrootfh获得根的file handler(ganesha会使用pseudofs)来将路径映射到file handler(函数get_gsh_export_by_pseudo->_get_gsh_export_ref)通过比较每个export中记录的地址来映射到pseudofs中的路径。

3. client提供信息

1
2
3
4
5
6
7
8
9
10
LogEvent(COMPONENT_DISPATCH,
"Request from %s for Program %" PRIu32
", Version %" PRIu32
", Function %" PRIu32
" has xid=%" PRIu32,
client_ip,
reqdata->svc.rq_msg.cb_prog,
reqdata->svc.rq_msg.cb_vers,
reqdata->svc.rq_msg.cb_proc,
reqdata->svc.rq_msg.rm_xid);
1
2
Dec 23 02:47:59 openeuler-vm-2203 nfs-ganesha[53234]: [svc_5] nfs_rpc_process_request :DISP :EVENT :hello= of 44 bytes and str len 0
Dec 23 02:47:59 openeuler-vm-2203 nfs-ganesha[53234]: [svc_5] nfs_rpc_process_request :DISP :EVENT :Request from fe80::f25a:bfe1:2ad5:29a for Program 100003, Version 4, Function 1 has xid=3737409323
  • 存在auth字段(opaque_auth已废弃,采用rq_cred_body),但是内容为空

  • rm_xid和rm_xdr:ntirpc中的标识?

  • rpcprog_t cb_prog; rpcvers_t cb_vers; rpcproc_t cb_proc; 程序,版本,函数

  • 可以拿到ip

4. 并行

包括三种技术

  1. pNFS(客户端首先发送请求获取数据分布信息,后直接与NFS存储节点进行交互,跳过NFS元数据节点,部分文件系统使用)

  2. multipath(创建多个客户端,通过不同IP连接同一个server)

  3. nconnect(创建多个客户端,连接同一个server)

4.1 pNFS

  • 首先向server通过getlayout请求获取layout,服务端返回当前请求文件的对应地址的ds的id,接着客户端发送getdeviceinfo获取对应的ip,后直接与ds交流,通过is_hole来获取空地址,向空地址写入后,发送到ds,然后向服务器更新layout(layoutcommit),最后layout return(nfs-ganesha中规定必须return),当server没有人读时,尝试merge这些layout(ext4中实现或相应fsal中实现),完成COW操作。(通过bl_submit_bio和zero_user_segment初始化页)

  • lock:租期锁,超时释放,客户端重启后通过grace重新拿到同一把锁。并发写是被允许的,因为支持直接向ds通过COW写入,但是错误不会保证。

  • 路径

    • nfs4_get_device_info->nfs4_proc_getdeviceinfo->nfs4_call_sync->nfs4_do_call_sync alloc_deviceid_node

    • nfs4_ff_layout_prepare_ds->nfs4_pnfs_ds_connect->_nfs4_pnfs_v4_ds_connect->nfs4_set_ds_client(nfs_v4)(nfs_v4_clientops)->nfs4_alloc_client->nfs_create_rpc_client->rpc_create

    • pnfs_try_to_read_data->>>bl_alloc_lseg->bl_alloc_extent->bl_find_get_deviceid->nfs4_find_get_deviceid->

4.2 multipath

直接复用nconnect,只不过创建的server地址不同

4.3 nconnect

  • 路径:

nfs4_set_client(nfs_v4)(nfs_v4_clientops)->nfs4_alloc_client->nfs_create_rpc_client->rpc_create

其他

  1. 打印日志(src/include/log.h)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
LogInfo(COMPONENT_DISPATCH,
"Could not authenticate request... rejecting with AUTH_STAT=%s",
auth_stat2str(auth_rc)
);
LogFullDebug(COMPONENT_DISPATCH,
"RPCSEC_GSS no_dispatch=%d", no_dispatch);
LogDebug(COMPONENT_DISPATCH,
"Cannot get client block for Program %" PRIu32
", Version %" PRIu32
", Function %" PRIu32,
reqdata->svc.rq_msg.cb_prog,
reqdata->svc.rq_msg.cb_vers,
reqdata->svc.rq_msg.cb_proc);

LogCrit(COMPONENT_DISPATCH,
"DUP: Unknown duplicate request cache status. This should never be reached!");

参考

【ceph】什么是NFS-Ganesha和fuse-CSDN博客

NFS-Ganesha 核心架构解读_文化 & 方法_陈涛_InfoQ精选文章

LTTng 简介&使用实战 - 新一 - 博客园

RGW NFS/ganesha 源码分析 – 下一代安全

nfs-ganesha - Session - 简书

nfs-ganesha - Open - 简书

nfs-ganesha rados_ng恢复原理分析_grace period ganesha-CSDN博客

【nfs-ganesha】nfs4.1 rados_cluster数据恢复机制 - 苏格拉底的落泪 - 博客园

nfs-ganesha - thread model - fridgethr - 简书

使用glibc xdr对结构体进行编解码_a-xdr编码-CSDN博客

[LTTng学习之旅]——环境搭建_编译tlg需要依赖fst的环境,请参考文档安装fts相关环境-CSDN博客

nfs-ganesha cache代码分析,转mdcache readdir_nfs-ganesha 去mdcache-CSDN博客

Kerberos认证原理及基于Kerberos认证的NFS文件共享 - 佟晖 - 博客园

RPCSEC_GSS · nfs-ganesha/nfs-ganesha Wiki

How does nfs-ganesha handle kerberos authentication? · Issue #903 · nfs-ganesha/nfs-ganesha

Kerberos setup for NFS Ganesha in Ceph · nfs-ganesha/nfs-ganesha Wiki

Nfsv4 configuration - Linux NFS

FS#50663 : [nfs-utils] rpc-gssd.service: Inconsistency detected by ld.so: dl-close.c: 811

nfsv4 在内核中的相关流程 - 知乎

DBus - D-Bus模块-调试 - 《Linux》 - 极客文档

Fsalsupport · nfs-ganesha/nfs-ganesha Wiki

File Systems · nfs-ganesha/nfs-ganesha Wiki

NFS handle - 简书

nfs-ganesha: pseudofs Struct Reference

nfs-ganesha: nfs4_pseudo.c File Reference

NetApp和VMware的NFS nConnect功能

支持NFS Multipathing的系统版本 - Kernel - openEuler 论坛

How to tune nconnect to improve NFS performance | FlamingBytes

Use nconnect to effortlessly increase NFS performance | by Emily Potyraj | Medium

nfs存储多路径 nfs 缓存_coolfengsy的技术博客_51CTO博客

认识NFS多路径 | openEuler文档 | openEuler社区 | v23.03

nfs多路径

NFS 挂载选项说明:nconnect=、nosharetransport、sharetransport= |技术支持 |SUSE

nfs-ganesha I/O performance · Issue #681 · nfs-ganesha/nfs-ganesha

What is pNFS? | Webopedia

NFS Enters a Parallel Universe | Enterprise Storage Forum

Add nConnect Support to NFS v4.1 - vDan

NFS Features for Enhanced Performance

vmware.com/docs/nfs-iscsi-multipathing-in-vsphere

PNFS Development Road Map - Linux NFS

NFS系统read调用过程(四)-CSDN博客

RFC5663 中文翻译 中文RFC RFC文档 RFC翻译 RFC中文版

RFC 5663:并行 NFS (pNFS) 块/卷布局

RFC6688 中文翻译 中文RFC RFC文档 RFC翻译 RFC中文版

RFC 6688: Parallel NFS (pNFS) Block Disk Protection

pnfs.com

linux-nfs.org PNFS Development

Parallel NFS (pNFS)

8.9. pNFS | Red Hat Product Documentation

详谈:pNFS增强文件系统架构 - 开源Linux - 博客园

8.10. 在 NFS 中启用 pNFS SCSI 布局 | Red Hat Product Documentation

linux/Documentation/admin-guide/nfs/pnfs-block-server.rst at 838f9bc02fee68185c1c6e667d6a7ab0eb5948a1 · torvalds/linux

nfs3驱动代码中xdr什么意思 - CSDN文库

理解filelayout中layout创建过程-CSDN博客

NFSv4布局获取处理-CSDN博客

NFS文件系统_ycnian的博客-CSDN博客

FILE LAYOUT_file layout(rfc5661)-CSDN博客

如何在NFS上使用扩展文件属性?-腾讯云开发者社区-腾讯云

理解NFSv4.1布局类型及其在MDS中的查找过程-CSDN博客

文件锁与NFS文件锁 - zhenjing - 博客园

  • Title: nfs-ganesha路径梳理
  • Author: Ethereal
  • Created at: 2024-12-22 20:20:26
  • Updated at: 2025-01-15 14:20:23
  • Link: https://ethereal-o.github.io/2024/12/22/nfs-ganesha路径梳理/
  • License: This work is licensed under CC BY-NC-SA 4.0.
 Comments