nfs4_state_owner代表了客户端的一个用户,包含了这个用户打开的所有文件的信息。每个文件用数据结构nfs4_state表示,每打开一个文件就向nfs4_state_owner中添加一个nfs4_state结构。因此,OPEN操作中首先要检查客户端是否为当前用户创建了nfs4_state_owner结构,如果没有就创建一个。这个流程是由函数nfs4_get_state_owner()实现的。
参数server:表示一个NFS文件系统
参数cred:这是用户信息的数据结构,表示客户端的一个用户
参数gfp_flags:这是分配内存时使用的标志位
struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server,
struct rpc_cred *cred,
gfp_t gfp_flags)
{
struct nfs_client *clp = server->nfs_client; // 找到NFS客户端的数据结构
struct nfs4_state_owner *sp, *new;
spin_lock(&clp->cl_lock);
// 在server->state_owners中查找符合条件的nfs4_state_owner结构,查询条件是cred,每个cred代表一个用户.
// 返回符合条件的nfs4_state_owner结构,并增加该结构的引用计数。
// 如果nfs4_state_owner已经挂载到lru链表中了,就从lru链表中删除.
// 如果不存在符合条件的nfs4_state_owner结构,就返回NULL.
sp = nfs4_find_state_owner_locked(server, cred);
spin_unlock(&clp->cl_lock);
if (sp != NULL) // 找到了,直接退出就可以了.
goto out;
// 当前用户还没有创建nfs4_state_owner结构.为当前用户创建一个新的nfs4_state_owner结构.
// 初始化引用计数为1.
new = nfs4_alloc_state_owner(server, cred, gfp_flags);
if (new == NULL)
goto out; // 创建过程失败,分配内存过程出错了.
do {
// 为新创建的nfs4_state_owner结构分配编号
if (ida_pre_get(&server->openowner_id, gfp_flags) == 0)
break; // 分配编号过程出错了
spin_lock(&clp->cl_lock);
// 将新创建的nfs4_state_owner结构添加到红黑树中,并且设置了编号.
// 由于nfs4_alloc_state_owner()分配内存时可能休眠,这个过程中其他进程可能
// 创建了新的nfs4_state_ower结构,因此nfs4_insert_state_owner_locked()
// 将new添加到红黑树之前又查找了一次,如果找到了符合条件的nfs4_state_owner结构
// 就不添加了,这种情况下sp和new就不相同了.
sp = nfs4_insert_state_owner_locked(new);
spin_unlock(&clp->cl_lock);
} while (sp == ERR_PTR(-EAGAIN));
if (sp != new) // 查找到了符合条件的nfs4_state_owner结构,就可以释放刚刚创建的结构了.
nfs4_free_state_owner(new);
out:
// 检查LRU链表中过期的nfs4_state_owner结构,删除这些结构.
// 当nfs4_state_owner在lru链表中的时间超过了90秒就说明过期了,就需要删除了.
// 90秒内的nfs4_state_o