从函数 nfs4_process_layout_stateid()看state数据结构

本文探讨了NFS4协议中state和delegation的概念,通过分析函数nfs4_process_layout_stateid的执行流程,揭示了stateid在服务器端如何与nfs4_file结构、全局哈希表及delegation链表交互。在open和lock操作中,stateid被分别存入不同的数据结构,用于验证和管理客户端的状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对state 和 delegation一直没有准确的认识,通过下面这个函数可以大概有个了解。

服务器端,nfs4_file结构中有链表layout_state,

当客户端打开某个文件第一次获取get_layout 时候,ls = find_get_layout_state(clp, fp);是找不到对应的ls的

然后会调用verify_stateid()函数,到lockstateid_hashtbl[hashval]和stateid_hashtbl[hashval]这两个全局变量,以及nfs4_file结构中的delegation链表中查找,看是否有相等的stateid,若有,则调用ls = alloc_init_layout_state(clp, fp, stateid);创建一个layout_stateid。


lock_stateid[]这个全局变量,会在nfsd4_lock()这个接口中,添加进去一个nfs4_stateid,

stateid_hashtbl[]这个全局变量是在open的时候添加进去的。



static int
verify_stateid(struct nfs4_file *fp, stateid_t *stateid)
{
    struct nfs4_stateid *local = NULL;
    struct nfs4_delegation *temp = NULL;

    /* check if open or lock stateid */
    local = find_stateid(stateid, RD_STATE);
    if (local)
        return 0;
    temp = find_delegation_stateid(fp->fi_inode, stateid);
    if (temp)
        return 0;
    return nfserr_bad_stateid;
}


nfs4_process_layout_stateid(struct nfs4_client *clp, struct nfs4_file *fp,

                stateid_t *stateid, struct nfs4_layout_state **lsp)
{
    struct nfs4_layout_state *ls = NULL;
    __be32 status = 0;

    dprintk("--> %s clp %p fp %p \n", __func__, clp, fp);

    dprintk("%s: operation stateid=" STATEID_FMT "\n", __func__,
        STATEID_VAL(stateid));

    status = nfs4_check_stateid(stateid);
    if (status)
        goto out;

    /* Is this the first use of this layout ? */
    spin_lock(&layout_lock);
    ls = find_get_layout_state(clp, fp);
    spin_unlock(&layout_lock);
    if (!ls) {
        /* Only alloc layout state on layoutget (which sets lsp). */
        if (!lsp) {
            dprintk("%s ERROR: Not layoutget & no layout stateid\n",
                __func__);
            status = nfserr_bad_stateid;
            goto out;
        }
        dprintk("%s Initial stateid for layout: file %p client %p\n",
            __func__, fp, clp);

        /* verify input stateid */
        status = verify_stateid(fp, stateid);
        if (status < 0) {
            dprintk("%s ERROR: invalid open/deleg/lock stateid\n",
                __func__);
            goto out;
        }
        ls = alloc_init_layout_state(clp, fp, stateid);
        if (!ls) {
            dprintk("%s pNFS ERROR: no memory for layout state\n",
                __func__);
            status = nfserr_resource;
            goto out;
        }
    } else {
        dprintk("%s Not initial stateid. Layout state %p file %p\n",
            __func__, ls, fp);

        /* BAD STATEID */
        status = nfserr_bad_stateid;
        if (memcmp(&ls->ls_stateid.si_opaque, &stateid->si_opaque,
            sizeof(stateid_opaque_t)) != 0) {

            /* if a LAYOUTGET operation and stateid is a valid
             * open/deleg/lock stateid, accept it as a parallel
             * initial layout stateid
             */
            if (lsp && ((verify_stateid(fp, stateid)) == 0)) {
                dprintk("%s parallel initial layout state\n",
                    __func__);
                goto update;
            }

            dprintk("%s ERROR bad opaque in stateid 1\n", __func__);
            goto out_put;
        }

        /* stateid is a valid layout stateid for this file. */
        if (stateid->si_generation > ls->ls_stateid.si_generation) {
            dprintk("%s bad stateid 1\n", __func__);
            goto out_put;
        }
update:
        update_stateid(&ls->ls_stateid);
        dprintk("%s Updated ls_stateid to %d on layoutstate %p\n",
            __func__, ls->ls_stateid.si_generation, ls);
    }
    status = 0;
    /* Set the stateid to be encoded */
    memcpy(stateid, &ls->ls_stateid, sizeof(stateid_t));

    /* Return the layout state if requested */
    if (lsp) {
        get_layout_state(ls);
        *lsp = ls;
    }
    dprintk("%s: layout stateid=" STATEID_FMT "\n", __func__,
        STATEID_VAL(&ls->ls_stateid));
out_put:
    dprintk("%s PUT LO STATE:\n", __func__);
    put_layout_state(ls);
out:
    dprintk("<-- %s status %d\n", __func__, htonl(status));

    return status;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值