Last active
December 21, 2015 06:38
-
-
Save umedaikiti/6265252 to your computer and use it in GitHub Desktop.
とりあえず動作するlinuxのブロックデバイスドライバ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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