我是研究Linux内核的本科生。
我对Linux内核中的I / O路径有一些疑问。
在Linux中,我想根据I / O请求的大小选择性地使用中断和轮询。
例如,我想修改内核代码,以便在fio基准测试的块大小小于64kb时进行轮询,并在大小时进行中断。
通过" 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;
}