2015-04-21 21 views
13

Sabit diskten yalnızca bir sektörü bellekteki belirli bir sayfaya okumak istiyorum, bu sayfa ayrılmış ve herhangi bir adres eşlemesiyle eşlenmiyor. this solution'u buldum, ancak bir dosyayı bir blok aygıtına ve bir sektöre nasıl çevireceğimi bilmiyorum. Hedef sayfa aynı işlevi kullanamazsınız herhangi eşleme olmadığındanLinux çekirdeğinde biyo isteği kullanarak bir sektör nasıl okunmalı

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

, ama cihazı ve bir sektöre FILP çevirmek gerekir: Örneğin, dosyanın mm/filemap.c işlev do_generic_file_read orada bu çizgidir Kendi biyo isteğimi üretebilmek. bunu nasıl yapabilirim?

Düzenleme

Bunu ekleyerek, olası bir çözüm olarak bu çalıştı 1, ilk sonra doğrudan cihaz almak için ext2_get_block çağırır sektörünü hesaplar Daha sonra istenen sayfa konumunu ekler ve biyo gönderir istek:

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

Bu istenen sayfa bir adres eşleştirmesi olmadığı için, biyo isteği oluşturmak için fonksiyonu mevcut adres eşleştirmesi kullanır. Bu tek bir sorunu var, submit_bio hat bu neden:

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

ve daha sonra bu neden:

[ 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 

ve bu:

[ 48.957807] hda: lost interrupt 

ben mm/readahead.c içinde __do_page_cache_readahead çalışması için bu katma ama mm/filemap.c ya da benzeri işlevlere benzer şekilde eklenebilir. belki birisi bu sorunu çözebilir!

+0

Bunu bir ISR'de yapmaya mı çalışıyorsunuz? – stark

cevap

1

Sektörü hesaplama şekliniz iyi görünüyor, ancak istediğiniz kesin sektörle sonuçlanacağını düşünmüyorum. Yani, blok cihazını yanlış anlıyorsun. ext2_get_block'u çağırmayın, çünkü sadece dosya sistemine özgü değil, aynı zamanda ne yaptığını gerçekten anlayamıyorsunuz ve blok cihazını almanın standart yolundan çok daha karmaşıktır. Bu test ve sonra sadece bir modül içinde derlersiniz eylem olarak görmek ve bir kanca kurmak istiyorsanız Bunun yerine, sadece, aynı zamanda

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

kullanmak (eğer belli bir blok aygıtı açtığınızda, böylece sen misin yaratıldı) işlevi tetikleyecektir. Mevcut işlevlerinize eklerken kullandığınız yönteminiz, çekirdeğin şu anda ne yapması gerektiğine müdahale edebilir ve testleriniz bozulabilir.

İlgili konular