PNFS中update_layout()情节分析

不知道情景分析的格式怎样写比较容易读,为防止自己忘记,直接把代码贴过来,加注释(当然是自己的理解,可能有错误,欢迎拍砖)



int pnfs_update_layout(struct inode *ino,

           struct nfs_open_context *ctx,
           u64 count,
           loff_t pos,
           enum pnfs_iomode iomode,
           struct pnfs_layout_segment **lsegpp)

{

    struct nfs4_pnfs_layout_segment arg = {
        .iomode = iomode,
        .offset = pos,
        .length = count
    };
    struct nfs_inode *nfsi = NFS_I(ino);
    struct pnfs_layout_type *lo;
    struct pnfs_layout_segment *lseg = NULL;
    bool take_ref = (lsegpp != NULL);
    DEFINE_WAIT(__wait);
    int result = 0;


//lo是与inode一一对应的变量,贯穿整个layout操作。在lo中,有ld_data指针,在block layout中,这个指针指向的是pnfs_block_layout,若其为空,则需要申请内存。并初始化

//此函数中,

    lo = get_lock_alloc_layout(ino);
    if (IS_ERR(lo)) {
        dprintk("%s ERROR: can't get pnfs_layout_type\n", __func__);
        result = PTR_ERR(lo);
        goto out;
    }
//查看lo中对应的lsemg链表中,是否已经包含了所要求的range
    /* Check to see if the layout for the given range already exists */
    lseg = pnfs_has_layout(lo, &arg, take_ref, !take_ref);
    if (lseg && !lseg->valid) {
        spin_unlock(&nfsi->lo_lock);
        if (take_ref)
            put_lseg(lseg);
        for (;;) {
            prepare_to_wait(&nfsi->lo_waitq, &__wait,
                    TASK_KILLABLE);
            spin_lock(&nfsi->lo_lock);
            lseg = pnfs_has_layout(lo, &arg, take_ref, !take_ref);
            if (!lseg || lseg->valid)
                break;
            dprintk("%s: invalid lseg %p ref %d\n", __func__,
                lseg, atomic_read(&lseg->kref.refcount)-1);
            if (take_ref)
                put_lseg(lseg);
            if (signal_pending(current)) {
                lseg = NULL;
                result = -ERESTARTSYS;
                break;
            }
            spin_unlock(&nfsi->lo_lock);
            schedule();
        }
        finish_wait(&nfsi->lo_waitq, &__wait);
        if (result)
            goto out_put;
    }

    if (lseg) {
        dprintk("%s: Using cached lseg %p for %llu@%llu iomode %d)\n",
            __func__,
            lseg,
            arg.length,
            arg.offset,
            arg.iomode);

        goto out_put;
    }

    /* if get layout already failed once goto out */
    if (test_bit(NFS_INO_LAYOUT_FAILED, &nfsi->pnfs_layout_state)) {
        if (unlikely(nfsi->pnfs_layout_suspend &&
            get_seconds() >= nfsi->pnfs_layout_suspend)) {
            dprintk("%s: layout_get resumed\n", __func__);
            clear_bit(NFS_INO_LAYOUT_FAILED,
                  &nfsi->pnfs_layout_state);
            nfsi->pnfs_layout_suspend = 0;
        } else {
            result = 1;
            goto out_put;
        }
    }
//要求独占lo,若访问计数非零,则当前进程会被挂起
    drain_layoutreturns(lo);
    /* Matching dec is done in .rpc_release (on non-error paths) */
    atomic_inc(&lo->lgetcount);
    /* Lose lock, but not reference, match this with pnfs_layout_release */
    spin_unlock(&nfsi->lo_lock);
//发送RPC包,想server申请一个layout
    result = get_layout(ino, ctx, &arg, lsegpp, lo);
out:
    dprintk("%s end (err:%d) state 0x%lx lseg %p\n",
            __func__, result, nfsi->pnfs_layout_state, lseg);
    return result;
out_put:
    if (lsegpp)
        *lsegpp = lseg;
    put_unlock_current_layout(lo);
    goto out;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值