ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

BLOCK层代码分析(6)之SGL聚散列表

2021-11-19 23:31:10  阅读:186  来源: 互联网

标签:nents chained 聚散 SGL table sg 分配 BLOCK


        原本计划本节介绍request的分配,发现会涉及到数据组织从bio到sgl的映射,因此本节介绍数据的SGL组织方式。

        在BLOCK层数据的组织形式为bio和request,通过这两个结构体就可以找到数据的位置。但若传输到SCSI层,硬盘位置用scsi command表示,内存中位置用scatterlist表示。本小节讲述scatterlist是如何将数据组织起来的。

1. scatterlist结构体

        结构体scatterlis包含从CPU视角和设备视角看到的数据的地址和长度(包括页内偏移)。但其中page_link有两个特殊作用:(1)当第0 bit为1时即设置SG_CHAIN,表明当前sgl是链接sgl,只起链接到下一个sgl的作用,这个sgl不会指向数据;(2)当第1bit为1时即设置SG_END,表明当前sgl是最后一个sgl,这个sgl仍指向数据。当其他情况时指向数据对应的第一个页信息。

        成员offset表示数据在页中的偏移。成员length表示数据的长度。

        成员dma_address表示数据的DMA地址即设备看到的地址,成员dma_length表示数据的DMA长度。

2. SGL类型

        SGL分为non-chained SGL和chained SGL。

        Non-chained SGL表示多个sgl是连续的,内核这里对最大的non-chained SGL数目做限制,最大不超过SG_MAX_SINGLE_ALLOC,当申请的SGL个数超过此限制时会自动生成chained SGL。

        Chained SGL存在多个的SGL链,每个SGL链中的SGL是连续的,其中每个SGL链(除了最后一个SGL链)最后一个SGL起链接作用。每个SGL链最大的SGL数目为SG_CHUNK_SIZE(128)。

3. SGL API介绍

        函数sg_alloc_table()用来分配non-chained SGL(当申请的数目nents超过限制时,也会生成chained SGL)。

int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)

        函数sg_alloc_table_chained()来分配chained SGL。其中nents为需要分配的SGL数目,first_chunk为sg_table中已经存在的SGL链,SGL链数目为first_chunk_nents。后面申请的SGL链与first_chunk相链。

​
int sg_alloc_table_chained(struct sg_table *table, int nents, struct scatterlist *first_chunk, unsigned nents_first_chunk)

        两者最终会调用__sg_alloc_table()。这里处理四种情况:

(1)first_chunk = NULL, nents <= max_ents时

        这种情况为sg_table,并没有提前分配SGL链,且需要分配SGL数目小于最大一次性能够分配的数目,此时通过alloc_fn()直接分配即可,生成non-chained SGL链。

(2)first_chunk = NULL, nents > max_ents时

        这种情况为sg_table,并没有提前分配SGL链,且需要分配SGL数目大于最大一次性能够分配的数目,此时通过alloc_fn()会分配一个包含max_ents数目的SGL的SGL链,剩下的部分分配另一个SGL链,并将它们链起来,生成chained SGL链。

(3)first_chunk != NULL, nents <= max_ents时

        这种情况为sg_table,提前分配SGL链, 且提前分配的SGL链上SGL数目满足需要的SGL链,此时会直接返回当前的sg_table。

(4)first_chunk != NULL, nents > max_ents时

         这种情况为sg_table,提前分配SGL链, 但提前分配的SGL链上SGL数目不能够满足nents数目,此时需要通过alloc_fn()分配剩余的数目的SGL组成SGL链,并与提供分配的SGL链连接起来,生成chained SGL链。

4. SCSI命令的SGL

        在SCSI层在分配request时默认内置了2个SGL(实际真正使用的仅1个,另一个做链接SGL使用),在申请时使用sg_alloc_table_chained(&cmd->sdb.table, nr_segs, cmd->sdb.table.sgl, SCSI_INLINE_SG_CNT)申请链式SGL。

        下图为申请150个SGL的情况,其中内置2个SGL为第一个SGL链,这个是随request提前分配的(静态分配),后面两个SGL链是从sgpool中申请分配的(动态分配)。

标签:nents,chained,聚散,SGL,table,sg,分配,BLOCK
来源: https://blog.csdn.net/flyingnosky/article/details/121427354

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有