2012-10-04 29 views
11

¿Cómo puedo crear mi propia solicitud de bio para leer un sector de la unidad de disco?Cómo leer un sector utilizando una solicitud biológica en el núcleo de Linux

Estoy intentando lo siguiente, pero se congela el sistema.

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

He intentado usar sb_bread() que funciona mucho mejor. Pero aún bloquea dentro de la función de solicitud personalizada del controlador. (Supongo que es debido a un bloqueo). Lo que estoy tratando de lograr es que quiero leer el bloque antes de que ocurra una escritura en ese bloque, estoy manejando esto reemplazando el make_request_fn del dispositivo de bloque. –

Respuesta

6

Es cuestión de edad, pero de todos modos aquí está el código para la lectura, espero que ayude a alguien:

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

Y para escribir:

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 pueden asignarse con alloc_page (GFP_KERNEL). También para cambiar los datos en page use page_address(page). Devuelve void* para que pueda interpretar ese puntero como lo que desee.

Cuestiones relacionadas