在Linux中,我想根据i / o请求的大小选择性地使用中断和轮询

时间:2018-06-08 06:04:46

标签: linux kernel

我是研究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;
    }

0 个答案:

没有答案