How to read a sector using a bio request in Linux kernel

driver, kernel, linux

Solution

It is an old question, but anyway here is the code for reading, I hope it will help someone:

int readPage(struct block_device *device, sector_t sector, int size,
     struct page *page)
{
    int ret;
    struct completion event;
    struct bio *bio = bio_alloc(device, 1, REQ_OP_READ, GFP_NOIO);

    bio->bi_iter.bi_sector = sector;

    bio_add_page(bio, page, size, 0);
    init_completion(&event);

    bio->bi_private = &event;
    bio->bi_end_io = readComplete;

    submit_bio(bio);
    wait_for_completion(&event);
    ret = test_bit(BIO_UPTODATE, &bio->bi_flags);

    bio_put(bio);
    return ret;
}

And for writing:

void writePage(struct block_device *device,
    sector_t sector, int size, struct page *page)
{
    struct bio *bio = bio_alloc(device, 1, REQ_OP_WRITE, GFP_NOIO);
    bio->bi_iter.bi_sector = sector;

    bio_add_page(bio, page, size, 0);
    bio->bi_end_io = writeComplete;

    submit_bio(bio);
}

`page` can be allocated with alloc_page(GFP_KERNEL). Also for changing data in `page` use `page_address(page)`. It returns `void*` so you can interpret that pointer as whatever you want.

Problem

How do I create my own bio request to read a sector from the disk drive ? I am trying the following but it freezes the 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"); } ```

Original source