FUSE(The Filesystem in Userspace)介绍:
像ext4,xfs等本地文件系统都是在linux内核代码中,并且运行在内核态,如果要在内核中定制化开发一个文件系统,对程序员的能力要求是比较高的。fuse为用户态文件系统提供了与VFS交互的通道,fuse分为内核态fuse模块,用户态libfuse和fusemount工具。其中内核态fuse模块是其最核心的功能,主要是转发VFS的operations到用户态,实现export文件系统(NFS)接口;可以基于用户态的libfuse进行开发,如mcachefs等,也可以根据fuse的协议自己编写通信模块,如GlusterFS。
基于fuse开发的用户态文件系统一般只支持POSIX接口,在某些不能通过POSIX方式mount的时候,一般会采用上层再套一层NAS系统来提供对外服务。如下图:
在上述用法中,使用nfs客户端的程序在访问文件或者目录的时候可能会收到Stale file handle(errno: ESTALE)的报错,如GlusterFS就有这个问题,其原因我们下面逐步分析。
Stale file handle问题分析:
nfs客户端和服务端(如:nfsd,nfs-ganesha等)之间通过RPC协议进行通信,与其他文件系统以inode表示其中的一个文件或目录类似,nfs客户端和服务端都通过fh(file handle)来表示,且各自独立cache fh(问题所在),实现exportfs的文件系统都需要实例化struct export_operations结构中的操作 (详细参照内核代码:include/linux/exportfs.h)
/**
* struct export_operations - for nfsd to communicate with file systems
* @encode_fh: encode a file handle fragment from a dentry
* @fh_to_dentry: find the implied object and get a dentry for it
* @fh_to_parent: find the implied object's parent and get a dentry for it
* @get_name: find the name for a given inode in a given directory
* @get_parent: find the parent of a given directory
* @commit_metadata: commit metadata changes to stable storage
*/
struct export_operations {
int (*encode_fh)(struct inode *inode, __u32 *fh, int *max_len, struct in