2012-10-04 9 views
11

Wie erstelle ich meine eigene Bio-Anfrage, um einen Sektor aus dem Laufwerk zu lesen?Wie liest man einen Sektor mit einer Bio-Anfrage im Linux-Kernel

Ich versuche Folgendes, aber es friert das System ein.

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

Ich versuchte mit sb_bread(), die viel besser funktioniert. Aber immer noch blockiert es innerhalb der Treiberanforderungsfunktion. (Ich vermute es wegen einer Sperre). Was ich versuche zu erreichen, ist, dass ich den Block lesen möchte, bevor ein Schreibvorgang für diesen Block stattfindet. Ich bearbeite dies, indem ich das make_request_fn des Blockgeräts ersetze. –

Antwort

6

Es ist alte Frage, aber trotzdem hier ist der Code für das Lesen, ich hoffe, es wird jemand helfen:

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

Und zum Schreiben:

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 zugeordnet werden können, mit alloc_page (GFP_KERNEL). Auch zum Ändern von Daten in page verwenden Sie page_address(page). Es gibt void* zurück, damit Sie diesen Zeiger wie gewünscht interpretieren können.