ACCESS是NFSv3中增加的一个请求,这个请求的作用是检查用户对文件的访问权限。由于服务器端可能对用户进行匿名映射,因此通常的uid/gid机制就不起作用了。NFSv2中客户端直接向服务器发起各种请求(如READ和WRITE)。如果用户没有相应的访问权限,则失败,客户端进行处理。NFSv3中客户端先通过ACCESS检查用户的访问权限,如果权限不满足就不发起后续请求了。如果权限满足,再发送后续请求。
NFS中,用户对文件的访问权限用数据结构nfs_access_entry表示
struct nfs_access_entry {
struct rb_node rb_node;
struct list_head lru;
unsigned long jiffies; // 这是一个时间戳
struct rpc_cred * cred; // 这里保存了用户信息
int mask; // 这是用户的访问权限
};
客户端所有用户对文件的访问权限保存在文件索引节点结构中的一棵红黑树中,同时保存在一个lru链表中。
struct nfs_inode {
....
struct rb_root access_cache;
struct list_head access_cache_entry_lru;
....
}
NFS中检查用户对文件访问权限的函数是nfs_do_access(),这个函数首先在文件索引节点结构里的红黑树中查找用户的访问权限,如果找到了直接检查权限;如果不存在就向服务器发起ACCESS请求,将返回的访问权限添加到红黑树中,然后检查用户的访问权限。
参数inode:这是一个文件索引节点,表示一个文件
参数cred:这是用户信息,表示客户端一个用户
参数mask:这是请求的访问权限,如MAY_READ、MAY_WRITE、MAY_EXEC
static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
{
struct nfs_access_entry cache;
int status;
// 步骤1 在红黑树中查找访问权限
status = nfs_access_get_cached(inode, cred, &cache);
if (status == 0) // 0表示找到了,不需要发起ACCESS请求了.
goto out; // 直接检查访问权限
/* Be clever: ask server to check for all possible rights */
// 步骤2 发起ACCESS请求
cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ; // 只查找读、写、执行权限.
cache.cred = cred; // 用户信息,请求这个用户的访问权限
cache.jiffies = jiffies; // 这是一个时间戳
status = NFS_PROTO(inode)->access(inode, &cache);