设置layout

来源:互联网 发布:滚动屏软件 编辑:程序博客网 时间:2024/05/17 05:56

    layout需要MDS、DS和客户端三方共同支持,当客户端通过GETATTR请求获取了layout类型后,还需要检查自己是否支持这种类型,客户端检查、设置layout的函数是set_pnfs_layoutdriver()。

    RFC5661定义了三种layout,三种layout的编号依次为

enum pnfs_layouttype {        LAYOUT_NFSV4_1_FILES  = 1,        LAYOUT_OSD2_OBJECTS = 2,        LAYOUT_BLOCK_VOLUME = 3,};
layout编号从1开始,0是一个保留序号,不允许出现编号为0的layout类型。

客户端与pNFS相关的数据结构是struct pnfs_layoutdriver_type,这个数据结构很恐怖,包含了很多函数:

struct pnfs_layoutdriver_type {        // 这个数据结构链接到全局链表pnfs_modules_tbl中        struct list_head pnfs_tblid;        const u32 id;           // 这种layout类型的编号.        const char *name;       // 这种layout类型的名称        struct module *owner;   // 模块        unsigned flags;         // 一些标志位        int (*set_layoutdriver) (struct nfs_server *, const struct nfs_fh *);        int (*clear_layoutdriver) (struct nfs_server *);        struct pnfs_layout_hdr * (*alloc_layout_hdr) (struct inode *inode, gfp_t gfp_flags);        void (*free_layout_hdr) (struct pnfs_layout_hdr *);        struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr, gfp_t gfp_flags);        void (*free_lseg) (struct pnfs_layout_segment *lseg);        /* test for nfs page cache coalescing */        const struct nfs_pageio_ops *pg_read_ops;         const struct nfs_pageio_ops *pg_write_ops;        struct pnfs_ds_commit_info *(*get_ds_info) (struct inode *inode);        void (*mark_request_commit) (struct nfs_page *req,                                     struct pnfs_layout_segment *lseg,                                     struct nfs_commit_info *cinfo);        void (*clear_request_commit) (struct nfs_page *req,                                      struct nfs_commit_info *cinfo);        int (*scan_commit_lists) (struct nfs_commit_info *cinfo,                                  int max);        void (*recover_commit_reqs) (struct list_head *list,                                     struct nfs_commit_info *cinfo);        int (*commit_pagelist)(struct inode *inode,                               struct list_head *mds_pages,                               int how,                               struct nfs_commit_info *cinfo);        /*         * Return PNFS_ATTEMPTED to indicate the layout code has attempted         * I/O, else return PNFS_NOT_ATTEMPTED to fall back to normal NFS         */        enum pnfs_try_status (*read_pagelist) (struct nfs_read_data *nfs_data);        enum pnfs_try_status (*write_pagelist) (struct nfs_write_data *nfs_data, int how);        void (*free_deviceid_node) (struct nfs4_deviceid_node *);        void (*encode_layoutreturn) (struct pnfs_layout_hdr *layoutid,                                     struct xdr_stream *xdr,                                     const struct nfs4_layoutreturn_args *args);        void (*cleanup_layoutcommit) (struct nfs4_layoutcommit_data *data);        void (*encode_layoutcommit) (struct pnfs_layout_hdr *layoutid,                                     struct xdr_stream *xdr,                                     const struct nfs4_layoutcommit_args *args);};

现在暂时不讲这些函数,后面用到的时候再讲。file layout中这个数据结构定义如下:

static struct pnfs_layoutdriver_type filelayout_type = {        .id                     = LAYOUT_NFSV4_1_FILES,        .name                   = "LAYOUT_NFSV4_1_FILES",        .owner                  = THIS_MODULE,        .alloc_layout_hdr       = filelayout_alloc_layout_hdr,        .free_layout_hdr        = filelayout_free_layout_hdr,        .alloc_lseg             = filelayout_alloc_lseg,        .free_lseg              = filelayout_free_lseg,        .pg_read_ops            = &filelayout_pg_read_ops,        .pg_write_ops           = &filelayout_pg_write_ops,        .get_ds_info            = &filelayout_get_ds_info,        .mark_request_commit    = filelayout_mark_request_commit,        .clear_request_commit   = filelayout_clear_request_commit,        .scan_commit_lists      = filelayout_scan_commit_lists,        .recover_commit_reqs    = filelayout_recover_commit_reqs,        .commit_pagelist        = filelayout_commit_pagelist,        .read_pagelist          = filelayout_read_pagelist,        .write_pagelist         = filelayout_write_pagelist,        .free_deviceid_node     = filelayout_free_deveiceid_node,};

    这个数据结构保存在struct nfs_server中了,表示这个NFS文件系统使用的layout类型。

struct nfs_server {        ......        struct pnfs_layoutdriver_type  *pnfs_curr_ld;        ......}
    另外,客户端还定义了一个全局链表pnfs_modules_tbl,这个链表中保存的也是struct pnfs_layoutdriver_type。因为layout最多有三种类型,因此这个链表中最多有三个元素。现在可以讲解了set_pnfs_layoutdriver()。

voidset_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh,                      u32 id){        struct pnfs_layoutdriver_type *ld_type = NULL;        // 编号为0的layout类型已经预留了,表示不使用layout.        if (id == 0)                goto out_no_driver;// EXCHGID4_FLAG_USE_PNFS_MDS、EXCHGID4_FLAG_USE_NON_PNFS表示服务器角色,// 这些标志位是通过EXCHANGE_ID获取的.        if (!(server->nfs_client->cl_exchange_flags &                 (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))) {                printk(KERN_ERR "NFS: %s: id %u cl_exchange_flags 0x%x\n",                        __func__, id, server->nfs_client->cl_exchange_flags);                goto out_no_driver;        }// 在全局链表pnfs_modules_tbl中查找是否已经加载这个layout驱动了.        ld_type = find_pnfs_driver(id);        if (!ld_type) {         // 这个内核模块还没有加载                // nfs_layout_nfsv41_files.ko  blocklayoutdriver.ko  objlayoutdriver.ko// 好吧,加载这个内核模块.                request_module("%s-%u", LAYOUT_NFSV4_1_MODULE_PREFIX, id);                ld_type = find_pnfs_driver(id);         // 再次查找                if (!ld_type) {         // 还是没有找到,只好出错了.                        dprintk("%s: No pNFS module found for %u.\n",                                __func__, id);                        goto out_no_driver;                }        }// 客户端已经加载这个layout驱动程序了// 关联到这个nfs_server结构中.        server->pnfs_curr_ld = ld_type;        // 如果layoutdriver定义了set_layoutdriver,就需要先执行这个函数        // file layout没有定义这个函数,因此就不看了。        if (ld_type->set_layoutdriver            && ld_type->set_layoutdriver(server, mntfh)) {                // 但是函数执行过程中出错了                printk(KERN_ERR "NFS: %s: Error initializing pNFS layout "                        "driver %u.\n", __func__, id);                module_put(ld_type->owner);                goto out_no_driver;        }        /* Bump the MDS count */// 增加NFS客户端源数据服务器的数量        atomic_inc(&server->nfs_client->cl_mds_count);        dprintk("%s: pNFS module for %u set\n", __func__, id);        return;out_no_driver:        dprintk("%s: Using NFSv4 I/O\n", __func__);        server->pnfs_curr_ld = NULL;}
    这个函数逻辑很简单,首先根据从MDS获取的layout类型编号在全局链表pnfs_modules_tbl中查找对应的pnfs_layoutdriver_type结构。如果找到了,说明已经加载这种layout的驱动程序了。如果没有找到,则首先加载这种layout的驱动程序,然后添加到全局链表中。最后设置nfs_server结构中的指针pnfs_curr_ld就可以了。

原创粉丝点击