2015-04-21 11 views
13

Chcę odczytać tylko jeden sektor z dysku twardego na określoną stronę w pamięci, ta strona jest zarezerwowana i nie jest mapowana na żadne mapowanie adresu. Znalazłem this solution, ale nie wiem, jak przetłumaczyć plik na urządzenie blokowe i sektor. Na przykład w funkcji do_generic_file_read w pliku mm/filemap.c jest ta linia:Jak odczytać sektor za pomocą żądania biologicznego w jądrze Linuksa

error = mapping->a_ops->readpage(filp, page); 

ponieważ strona docelowa nie jest jakiegokolwiek mapowania nie mogę wykorzystać tę samą funkcję, ale muszę przetłumaczyć filp urządzenia i sektora aby móc wygenerować moją własną prośbę o bio. jak mogę to zrobić?

Edycja 1

próbowałem to jako możliwe rozwiązanie, dodając to, to najpierw oblicza sektora, a następnie bezpośrednio wywołuje ext2_get_block uzyskać urządzeniu, następnie dodaje odpowiednią lokalizację strony i składa bio żądanie:

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); 

ta wykorzystuje istniejące mapowanie adresów w funkcji do tworzenia żądania bio, ponieważ żądana strona nie posiada mapowanie adresów. Ma tylko jeden problem, linia submit_bio powoduje to:

[ 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 ]--- 

i później powoduje to:

[ 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 

a to:

[ 48.957807] hda: lost interrupt 

dodałem to funkcjonować __do_page_cache_readahead w mm/readahead.c ale można go dodać podobnie do mm/filemap.c lub podobnych funkcji. może ktoś może rozwiązać ten problem!

+0

Czy próbujesz to zrobić w ISR? – stark

Odpowiedz

1

Sposób, w jaki obliczasz sektor, wydaje się być w porządku, chociaż nie sądzę, że otrzymasz dokładnie taki sektor, jaki chcesz. Mówiąc to, całkowicie blokujesz urządzenie blokujące. Nie odwołuj się do ext2_get_block, ponieważ nie tylko jest to system plików specyficzny, ale nie wydaje się, aby naprawdę rozumiał, co robi i jest o wiele bardziej mylący niż standardowy sposób uzyskiwania urządzenia blokowego. Zamiast tego, po prostu użyć

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

Ponadto, jeśli chcesz przetestować i zobaczyć go w akcji, a potem po prostu skompilować go do modułu i skonfigurować hak tak, że po otwarciu pewnego urządzenia blokowego (to ty utworzony) wywoła funkcję. Twoja obecna metoda dodania go do istniejących funkcji może zakłócać działanie aktualnie wykonywanego jądra, a to zepsuje testy.

Powiązane problemy