不知道情景分析的格式怎样写比较容易读,为防止自己忘记,直接把代码贴过来,加注释(当然是自己的理解,可能有错误,欢迎拍砖)
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,若其为空,则需要申请内存。并初始化
//此函数中,
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申请一个layoutresult = 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;
}