块IO子系统-通用块层

块IO子系统层级关系

         块IO子系统的一般IO处理流程:虚拟文件系统层调用通用块层提供的接口(submit_bio)向块IO子系统提交IO请求,这些请求在IO调度层经过合并/排序等操作,转换成I/O请求派发到具体的块设备等待队列,由具体的块设备驱动去处理。

        上述操作包括了两种IO请求:一种是通用块层的I/O请求,即bio;另一种是块设备驱动层的I/O请求,以request描述。

一、主要数据结构

        第一个重要的数据结构就是struct bio,上一章介绍bdi回写的时候块设备bdi回写实现_叶落随风亦随雨的博客-CSDN博客

提到从回写最后调用do_writepages,再往后就是具体的文件系统内建立bio并调用submit_bio传递到通用块层,其中bio就是一个关键。

        结构体定义如下:

struct bio {
        struct bio              *bi_next;       /* request queue link */
        struct gendisk          *bi_disk;
        unsigned int            bi_opf;         /* bottom bits req flags,
                                                 * top bits REQ_OP. Use
                                                 * accessors.
                                                 */
        unsigned short          bi_flags;       /* status, etc and bvec pool number */
        unsigned short          bi_ioprio;
        unsigned short          bi_write_hint;
        blk_status_t            bi_status;
        u8                      bi_partno;
        atomic_t                __bi_remaining;

        struct bvec_iter        bi_iter;

        bio_end_io_t            *bi_end_io;

        void                    *bi_private;
#ifdef CONFIG_BLK_CGROUP
        /*
         * Represents the association of the css and request_queue for the bio.
         * If a bio goes direct to device, it will not have a blkg as it will
         * not have a request_queue associated with it.  The reference is put
         * on release of the bio.
         */
        struct blkcg_gq         *bi_blkg;
        struct bio_issue        bi_issue;
#ifdef CONFIG_BLK_CGROUP_IOCOST
        u64                     bi_iocost_cost;
#endif
#endif

#ifdef CONFIG_BLK_INLINE_ENCRYPTION
        struct bio_crypt_ctx    *bi_crypt_context;
#endif
       union {
#if defined(CONFIG_BLK_DEV_INTEGRITY)
                struct bio_integrity_payload *bi_integrity; /* data integrity */
#endif
        };

        unsigned short          bi_vcnt;        /* how many bio_vec's */

        /*
         * Everything starting with bi_max_vecs will be preserved by bio_reset()
         */

        unsigned short          bi_max_vecs;    /* max bvl_vecs we can hold */

        atomic_t                __bi_cnt;       /* pin count */

        struct bio_vec          *bi_io_vec;     /* the actual vec list */

        struct bio_set          *bi_pool;

        /*
         * We can inline a number of vecs at the end of the bio, to avoid
         * double allocations for a small number of bio_vecs. This member
         * MUST obviously be kept at the very end of the bio.
         */
        struct bio_vec          bi_inline_vecs[];
};

其中gendisk指向具体的块设备;

bi_io_vec、bi_vcnt和__bi_cnt主要用来管理这一次IO操作涉及的内存数组,每个bio_vec结构都是一个形式为<page, offset, len>的向量,它描述的是一个特定的段:段所在的物理页、块在物理页中的偏移量、从给定偏移量开始的块长度。整个bio_io_vec结构体数组表示了一个完整的缓冲区。

/**
 * struct bio_vec - a contiguous range of physical memory addresses
 * @bv_page:   First page associated with the address range.
 * @bv_len:    Number of bytes in the address range.
 * @bv_offset: Start of the address range relative to the start of @bv_page.
 *
 * The following holds for a bvec if n * PAGE_SIZE < bv_offset + bv_len:
 *
 *   nth_page(@bv_page, n) == @bv_page + n
 *
 * This holds because page_is_mergeable() checks the above property.
 */
struct bio_vec {
        struct page     *bv_page;
        unsigned int    bv_len;
        unsigned int    bv_offset;
};

        bio_vec 则是组成 bio 数据的最小单位,他包含了一块数据所在的页,这块数据所在的页内偏移以及长度,通过这些信息就可以很清晰的描述数据具体位于内存的什么位置。

        上述描述的是bio数据所在的内存位置,通过bio_vec数组可以看出一个bio的数据可以用多个不连续的内存段连接一起表示,那么这些数据对应的块设备地址范围是如何表示的?是通过另外一个结构体bi_iter表示的,它所表示的块设备地址范围则是一个连续的空间。

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 */
};

       他们之间的关系如下图:

二、bio请求的生成和提交 

        主要介绍在文件系统层如何生成bio结构体,并调用submit_bio向通用块层提交。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值