获取layout类型

    NFSv4.1支持三种layout类型:file layout、object layout、block layout,这三种layout对数据读写过程的处理方式不同。因此pNFS系统中,客户端首先需要获取layout类型,这是在挂载文件系统时实现的。客户端挂载文件系统时需要发起GETATTR请求,获取文件系统的基本信息,这个处理函数是nfs4_proc_fsinfo。

static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
{
        int error;

        nfs_fattr_init(fsinfo->fattr);
        error = nfs4_do_fsinfo(server, fhandle, fsinfo);
        if (error == 0) {
                /* block layout checks this! */
                server->pnfs_blksize = fsinfo->blksize;
                set_pnfs_layoutdriver(server, fhandle, fsinfo->layouttype);
        }

        return error;
}

    RFC5661定义了NFS文件系统相关的很多属性,其中一个属性是fs_layout_type,这个属性表示这套pNFS环境中支持的layout类型。当MDS接收到GETATTR请求报文后,如果请求报文中设置了这个属性位,就会检查支持的pNFS类型,然后封装到应答报文中返回给客户端。客户端调用set_pnfs_layoutdriver()设置在nfs_server结构中。下一篇文章中再讲解这个函数的流程,这篇文章中主要讲讲MDS查找layout类型的过程。首先介绍一个与layout相关的数据结构struct pnfs_export_operations,这个数据结构定义了MDS中layout相关的函数。NFS是一种网络文件系统,它必须依附于一种实际的文件系统之上(比如EXT3、JFS等)。如果底层的文件系统支持pNFS,则这种文件系统必须实现struct pnfs_export_operations中定义的方法。这个数据结构定义如下:

struct pnfs_export_operations {
        int (*layout_type) (struct super_block *);

        int (*get_device_info) (struct super_block *,
                                struct exp_xdr_stream *,
                                u32 layout_type,
                                const struct nfsd4_pnfs_deviceid *);
        
        int (*get_device_iter) (struct super_block *,
                                u32 layout_type,
                                struct nfsd4_pnfs_dev_iter_res *);
        
        int (*set_device_notify) (struct super_block *,
                                  struct pnfs_devnotify_arg *);
        
        enum nfsstat4 (*layout_get) (struct inode *,
                                     struct exp_xdr_stream *xdr,
                                     const struct nfsd4_pnfs_layoutget_arg *,
                                     struct nfsd4_pnfs_layoutget_res *);
        
        int (*layout_commit) (struct inode *,
                              const struct nfsd4_pnfs_layoutcommit_arg *,
                              struct nfsd4_pnfs_layoutcommit_res *);
        
        int (*layout_return) (struct inode *,
                              const struct nfsd4_pnfs_layoutreturn_arg *);
        
        int (*can_merge_layouts) (u32 layout_type);
        
        void (*get_verifier) (struct super_block *, u32 *p);
        
        int (*get_state) (struct inode *, struct knfsd_fh *,
                          struct pnfs_get_state *);
};
    这个数据结构中函数很多,看着也很复杂,但是我们通过函数名称能大概明白每个函数的意思。比如get_device_info()应该是GETDEVICEINFO中调用的函数,laytou_get()应该是LAYOUTGET中调用的函数,layout_return()应该是LAYOUTRETURN中调用的函数,layout_type()应该是获取layout类型的函数。而且底层文件系统不必实现这个数据结构中所有的函数,根据实际情况实现部分函数就可以了。当然,"实际情况"是什么,只有这种文件系统的开发者清楚了。在后面的文章中我们将以GFS为例,GFS文件系统只实现了下列几个函数:

const struct pnfs_export_operations pnfs_dlm_export_ops = {
        .layout_type = nfsd4_pnfs_dlm_layouttype,
        .get_device_info = nfsd4_pnfs_dlm_getdevinfo,
        .get_device_iter = nfsd4_pnfs_dlm_getdeviter,
        .layout_get = nfsd4_pnfs_dlm_layoutget,
};

    为了支持pNFS,文件系统超级块中增加了一个指针 s_pnfs_op,这个指针指向了文件系统layout相关的操作函数集合。当然,这个指针目前只存在于Benny Halevy的代码树中,标准内核代码中还没有这个指针。

struct super_block {
        ......
        const struct pnfs_export_operations *s_pnfs_op;
        ......
}

    现在可以接着讲MDS查找layout类型的过程了。GETATTR请求的处理函数是nfsd4_encode_fattr(),这个函数处理了MDS支持的所有属性,其中就包含fs_layout_type,处理这个属性的代码片段如下:

__be32
nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
                struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval,
                struct svc_rqst *rqstp, int ignore_crossmnt)
{
        ......

        if ((bmval1 & FATTR4_WORD1_FS_LAYOUT_TYPES) ||
            (bmval2 & FATTR4_WORD2_LAYOUT_TYPES)) {
                // 取出底层文件系统超级块的数据结构
                struct super_block *sb = dentry->d_inode->i_sb;
                int type = 0;

                /* Query the filesystem for supported pNFS layout types.
                 * Currently, we only support one layout type per file system.
                 * The export_ops->layout_type() returns the pnfs_layouttype4.
                 */
                buflen -= 4;
                if (buflen < 0)         /* length */
                        goto out_resource;

                // 检查文件系统是否定义了layout_type()函数
                if (sb && sb->s_pnfs_op && sb->s_pnfs_op->layout_type)
                        // 调用layout_tyoe()取出文件系统的layout类型.
                        type = sb->s_pnfs_op->layout_type(sb);
                dprintk("%s: sb=%p s_pnfs_op=%p layout_type()=%p layout_type=%u\n",
                        __func__, sb, sb->s_pnfs_op, sb->s_pnfs_op ? sb->s_pnfs_op->layout_type : NULL, type);
                if (type) {
                        if ((buflen -= 4) < 0)  /* type */
                                goto out_resource;
                        WRITE32(1);     /* length */
                        // 组装进GETATTR应答报文中.
                        WRITE32(type);  /* type */
                } else
                        WRITE32(0);  /* length */
        }

        if (bmval2 & FATTR4_WORD2_LAYOUT_BLKSIZE) {
                if ((buflen -= 4) < 0)
                        goto out_resource;
                dprintk("%s: layout_blksize=%lu\n", __func__, stat.blksize);
                WRITE32(stat.blksize);
        }

        ......
}
    可以看出,nfsd4_encode_fattr()直接调用底层文件系统的layout_type()获取layout类型了,而GFS文件系统中这个函数很简单:

static int
nfsd4_pnfs_dlm_layouttype(struct super_block *sb)
{
        return LAYOUT_NFSV4_1_FILES;
}

讲完了。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值