这样转发一个bio请求行不行?
大家好!根据论坛中一个兄弟的程序,我改写了下,实现了在内存中建立一个块设备驱动,现在想simp_blkdev_make_request函数中拷贝一个bio结构到/dev/sda2分区中(也就是将数据请求在/dev/sda2上也存储一份),下面程序不知道是否可行,我insmod后,老是死机。如果这样做不行,请问要实现这样一个功能,该如何做呢 谢谢!代码如下:#include <linux/string.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/module.h> //同kernel.h,最基本的内核模块头文件
#include <linux/kernel.h> //同module.h,最基本的内核模块头文件
#include <linux/sched.h> //这里包含了进行正确性检查的宏
#include <linux/fs.h> //文件系统所必需的头文件
#include <asm/uaccess.h> //这里包含了内核空间与用户空间进行数据交换时的函数宏
#include <asm/io.h> //I/O访问
#define SIMP_BLKDEV_DEVICEMAJOR COMPAQ_SMART2_MAJOR
#define SIMP_BLKDEV_DISKNAME "simp_blkdev"
#define SIMP_BLKDEV_BYTES (16*1024*1024)
#define SIMP_BLKDEV_MAXPARTITIONS (2)
static struct request_queue *simp_blkdev_queue;
static struct gendisk *simp_blkdev_disk;
unsigned char simp_blkdev_data;
static void simp_blkdev_do_request(struct request_queue *q);
static int simp_blkdev_make_request(struct request_queue *q,struct bio *bio);
struct block_device_operations simp_blkdev_fops = {
.owner = THIS_MODULE,
};
static int __init simp_blkdev_init(void)
{
int ret;
// simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, NULL);
simp_blkdev_queue = blk_alloc_queue(GFP_KERNEL);
if (!simp_blkdev_queue) {
ret = -ENOMEM;
goto err_init_queue;
}
blk_queue_make_request(simp_blkdev_queue,simp_blkdev_make_request);
simp_blkdev_disk = alloc_disk(SIMP_BLKDEV_MAXPARTITIONS);
if (!simp_blkdev_disk) {
ret = -ENOMEM;
goto err_alloc_disk;
}
strcpy(simp_blkdev_disk->disk_name,SIMP_BLKDEV_DISKNAME);
simp_blkdev_disk->major = SIMP_BLKDEV_DEVICEMAJOR;
simp_blkdev_disk->first_minor = 0;
simp_blkdev_disk->fops = &simp_blkdev_fops;
simp_blkdev_disk->queue = simp_blkdev_queue;
set_capacity(simp_blkdev_disk, SIMP_BLKDEV_BYTES>>9);
add_disk(simp_blkdev_disk);
return 0;
err_alloc_disk:
blk_cleanup_queue(simp_blkdev_queue);
err_init_queue:
return ret;
}
static void __exit simp_blkdev_exit(void)
{
del_gendisk(simp_blkdev_disk);
put_disk(simp_blkdev_disk);
blk_cleanup_queue(simp_blkdev_queue);
}
static int simp_blkdev_make_request(struct request_queue *q,struct bio *bio)
{
struct bio_vec *bvec;
int i;
void *dsk_mem;
if((bio->bi_sector<<9)+bio->bi_size>SIMP_BLKDEV_BYTES)
{
printk(KERN_ERR SIMP_BLKDEV_DISKNAME ": bad request: block=%llu, count=%u \n",(unsigned long long)bio->bi_sector, bio->bi_size);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
bio_endio(bio, 0, -EIO);
#else
bio_endio(bio, -EIO);
#endif
return 0;
}
dsk_mem = simp_blkdev_data + (bio->bi_sector << 9);
//下面这几行打算实现重定向功能
struct file *file;
file = filp_open("/dev/sda2",O_RDWR,0);
struct inode *i_node=file->f_dentry->d_inode;
if(i_node!=NULL){
struct block_device *bi_dev=i_node->i_bdev;
struct bio *mbio;
mbio = bio_clone(bio, GFP_NOIO);
//mbio->bi_sector = r1_bio->sector + conf->mirrors.rdev->data_offset;
mbio->bi_bdev = bi_dev;
generic_make_request(bio);
printk("open block_device success!\n");
} //重定向功能完成
//下面是正常的数据读写
bio_for_each_segment(bvec, bio, i) {
void *iovec_mem;
switch (bio_rw(bio)) {
case READ:
case READA:
iovec_mem = kmap(bvec->bv_page) + bvec->bv_offset;
memcpy(iovec_mem, dsk_mem, bvec->bv_len);
kunmap(bvec->bv_page);
break;
case WRITE:
iovec_mem = kmap(bvec->bv_page) + bvec->bv_offset;
memcpy(dsk_mem, iovec_mem, bvec->bv_len);
kunmap(bvec->bv_page);
break;
default:
printk(KERN_ERR SIMP_BLKDEV_DISKNAME": unknown value of bio_rw: %lu\n",bio_rw(bio));
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
bio_endio(bio, 0, -EIO);
#else
bio_endio(bio, -EIO);
#endif
return 0;
}
dsk_mem += bvec->bv_len;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
bio_endio(bio, bio->bi_size, 0);
#else
bio_endio(bio, 0);
#endif
return 0;
}
module_init(simp_blkdev_init);
module_exit(simp_blkdev_exit);
[ 本帖最后由 idclei 于 2009-11-25 09:36 编辑 ]
页:
[1]