I'm currently trying to implement a (not that ?) simple kernel block device driver.
I inspired mainly from the book Linux Device Drivers, 3rd Edition which is not totally up-to-date anymore as it was published in 2005.
Anyway the logic is still there and I learnt a lot from it. However examples are not really effective as many things have changed since 2005.
I found a github repository where examples should be updated to work on recent kernels but I think there is still some things to update as I can't adapt examples to make it work on kernel 4.9.0
Here is how my module is made:
At initialization :
register_blkdev
gendisk
structuregendisk
structureadd_disk
Then I implemented a function to handle request events from request queue and treat read and write events on the block device.
Here is the function : (It's highly inspired from LLD-3rd with some modifications to match current kernel functions)
static void block_mod_request(struct request_queue *queue)
{
printk(KERN_NOTICE "Entering request function\n");
struct request *request;
while(NULL != (request = blk_fetch_request(queue)))
{
blk_mod_t *self = request->rq_disk->private_data;
// Check if request is a filesystem request (i.e. moves block of data)
if(REQ_TYPE_FS != request->cmd_type)
{
// Close request with unsuccessful status
printk(KERN_WARNING "Skip non-fs request\n");
__blk_end_request_cur(request, -EIO);
continue;
}
// Treat request
block_mod_transfer(self, blk_rq_pos(request), blk_rq_cur_sectors(request), request->buffer, rq_data_dir(request));
// Close request with successful status
__blk_end_request_cur(request, 0);
}
return;
}
However at compiling I got the following error:
block_mod.c:82:91: error: ‘struct request’ has no member named ‘buffer’
block_mod_transfer(self, blk_rq_pos(request), blk_rq_cur_sectors(request), request->buffer, rq_data_dir(request));
After checking file blkdev.h
into kernel v4.9.0 headers, it seems that the field buffer
no longer exists into struct request
.
However I'm not able to find any information on how things have evolved and how to modify the code to make it work.
If I understand well, the buffer
field is supposed to be a pointer to a virtual kernel address. I suppose that once this buffer filled/read the kernel handles the transfer of data to/from userspace.
I'm kinda lost because I can't find where I should find the kernel virtual address if it's not given by the request anymore.
How am I supposed to know where to transfert data?
Block devices are nonvolatile mass storage devices whose information can be accessed in any order. Hard disks, floppy disks, and CD-ROMs are examples of block devices. OpenBoot typically uses block devices for booting.
Block devices − A block device is one with which the driver communicates by sending entire blocks of data. For example, Hard disks, USB cameras, Disk-On-Key etc. Character devices − A character device is one with which the driver communicates by sending and receiving single characters (bytes, octets).
Block devices are characterized by random access to data organized in fixed-size blocks. Examples of such devices are hard drives, CD-ROM drives, RAM disks, etc.
The block devices on a system can be discovered with the lsblk (list block devices) command. Try it in the VM below. Type lsblk at the command prompt and then press Enter.
The message from the commit containing the culprit change, authored by Ming Lei:
block: remove struct request buffer member
This was used in the olden days, back when onions were proper yellow. Basically it mapped to the current buffer to be transferred. With highmem being added more than a decade ago, most drivers map pages out of a bio, and
rq->buffer
isn't pointing at anything valid.Convert old style drivers to just use
bio_data()
.
There are some good resources for reading about BIO, such as this post on lwn. A relevant snippet:
char *bio_data(struct bio *bio)
Returns the kernel virtual address for the data buffer.
So it looks like you will have more success using bio_data(rq->bio)
in place of rq->buffer
.
Edit by author:
Also found this link which is in two parts and presents in first part the bio layer and in second part the request layer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With