Linux kernel之Block IO系统

1.背景

1.1 block device 处理流程

image.png
  • VFS
    VFS 将调用用户系统调用API read() 处理转换成对应的内核系统调用服务程序,并将对应的read 操作重定向到具体的文件系统的操作实现。
  • FS
    本质上,文件系统最小访问单位为block, 对于文件系统来说,文件由一个个block 构成,文件系统通过file block number定位数据在文件中的位置(相对于文件的起始位置)。而磁盘同样有一个个固定大小的block 构成,文件系统通过logical block number(相对于磁盘开始位置)定位磁盘的位置。
    1)FS根据文件系统最小可访问单位block size,确定访问的数据的内容的 file block number(相对于文件起始位置);
    2)根据1)要访问的数据的file block number,调用具体文件系统的函数,确定要访问的数据映射在磁盘中的位置logical block number(相对于磁盘);
  • Block layer
    block layer 为所有类型的块设备建立统一的模型,抽象底层HW 的细节,为块设备提供一个通用的视角。block layer 接收上层(文件系统)对块设备的磁盘操作请求,最终发送IO 情况
  • device driver
    通过发送对应的command 给HW 以驱动实际数据的传输。

1.2 block layer

  • block layer 可划分为两层:bio layer , request layer
    image.png

2. block layer 工作原理

2.0 IO处理

i. 数据组织数据结构:bio/bio_vec
ii. bio 的处理
(1)bio 的 split 和 merge;
(2)bio 的bounce;
(3)bio 包装成 request;
iii. request 的处理
(1)request 的分配和获取;
(2)request 的 plug/unplug;
(3)request 的下发;

2.1 核心数据结构 bio/bio_vec

bio :
i. main unit of I/O for the block layer and lower layers (ie drivers and stacking drivers)(官方解释)
ii. bio结构体用于表示IO 请求(1)数据在内存和磁盘的位置, (2)数据大小以及(3)IO完成情况
iii. bio 中重要的数据结构:bio_vec和bi_iter
bio_vec:描述了IO数据在内存中的组织
bi_iter: 描述了IO数据在磁盘中位置以及当前IO数据的完成情况

bio/bio_vec/bi_iter图示.png

struct bio_vec {
    struct page *bv_page;
    unsigned int    bv_len;
    unsigned int    bv_offset;
};

struct bvec_iter {
    sector_t        bi_sector;  /* device address in 512 byte
                           sectors */
    unsigned int        bi_size;    /* residual I/O count */

    unsigned int        bi_idx;     /* current index into bvl_vec */

    unsigned int            bi_bvec_done;   /* number of bytes completed in
                           current bvec */
};

iiii. bio 和request 之间的关系
request:可由在硬盘位置连续的bio链接起来的

image.png

2.2 bio 的remap

i. 特定分区的bio 的bi_sector 会重映射remap 到 整个磁盘设备的 IO偏移;
ii. 另外DM 设备 mapped device 的bio 根据其映射规则需要remap 到target device的 bio.

/*
 * Remap block n of partition p to block n+start(p) of the disk.
 */
static int blk_partition_remap(struct bio *bio)
{
    struct block_device *p = bio->bi_bdev;

    if (unlikely(should_fail_request(p, bio->bi_iter.bi_size)))
        return -EIO;
    if (bio_sectors(bio)) {
        bio->bi_iter.bi_sector += p->bd_start_sect;
        trace_block_bio_remap(bio, p->bd_dev,
                      bio->bi_iter.bi_sector -
                      p->bd_start_sect);
    }
    bio_set_flag(bio, BIO_REMAPPED);
    return 0;
}

2.3 bio 的 split 和 merge

2.3.1 基本概念
bio的切分:将一个bio分成两个bio;
bio的合并:将bio与IO请求request进行合并。
2.3.2 切分的依据
(1)q->limits.max_segments
表示请求队列request-queue中每个IO请求request的最大segment数目
(2)q->limits.max_segment_size
表示请求队列request-queue中每个segment最大的数据大小
(3)q->limits.max_sectors
表示请求队列支持一次传输request的最大扇区数目即IO请求最大size。

image.png

2.3.3 拆分图示

拆分前.png

拆分后.png

2.3.4 合并类型

前向合并.png

后向合并.png

2.3.5 合并过程-两种机制的合并
(1)与plug/unplug 机制的plug->mq_list中的request进行合并。
(2)与 IO调度器机制的schedule list (定义IO调度器)或block mq的软件queue机制ctx->rq_lists(没有定义IO调度器)上request进行合并。

2.4 bio 包装成 request

经过bio split 和bio merge, bio 还在的话,会将bio 封装到request 中,后续操作的对象由bio 转向 request。

2.5 request 的分配和获取

2.5.1 request 的分配
i. request 分配: 在初始化阶段就分配好
ii. request 申请: runtime 时通过申请一个空闲的tag获取一个空闲的request 。
iii. tag 和 request 一一对应。
xi. tag 管理:通过sbitmap_queue 管理
2.5.2 tag 管理-sbitmap_queue
sbitmap_queue 在bitmap 基础之上增加
(1)bitmap分组管理的功能(sbitmap);
(2)等待功能,即在没有无空闲bit时,会让队列一直等待
2.5.3 request 分配
i. 初始化阶段,根据硬件的queue 数量和队列深度,分配nr_hw_queues 个hctx, 每个hctx 对应一套blk_mq_tags,
ii. 每个HCTX,存在total_tags和reserved_tags两个sbitmap,分别用于分配和释放tags以及reserved_tags及与之对应的request。
iii. static_rq指向提前分配的request(包括(nvme/scsi)command以及底层驱动的私有结构)。提前分配的静态request数目为nr_hw_queues * queue_depth。

image.png

2.5.4 request 获取
先申请空闲的tag,若没有空闲的tag,则通过等待机制等空闲的tag, 然后找到对应的request,

2.6 request 的 plug/unplug

i. plug/unplug机制,通过request的延迟下发,为后续的IO增加合并和排序操作的可能,以减少request 数量。类似于蓄流和泄流。
ii. 工作流程:在开启机制后,request 会放置到plug list中(plug过程),当达到某个条件时会将request 统一下发(unplug过程)。
iii. plug的时机
plug 通过block_start_plug()开启的。对于每个线程描述符task_struct,存在成员blk_plug,若为空表示没有使能PLUG,否则表示已使能PLUG。函数blk_start_plug()进行成员初始化,同时给task_struct->plug赋值。
在开启BLOCK PLUG后,可以将通过函数blk_add_rq_to_plug()将IO请求加入到plug->mq_list中,且判断所包含的IO请求是否来自多个队列(通过成员multiple_queues)。
xi. unplug的时机
unplug的时机有三种:
(1)所积攒的IO数目达到BLK_MAX_REQUEST_COUNT(16)
(2)或遇到的IO大小超过BLK_PLUG_FLUSH_SIZE (128K)时;
(3)使用blk_finish_plug()主动冲刷;

2.7 IO 的下发路径

IO 下发处理路径
路径一:使能了plug/unplug机制,此时会等待plug池中存取足够的IO后统一往调度器插入IO,并选取IO下发;
路径二:没有使能plug/unplug机制,此时会将IO插入调度器中,并选取IO下发;
路径三:跳过调度层,直接下发IO;

image.png

参考block layer 系列文章:https://blog.csdn.net/flyingnosky/article/details/121341392

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,653评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,321评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,833评论 0 324
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,472评论 1 266
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,306评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,274评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,658评论 3 385
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,335评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,638评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,697评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,454评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,311评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,699评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,986评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,254评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,647评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,847评论 2 335

推荐阅读更多精彩内容