linux - 在 Linux 中,我想根据 i/o 请求的大小有选择地使用中断和轮询
问题描述
我是学习Linux内核的本科生。
我对 Linux 内核中的 I/O 路径有一些疑问。
在 Linux 中,我想根据 i/o 请求的大小有选择地使用中断和轮询。
比如我想修改内核代码,在fio benchmark的block size小于64kb的时候进行poll,大的时候进行interrupt。
由于通过“Perf”跟踪函数,它似乎与“__blkdev_direct_IO_simple”函数的工作方式不同。
如何修复代码?
__blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
{
struct file *file = iocb->ki_filp;
struct block_device *bdev = I_BDEV(bdev_file_inode(file));
struct bio_vec inline_vecs[DIO_INLINE_BIO_VECS], *vecs, *bvec;
loff_t pos = iocb->ki_pos;
bool should_dirty = false;
struct bio bio;
ssize_t ret;
blk_qc_t qc;
int i;
if ((pos | iov_iter_alignment(iter)) &
(bdev_logical_block_size(bdev) - 1))
return -EINVAL;
if (nr_pages <= DIO_INLINE_BIO_VECS)
vecs = inline_vecs;
else {
vecs = kmalloc(nr_pages * sizeof(struct bio_vec), GFP_KERNEL);
if (!vecs)
return -ENOMEM;
}
bio_init(&bio, vecs, nr_pages);
bio.bi_bdev = bdev;
bio.bi_iter.bi_sector = pos >> 9;
bio.bi_write_hint = iocb->ki_hint;
bio.bi_private = current;
bio.bi_end_io = blkdev_bio_end_io_simple;
ret = bio_iov_iter_get_pages(&bio, iter);
if (unlikely(ret))
return ret;
ret = bio.bi_iter.bi_size;
if (iov_iter_rw(iter) == READ) {
bio.bi_opf = REQ_OP_READ;
if (iter_is_iovec(iter))
should_dirty = true;
} else {
bio.bi_opf = dio_bio_write_op(iocb);
task_io_account_write(ret);
}
qc = submit_bio(&bio);
for (;;) {
set_current_state(TASK_UNINTERRUPTIBLE);
if (!READ_ONCE(bio.bi_private))
break;
if (!(iocb->ki_flags & IOCB_HIPRI) ||
!blk_mq_poll(bdev_get_queue(bdev), qc))
io_schedule();
}
__set_current_state(TASK_RUNNING);
bio_for_each_segment_all(bvec, &bio, i) {
if (should_dirty && !PageCompound(bvec->bv_page))
set_page_dirty_lock(bvec->bv_page);
put_page(bvec->bv_page);
}
if (vecs != inline_vecs)
kfree(vecs);
if (unlikely(bio.bi_status))
ret = blk_status_to_errno(bio.bi_status);
bio_uninit(&bio);
return ret;
}
解决方案
推荐阅读
- r - 如何将 Margin 列转换为两列,即 1 用于运行,其他用于 Wickets?
- python - 使用聚合方法进行 Django 计算
- node.js - 将 req 作为默认值传递给 EJS
- c++ - 可变参数模板的正确语法
- javascript - 使用 vue.js 和 laravel 从 chiled 向 parent 发送数据
- xaml - Xamarin Forms 中包含 Grid 的堆栈布局之间的间距
- amazon-web-services - 无法增长分区 ubuntu EC2
- vue.js - Vue.js:如何在名称输入属性中绑定键
- python - Allure ModuleNotFoundError 但仅在包的某些功能上
- java - Spring 教程 - 用于发布 JSON 数据的 CURL 命令不起作用