C 如何在Linux内核中使用bio请求读取扇区

C 如何在Linux内核中使用bio请求读取扇区,c,linux,linux-kernel,C,Linux,Linux Kernel,我只想将硬盘中的一个扇区读取到内存中的特定页面,该页面是保留的,不映射到任何地址映射。我找到了,但我不知道如何将文件转换为块设备和扇区。例如,在文件mm/filemap.c中的函数do\u generic\u file\u read中有一行: error = mapping->a_ops->readpage(filp, page); 由于目标页面没有任何映射,我无法使用相同的功能,但我需要将filp转换为设备和扇区,以便能够生成我自己的bio请求。我该怎么做 编辑1 我尝试将此作为

我只想将硬盘中的一个扇区读取到内存中的特定页面,该页面是保留的,不映射到任何地址映射。我找到了,但我不知道如何将文件转换为块设备和扇区。例如,在文件
mm/filemap.c
中的函数
do\u generic\u file\u read
中有一行:

error = mapping->a_ops->readpage(filp, page);
由于目标页面没有任何映射,我无法使用相同的功能,但我需要将filp转换为设备和扇区,以便能够生成我自己的bio请求。我该怎么做

编辑1

我尝试将此作为可能的解决方案,通过添加此选项,它首先计算扇区,然后直接调用
ext2\u get\u block
获取设备,然后添加所需的页面位置并提交bio请求:

struct page *myPage;
int myRet;
struct buffer_head bh;
struct bio *bio = bio_alloc(GFP_NOIO,1);
myPage = pfn_to_page(Some_Location);
bio_init(bio);
bio->bi_sector = (sector_t)page_offset << (PAGE_CACHE_SHIFT - mapping->host->i_blkbits);
myRet = ext2_get_block(mapping->host, bio->bi_sector, &bh, 0);
bio->bi_bdev = bh.b_bdev;
bio->bi_next = NULL;
bio->bi_size = PAGE_SIZE;
bio_add_page(bio, myPage, PAGE_SIZE, 0);
submit_bio(READ, bio);
后来的原因是:

[    4.792142] ------------[ cut here ]------------
[    4.792892] WARNING: at arch/x86/kernel/pci-nommu.c:63 nommu_map_sg+0xd9/0x100()
[    4.793674] Hardware name: Standard PC (i440FX + PIIX, 1996)
[    4.794149] Modules linked in:
[    4.794607] Pid: 153, comm: kblockd/0 Not tainted 2.6.32.65 #308
[    4.795077] Call Trace:
[    4.795545]  [<ffffffff81056875>] ? warn_slowpath_common+0x65/0xa0
[    4.796024]  [<ffffffff810380a9>] ? nommu_map_sg+0xd9/0x100
[    4.796446]  [<ffffffff8121ef4a>] ? ide_dma_prepare+0xda/0x180
[    4.796900]  [<ffffffff81219923>] ? do_rw_taskfile+0x253/0x330
[    4.797532]  [<ffffffff8122311c>] ? ide_do_rw_disk+0x22c/0x320
[    4.797983]  [<ffffffff81215c3a>] ? do_ide_request+0x11a/0x600
[    4.798416]  [<ffffffff81051450>] ? __dequeue_entity+0x30/0x40
[    4.798854]  [<ffffffff810519a1>] ? finish_task_switch.constprop.110+0x31/0xc0
[    4.799391]  [<ffffffff8141fdd6>] ? thread_return+0x2a/0x1d4
[    4.799816]  [<ffffffff81052116>] ? check_preempt_wakeup+0x76/0xe0
[    4.800279]  [<ffffffff811a3be0>] ? blk_unplug_work+0x0/0x20
[    4.800754]  [<ffffffff811a5b2a>] ? generic_unplug_device+0x1a/0x30
[    4.801218]  [<ffffffff810661dc>] ? worker_thread+0x13c/0x210
[    4.802710]  [<ffffffff81069cb0>] ? autoremove_wake_function+0x0/0x30
[    4.804130]  [<ffffffff810660a0>] ? worker_thread+0x0/0x210
[    4.805357]  [<ffffffff810660a0>] ? worker_thread+0x0/0x210
[    4.806356]  [<ffffffff81069907>] ? kthread+0x77/0x80
[    4.807302]  [<ffffffff81033eaa>] ? child_rip+0xa/0x20
[    4.808500]  [<ffffffff81069890>] ? kthread+0x0/0x80
[    4.809060]  [<ffffffff81033ea0>] ? child_rip+0x0/0x20
[    4.809620] ---[ end trace 61d7e1478dbb58eb ]---
[    4.871857] hda: task_pio_intr: status=0x58 { DriveReady SeekComplete DataRequest }
[    4.872553] hda: possibly failed opcode: 0x29
[    4.873346] hda: DMA disabled
[    4.885478] Clocksource tsc unstable (delta = 115822911 ns)
[    4.886364] Switching to clocksource jiffies
[    4.919051] ide0: reset: success
这是:

[   48.957807] hda: lost interrupt

我将其添加到
mm/readahead.c
中的函数
\u do\u page\u cache\u readahead
,但它可以类似地添加到
mm/filemap.c
或类似函数中。也许有人能解决这个问题

你计算扇区的方法似乎很好,尽管我不认为你最终会得到你想要的精确扇区。也就是说,您获取的块设备完全错误。不要调用
ext2\u get\u block
,因为它不仅是特定于文件系统的,而且您似乎并不真正了解它的功能,而且它比获取块设备的标准方法更容易混淆。相反,只要使用

bio.bi_bdev = I_BDEV(mapping->host);

另外,如果你想测试它并看到它的作用,那么只需将它编译成一个模块并设置一个钩子,这样当你打开一个特定的块设备(你创建的)时,它就会触发这个函数。您当前将其添加到现有函数中的方法可能会干扰内核当前正在执行的任何操作,并且会干扰您的测试。

您是否试图在ISR中执行此操作?