linux块设备5

linux 3.1.5


blk-merge.c

blk_recalc_rq_segments/__blk_recalc_rq_segments: 计算request中的segments数。高page的算, 被blk_core调用

blk_recount_segments: 仅统计这个bio的segments, 不包含next的, 被driver/fs/其他merge函数调用


blk_phys_contig_segment:

cluster为0, 返回0,

bio bi_seg_back_size + bio next bi_seg_front_size > max segment size, 返回0

bi_seg_back_size是指这个bio当中剩余的不足max segment的部分

bi_seg_front_size其实指这个bio整个就不足max segment


bio为空或者无数据, 返回1


bio和next bio不是相连的。 返回0

BIO_SEG_BOUNDARY: 检查边界是否相连, 是, 返回1

返回1, 表示可merge(可在一个segment中), 返回0, 不可merge(不可在一个segment中)


blk_rq_map_sg:由driver或者blk-lib调用

map request到sglist(scatter list), 并且返回segment数量

ll_new_hw_segment: merge bio到request


ll_back_merge_fn/ll_front_merge_fn: 调用ll_new_hw_segment 来merge bio到request,它被

bio_attempt_back_merge/bio_attempt_front_merge调用, 分别把bio加到request的tail和头



ll_merge_requests_fn: check是否能merge reqest和next request


blk_rq_set_mixed_merge: 设置request mixed merge标志


blk_account_io_merge:统计分区的io stat, 并且如果无分区引用, 删除分区


attempt_merge:

检查是否request, net request是否mergable

不merge dsiacard, secure request

不merge方向不同, 不merge不 在同一个disk的, 不merge next是special

调用 ll_merge_requests_fn检查是否能merge, 并且更新segment count

如有必要, set mixed merge标志

将next bio加到request bio tail

调用elv_merge_requests在elevator层作处理

调用blk_account_io_merge处理next

调用__blk_put_request释放next



attempt_back_merge/attempt_front_merge/blk_attempt_req_merge:

调用attempt_merge尝试merge

由blk core的make request调用


blk-settings.c:

blk_queue_prep_rq: 设置prepare request queue函数, 由driver调用

blk_queue_unprep_rq: 设置unprepare函数, 由driver调用

blk_queue_merge_bvec/blk_queue_softirq_done/blk_queue_rq_timeout/

blk_queue_rq_timed_out/blk_queue_lld_busy: 注册相应的request处理函数, 由driver调用


blk_set_default_limits: 设置limit的缺省值, driver调用和blk setting的make request调用


blk_queue_make_request: 设置queue的make_request_fn函数, 初始化一些变量, 由driver, core(core的blk_init_allocated_queue_node)调用


blk_queue_bounce_limit: 设置queue的bounce buffer的limit, driver和setting调用

blk_queue_max_hw_sectors/blk_limits_max_hw_sectors: 设置最大 hw_sectors, 并且设置max_sectors为max_hw_sector size和default 1024两者的最小值, 由driver setting调用


blk_queue_max_discard_sectors: 设置max discard sectors值

blk_queue_max_segments/blk_queue_max_segment_size/blk_queue_logical_block_size/blk_queue_physical_block_size/blk_queue_alignment_offset/blk_limits_io_min/blk_queue_io_min/blk_limits_io_opt/blk_queue_io_opt/blk_queue_stack_limits/ : driver调用, 设置各limit


blk_queue_stack_limits/blk_stack_limits/: 为一些stack driver, 设置所有的设备的common的limit,(各;imit在一个函数里设置)



blk_queue_dma_pad: 设置dma pad mask

blk_queue_update_dma_pad: 更新pad mask


blk_queue_dma_drain: 设置dma drain buffer, 是一些如atapi一样使用的dma设备需要真实的pad buffer传输数据, 由atapi scsi调用


blk_queue_segment_boundary: 设置segment boundary

blk_queue_dma_alignment/blk_queue_update_dma_alignment: 设置更新dma aligment



blk_queue_flush: 设置queue flush标志, driver调用


blk_queue_flush_queueable: 设置queue的queueable标志


blk_settings_init: 设置blk_max_low_pfn/blk_max_pfn, 在加载blk系统的时候调用



blk-sysfs.c: blk queue的sysfs操作函数, 操作各种属性, 当有些属性修改时,需要唤醒queue或者其它

show, store等

blk_register_queue: register a queue在add disk的时候

blk_unregister_queue: unregister a queue在del disk时




blk-tag.c: 当前被scsi使用,

生成queue的tag map, 并对request生成tag




blk-throttle.c: 用于控制request queue的io bandwidth

主要三个函数被blk-core调用:

blk_throtl_init/: blk core生成queue的时候

blk_throtl_bio/: blk-core产生request的时候

blk_throtl_exit: blk queue release的时候(sysfs kobj)


throtl_init: 模块初始化函数, 分配workqueue, 注册blkio_policy_throtl到blkio_list(是blk cgoup list, blk cgroup是cgroup, blk cgroup由好多cft, 其中的一些就是控制流量的throttl, 每个cft在subsys中有个目录和文件, 有相应的读写操作函数, 这些函数最终会调到blkio_policy_throtl所定义的函数。)

blkio_policy_throtl:

policy是BLKIO_POLICY_THROTL

含有bps和iops的更新函数。


blk_throtl_init:

生成和初始化throtl_data,init blk_throtl_work, 设置td的queue为blk core生成的queue

调用throtl_alloc_tg生成throtl_grp, 这个函数还会调用blkio_alloc_blkg_stats生成blk group的每cpu变量 stats, 初始化tg

设置td的root_tg为刚生成的tg

调用throtl_init_add_tg_lists把tg加入到td的tg_list, 这个函数调用__throtl_tg_fill_dev_details设置tg的dev(来自td queue的dev), 调用blkiocg_add_blkio_group把tg加到blkio_root_cgroup, 初始化tg的bps, iops


设置q->td = td;


blk_throtl_exit:

停止workqueue

从cgroup删除tg

从td删除tg

如有需要同步rcu, synchronize_rcu(nr_undestroyed_grps》0时)

free td



blk_throtl_bio: 增加bio到tg

对于throttled bio, do nothing

查找tg(以td为key, 在blkcg中查找), 如果由、有, 且tg的bps, iops在指定方向无定义, 就更新cgroup的stat, 返回0, (对于blk core来讲, 返回0, 意味着将调用queue的make_request_fn函数, 否则会将bio加入tg, 不必调用该函数)

get tg(可能有, 可能新生成)

如果tg中的queue数大于0, 设update_disptime= false(不必现在schedule tg workqueue)

调用tg_may_dispatch检查是否可以dispatch bio到tg, 返回1, 不可以(但更新了tg的bytes_disp, io_disp, 以及cgroup的stat, ?)。还调用throtl_trim_slice,一面bio长时间得不到响应

调用throtl_add_bio_tg,增加bio到tg

如update_disptime为true, 调用tg_update_disptime更新, tg的disptime, 然后throtl_schedule_next_dispatch调度tg work



xchg: 交换数据, 因为原子性, 也会用于设置。


throtl_unlink_blkio_group: destroy tg, cgroup destroy的时候使用


throtl_schedule_delayed_work: 如果nr queues > 0或者limit changes,调度 throtld_workqueue,


blk_throtl_work: 调度程序, 调用throtl_dispatch。

throtl_dispatch:调用throtl_process_limit_change处理limit 变化的情况, 如果total_nr_queued不为0, 调用throtl_select_dispatch处理queue

throtl_unlink_blkio_group: destroy tg


throtl_dispatch:
roundup: ((x+(y-1))/y) * y: 将x按照y的倍数向上圆整
rounddown: x - x%y: 将x按y向下圆整

tg_may_dispatch: 返回1, 表示立即可以执行, 返回0, 表示还要等待wait个时间
如果tg的bps[rw]/iops[rw] = -1, 表示没有流量限制,返回1
如果tg的slice已经用完, 重新设置, 否则如果slice end的时间小于当前时间加上throtl_slice, 需要重新设置slice end时间
调用tg_with_in_bps_limit(bytes_disp(大小)和bps(限制)比较, 大小加上bio size小于bps, 在限制内, 否则用剩余的size计算等待时间)/tg_with_in_iops_limit(io_disp(大小)和iops(限制)比较, 小于在限>制内)进行流量限制检查, 在限制内的, 返回1, wait为0
取iops/bps的较大值, 并用此重设slice end

io_disp指读或者写的io次数
bps指每次读写多少

throtl_charge_bio: 在可以dispatch之后, 用此函数更新io_disp/bytes_disp,还有tg cpu stat

blk_throtl_bio: 当core的make request在调用它的时候, 如果返回非0, 就不会调用queue的make request fn, 否则调用。
对于blk_throtl_bio函数来讲, 在get tg失败的时候才会返回非0, 其他不管是queue bio或者是立即dispatch, 都返回0
throtl_trim_slice: 对iops/bps进行裁剪, 防止bio长时间queued(不是特别理解)
如果nr_queued大于0或者现在不可以dispatch, 就queue bio(就是把bio加到tg的bio list上), 并且把tg插到tg树(tg_service_tree)上面
同时如果插入之前nr_queued是0(意指新的tg吧!), 则需要更新dispatch时间,并发起调度(用td的min disp时间调度(触发)tg work(这个时间是由tg数得到的))(过disp time时间去执行blk_throtl_work, 而blk_throtl_work将调用throtl_dispatch)。
如果加入了queue, biop会被置空, 这样的话在blk core的make request中就不会运行。


throtl_dispatch:
如果是limit改变引起的, 调用throtl_process_limit_change,
如果queue的size不是0, 调用throtl_select_dispatch(--->throtl_dispatch_tg->tg_dispatch_one_bio)得到可以dispatch的bio的list(bio_list_on_stack),从每个tg里面拿出最大读的%75, 写的25%个数的bio。如果这个tg中还有bio, 那么还要把这个tg插入到树中
调用throtl_schedule_next_dispatch启动下次的调度
如果这个list中有(bio_list_on_stack), 对每个bio调用generic_make_request,


blk-timeout.c:
DECLARE_FAULT_ATTR(fail_io_timeout), 定义timeout相关的io fail的sysfs的操作

blk_delete_timer: 删除request对应的timer
blk_rq_timed_out: timeout处理, 调用queue的rq_timed_out_fn, 并根据返回值做相应处理(完成或者重启), 被blk_rq_timed_out_timer/abort调用

blk_add_timer:把request加入到timeoutlist





你可能感兴趣的:(linux,list,IO,buffer,merge,alignment)