上一篇文章中我们分析了layout在客户端的保存形式、相关的数据结构、客户端发起LAYOUTGET请求的时间点,这篇文章中我们详细分析一下LAYOUTGET请求的发起过程以及MDS端的处理过程。
1.客户端处理程序
首先看几个客户端的数据结构:
struct nfs4_layoutget {
// LAYOUTGET请求报文中的数据
struct nfs4_layoutget_args args;
// 存储LAYOUTGET应答报文中的数据
struct nfs4_layoutget_res res;
// 这表示一个layout
struct pnfs_layout_segment **lsegpp;
// 一些标志位
gfp_t gfp_flags;
};
struct nfs4_layoutget_args中保存了LAYOUTGET请求报文中的信息,这个数据结构定义如下:
struct nfs4_layoutget_args {
__u32 type; // layout类型
struct pnfs_layout_range range; // 这是请求数据在文件中的范围.
__u64 minlength; // 表示layout长度的最小值.
// 这是应答消息的最大长度
__u32 maxcount;
struct inode *inode; // 文件索引节点
struct nfs_open_context *ctx; // 用户信息
struct nfs4_sequence_args seq_args;
nfs4_stateid stateid; // 这是LAYOUTGET请求中使用的stateid.
// 这个字段由具体的layout类型使用,这个字段用来保存应答消息中跟layout类型相关的数据。
struct nfs4_layoutdriver_data layout;
};
struct nfs4_layoutget_res用来保存LAYOUTGET应答报文中的信息,这个数据结构的定义如下:
struct nfs4_layoutget_res {
// 文件关闭时是否需要返回layout.
__u32 return_on_close;
// 这是申请下来的layout范围
struct pnfs_layout_range range;
__u32 type; // layout类型
nfs4_stateid stateid; // 这是LAYOUTGET返回的stateid.
struct nfs4_sequence_res seq_res;
// 这是保存的是供具体layout类型使用的数据,这个指针会指向nfs4_layoutget_args结构中的layout字段。
struct nfs4_layoutdriver_data *layoutp;
};
send_layoutget()代码如下:
static struct pnfs_layout_segment *
send_layoutget(struct pnfs_layout_hdr *lo,
struct nfs_open_context *ctx,
struct pnfs_layout_range *range,
gfp_t gfp_flags)
{
struct inode *ino = lo->plh_inode; // 先取出文件索引节点
struct nfs_server *server = NFS_SERVER(ino); // 找到nfs_server结构
struct nfs4_layoutget *lgp; // 这是LAYOUTGET的参数和返回值.
struct pnfs_layout_segment *lseg; // 这是一个layout的指针
dprintk("--> %s\n", __func__);
BUG_ON(ctx == NULL);
lgp = kzalloc(sizeof(*lgp), gfp_flags); // 为LAYOUTGET请求分配参数和返回值
if (lgp == NULL)
return NULL; // 分配内存过程失败.
lgp->args.minlength = PAGE_CACHE_SIZE; // 这是最少请求的数据量
if (lgp->args.minlength > range->length)
lgp->args.minlength = range->length; // 当超出了请求的总数据量时就减少这个范围.
// 这是指定了应答消息的最大长度,当应答消息超出这个长度时服务器会返回TOOSMALL.
lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE;
lgp->args.range = *range; // 这里保存的是请求文件中的数据范围.
lgp->args.type = server->pnfs_curr_ld->id; // 这表示layout类型
lgp->args.inode =