2012-10-04 12 views
11

Jak utworzyć własne żądanie bio do odczytu sektora z dysku?Jak odczytać sektor za pomocą żądania bio w jądrze Linuksa

Próbuję wykonać następujące czynności, ale zamraża system.

static void read_bio() 
{ 
    struct bio *b; 
    struct page *p; 

    b = bio_alloc(GFP_KERNEL, 1); 
    if (!b) { 
     printk(KERN_INFO "bio allocation failed\n"); 
    } 
    bio_init(b); 

    b->bi_sector = 10000; 
    b->bi_bdev = bd; /* "/dev/sda1" */ 
    b->bi_end_io = bio_end_clone; 

    p = alloc_page(GFP_KERNEL); 
    if (!p) { 
     printk(KERN_INFO "page allocation failed\n"); 
    } 
    bio_add_page(b, p, PAGE_SIZE, 0); 
    b->bi_private = p; 

    bio_get(b); 
    submit_bio(READ, b); 
    printk(KERN_DEBUG "submit read request\n"); 
} 
+0

Próbowałem używać sb_bread(), który działa znacznie lepiej. Ale nadal blokuje się w funkcji niestandardowego żądania sterownika. (Zgaduję, że to z powodu jakiegoś zamka). Próbuję osiągnąć to, że chcę przeczytać blok przed zapisaniem do tego bloku, zajmuję się tym, zastępując make_request_fn urządzenia blokowego. –

Odpowiedz

6

To stare pytanie, ale w każdym razie tutaj jest kod do czytania, mam nadzieję, że to pomoże ktoś:

int readPage(struct block_device *device, sector_t sector, int size, 
    struct page *page) 
{ 
    int ret; 
    struct completion event; 
    struct bio *bio = bio_alloc(GFP_NOIO, 1); 
    bio->bi_bdev = device; 
    bio->bi_sector = sector; 
    bio_add_page(bio, page, size, 0); 
    init_completion(&event); 
    bio->bi_private = &event; 
    bio->bi_end_io = readComplete; 
    submit_bio(READ | REQ_SYNC, bio); 
    wait_for_completion(&event); 
    ret = test_bit(BIO_UPTODATE, &bio->bi_flags); 
    bio_put(bio); 
    return ret; 
} 

A do zapisu:

void writePage(struct block_device *device, 
      sector_t sector, int size, struct page *page) 
{ 
    struct bio *bio = bio_alloc(GFP_NOIO, 1); 
    bio->bi_bdev = vnode->blkDevice; 
    bio->bi_sector = sector; 
    bio_add_page(bio, page, size, 0); 
    bio->bi_end_io = writeComplete; 
    submit_bio(WRITE_FLUSH_FUA, bio); 
} 

page można przydzielić z alloc_page (GFP_KERNEL). Również do zmiany danych w page użyć page_address(page). Zwraca void*, dzięki czemu można zinterpretować ten wskaźnik jako cokolwiek chcesz.

Powiązane problemy