Skip to content

Instantly share code, notes, and snippets.

@umedaikiti
Last active December 21, 2015 06:38
Show Gist options
  • Save umedaikiti/6265252 to your computer and use it in GitHub Desktop.
Save umedaikiti/6265252 to your computer and use it in GitHub Desktop.
とりあえず動作するlinuxのブロックデバイスドライバ
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/blkdev.h>
//ブロックデバイスを作ってみたくて試行錯誤しながら書いた
//とりあえず動作することを目標にしたので中身はいい加減
#define MODNAME "blkdevtest"
#define CAPACITY_SECTOR 1024
static int blktest_major;
static spinlock_t blktest_lock;
static struct request_queue *blktest_queue;
struct gendisk *blktest_gd;
static void blktest_request(struct request_queue * queue)
{
struct request *req;
struct bio_vec *bv;
struct req_iterator iter;
while((req = blk_fetch_request(queue)) != NULL){
if(req->cmd_type != REQ_TYPE_FS){
printk(KERN_INFO "req->cmd_type != REQ_TYPE_FS\n");
__blk_end_request_all(req, -1);
continue;
}
rq_for_each_segment(bv, req, iter){
int len = bv->bv_len;
unsigned char *buf = page_address(bv->bv_page) + bv->bv_offset;
int i;
printk(KERN_INFO "addr = %p, len = %d\n", buf, len);
if(rq_data_dir(req) == WRITE){
printk(KERN_INFO "WRITE: %s\n", buf);
}
else if(rq_data_dir(req) == READ){
for(i=0;i<blk_rq_cur_sectors(req);i++){
int sector = iter.bio->bi_sector + i;
printk(KERN_INFO "READ: sector = %d\n", sector);
memset(buf + 512 * i, sector, 512);
}
}
}
printk(KERN_INFO "sector = %d, cur_bytes = %d, cur_sectors = %d\n", (int)blk_rq_pos(req), blk_rq_cur_bytes(req), blk_rq_cur_sectors(req));
__blk_end_request_all(req, 0);
}
}
static struct block_device_operations blktest_fops = {
.owner = THIS_MODULE,
};
static int __init blktest_init(void)
{
blktest_major = register_blkdev(0, MODNAME);
printk(KERN_INFO "[blkdevtest]: major = %d\n", blktest_major);
if(blktest_major <= 0){
printk(KERN_WARNING "register_blkdev");
return blktest_major;
}
spin_lock_init(&blktest_lock);
blktest_queue = blk_init_queue(blktest_request, &blktest_lock);
if(!blktest_queue){
printk(KERN_WARNING "blk_init_queue");
unregister_blkdev(blktest_major, MODNAME);
return -ENOMEM;
}
blktest_gd = alloc_disk(4);
if(!blktest_gd){
printk(KERN_WARNING "alloc_disk\n");
blk_cleanup_queue(blktest_queue);
unregister_blkdev(blktest_major, MODNAME);
return -ENOMEM;
}
sprintf(blktest_gd->disk_name, "%s", MODNAME);
blktest_gd->queue = blktest_queue;
blktest_gd->major = blktest_major;
blktest_gd->first_minor = 0;
blktest_gd->fops = &blktest_fops;
set_capacity(blktest_gd, CAPACITY_SECTOR);
add_disk(blktest_gd);
printk(KERN_INFO "module loaded\n");
return 0;
}
static void __exit blktest_exit(void)
{
del_gendisk(blktest_gd);
put_disk(blktest_gd);
blk_cleanup_queue(blktest_queue);
unregister_blkdev(blktest_major, MODNAME);
printk(KERN_INFO "module unloaded");
}
module_init(blktest_init)
module_exit(blktest_exit)
MODULE_DESCRIPTION(MODNAME);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment