NFS系统read调用过程(六)

本文深入解析了NFS客户端在执行read操作时的详细流程,包括创建nfs_read_header结构,初始化nfs_pgio_header,根据请求数据量创建多个READ请求,发起READ请求,以及收尾工作。关键步骤涉及nfs_pagein_multi、nfs_read_rpcsetup及nfs_initiate_read等函数的使用。
摘要由CSDN通过智能技术生成

    这篇文章详细讲解nfs_generic_pg_readpages()的流程。

1.创建一个nfs_read_header结构

        rhdr = nfs_readhdr_alloc();
        if (!rhdr) {    // 创建rhdr失败了,不能处理desc中的缓存页了,需要释放这些缓存页
                desc->pg_completion_ops->error_cleanup(&desc->pg_list);
                return -ENOMEM;
        }
创建nfs_read_header结构的函数是nfs_readhdr_alloc(),系统为nfs_read_header结构创建了slab缓存,名称是nfs_rdata_cachep,从slab缓存中分配内存。

struct nfs_read_header *nfs_readhdr_alloc(void)
{
        struct nfs_read_header *rhdr;

        // 从slab中分配内存
        rhdr = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL);
        if (rhdr) {
                struct nfs_pgio_header *hdr = &rhdr->header;    // 这是nfs_pgio_header结构

                // 对nfs_pgio_header进行一些初始化
                INIT_LIST_HEAD(&hdr->pages);    // 这是一个链表,链表中保存的数据结构是nfs_page
                INIT_LIST_HEAD(&hdr->rpc_list); // 这是一个链表,链表中保存的数据结构是nfs_read_data
                spin_lock_init(&hdr->lock);     // 这是一个自旋锁
                atomic_set(&hdr->refcnt, 0);    // 初始化引用计数为0
        }
        return rhdr;        // 返回新分配的nfs_read_header结构
}

当nfs_read_header创建失败时,就不能向服务器请求数据,填充缓存页了,因此需要进行错误处理,READ操作中,这个处理函数是nfs_async_read_error()。这个函数定义如下:

参数head:这是一个链表,链表中保存的是nfs_page结构,这是需要填充的缓存页。

// 当创建nfs_read_header结构失败,不能继续处理读请求了.
static void
nfs_async_read_error(struct list_head *head)
{
        struct nfs_page *req;

        while (!list_empty(head)) {     // 依次删除链表中的每个缓存页
                req = nfs_list_entry(head->next);       // 取出链表中一个nfs_page结构
                nfs_list_remove_request(req);           // 从链表中摘除
                nfs_readpage_release(req);              // 释放这个缓存页
        }
}
这个函数摘除链表中所有的缓存页,然后删除这些缓存页,删除缓存页的处理函数是nfs_readpage_release()。
static void nfs_readpage_release(struct nfs_page *req)
{
    // 找到文件的索引节点
        struct inode *d_inode = req->wb_context->dentry->d_inode;

        if (PageUptodate(req->wb_page))     // 缓存中的数据是最新的
                nfs_readpage_to_fscache(d_inode, req->wb_page, 0);      // 加入到FS-Cache中

        unlock_page(req->wb_page);      // 解锁

        dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
                        req->wb_context->dentry->d_inode->i_sb->s_id,   // 文件系统名称
                        (long long)NFS_FILEID(req->wb_context->dentry->d_inode),        // 文件编号
                        req->wb_bytes,          // 缓存中有效数据量
                        (long long)req_offset(req));    // 偏移值
        nfs_release_request(req);       // 减少req的引用计数,当计数减为0时释放这个结构.
}
这里又涉及到了FS-Cache缓存。nfs_readpage_release()不仅在这里调用,当READ操作正常结束后也会调用这个函数,因此如果缓存页中的数据有效需要将数据写入FS-Cache缓存中。以后再讲解FS-Cache。

2.初始化nfs_pgio_header

        hdr = &rhdr->header;
        nfs_pgheader_init(desc, hdr, nfs_readhdr_free);
        atomic_inc(&hdr->refcnt);

初始化工作是由nfs_pgheader_init()完成的。

参数desc:这个变量在前面已经初始化好了,包含了缓存页的信息以及各种操作函数。

参数hdr:这是待初始化的变量,nfs_pgheader_init()根据desc中的信息初始化hdr。

变量nfs_readhdr_free:这是释放hdr占用内存的函数,当需要使用hdr占用的内存时调用这个函数。


                
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值