I am implementing a virtual device driver for learning purpose,now i find it's performance is bad,i cann't get reason for it. I read the raid0 source code,you are the author,please you help me.
disk read /dev/vbd(virtual)
[root@server_1 vbd_test_7]# dd if=/dev/vbd0 of=/dev/zero count=1000000 bs=1k
1000000+0 records in
1000000+0 records out
1024000000 bytes (1.0 GB) copied, 15.8438 seconds, 64.6 MB/s
1000000+0 records in
1000000+0 records out
1024000000 bytes (1.0 GB) copied, 15.8438 seconds, 64.6 MB/s
[root@server_1 vbd_test_7]# dd if=/dev/sdb of=/dev/zero count=1000000 bs=1k
1000000+0 records in
1000000+0 records out
1024000000 bytes (1.0 GB) copied, 6.18553 seconds, 166 MB/s
1000000+0 records in
1000000+0 records out
1024000000 bytes (1.0 GB) copied, 6.18553 seconds, 166 MB/s
what make the performance difference?
code:
MODULE_LICENSE("Dual BSD/GPL");
static int vbd_major = 0;
module_param(vbd_major, int, 0);
static int hardsect_size = 512;
module_param(hardsect_size, int, 0);
static int nsectors = 1024*1024*2; /* How big the drive is */
module_param(nsectors, int, 0);
module_param(vbd_major, int, 0);
static int hardsect_size = 512;
module_param(hardsect_size, int, 0);
static int nsectors = 1024*1024*2; /* How big the drive is */
module_param(nsectors, int, 0);
#define WINDOWS_ROBOT_NUM 4
#define SNOPSHOT_EACH_WINDOWS_ROBOT 4
static int ndevices = 1;
module_param(ndevices, int, 0);
#define SNOPSHOT_EACH_WINDOWS_ROBOT 4
static int ndevices = 1;
module_param(ndevices, int, 0);
/*
* We can tweak our hardware sector size, but the kernel talks to us
* in terms of small sectors, always.
*/
#define KERNEL_SECTOR_SIZE 512
#define VBD_MINORS 1
* We can tweak our hardware sector size, but the kernel talks to us
* in terms of small sectors, always.
*/
#define KERNEL_SECTOR_SIZE 512
#define VBD_MINORS 1
/*
* The internal representation of our device.
*/
struct vbd_dev
{
short users; /* How many users */
short media_change; /* Flag a media change? */
spinlock_t lock; /* For mutual exclusion */
struct request_queue *queue; /* The device request queue */
struct gendisk *gd; /* The gendisk structure */
};
* The internal representation of our device.
*/
struct vbd_dev
{
short users; /* How many users */
short media_change; /* Flag a media change? */
spinlock_t lock; /* For mutual exclusion */
struct request_queue *queue; /* The device request queue */
struct gendisk *gd; /* The gendisk structure */
};
typedef struct vbd_dev vbd_dev_t ;
static vbd_dev_t *Devices = NULL;
static vbd_dev_t *Devices = NULL;
static struct block_device *bdev = NULL;
static int vbd_endio(struct bio* bio,unsigned int done,int error)
{
struct bio* ori_bio;
ori_bio = bio->bi_private;
//printk(KERN_INFO"clone_endio:%d\n",ori_bio->bi_size);
bio_endio(ori_bio,ori_bio->bi_size,error);
//printk(KERN_INFO"clone_endio\n");
bio_put(bio);
bio_endio(ori_bio,ori_bio->bi_size,error);
//printk(KERN_INFO"clone_endio\n");
bio_put(bio);
return 0;
}
}
static int vbd_make_request(request_queue_t *q, struct bio *bio)
{
//struct bio_vec *bvec;
struct bio* newbio;
//sector_t sector = bio->bi_sector;
//sector_t total_sector_num = 0;
//int i;
#if 0
printk("********************start*************************\n");
if(bio->bi_sector%8!=0)printk("**************what we need happen*********\n");
printk("bio->bi_sector=%d\n",bio->bi_sector);
printk("bio->bi_vcnt=%d\n",bio->bi_vcnt);
printk("bio->bi_idx=%d\n",bio->bi_idx);
printk("bio->bi_max_vecs=%d\n",bio->bi_max_vecs);
printk("bio->bi_size=%d secotrs\n",(bio->bi_size)>>9);
for(i=0;i<bio->bi_vcnt;i++)
{
total_sector_num+=(bio->bi_io_vec[i].bv_len)>>9;
printk("total sector num =%d\n",total_sector_num);
}
printk("********************finish*************************\n");
#endif
printk("********************start*************************\n");
if(bio->bi_sector%8!=0)printk("**************what we need happen*********\n");
printk("bio->bi_sector=%d\n",bio->bi_sector);
printk("bio->bi_vcnt=%d\n",bio->bi_vcnt);
printk("bio->bi_idx=%d\n",bio->bi_idx);
printk("bio->bi_max_vecs=%d\n",bio->bi_max_vecs);
printk("bio->bi_size=%d secotrs\n",(bio->bi_size)>>9);
for(i=0;i<bio->bi_vcnt;i++)
{
total_sector_num+=(bio->bi_io_vec[i].bv_len)>>9;
printk("total sector num =%d\n",total_sector_num);
}
printk("********************finish*************************\n");
#endif
newbio = bio_clone(bio,GFP_NOIO);
newbio->bi_bdev = bdev;
newbio->bi_end_io = vbd_endio;
newbio->bi_private = bio;
newbio->bi_flags &= ~(1 << BIO_SEG_VALID);
printk(KERN_INFO"newbio->bi_flags=%d\n",newbio->bi_flags);
printk(KERN_INFO"bio->bi_flags=%d\n",bio->bi_flags);
generic_make_request(newbio);
printk(KERN_INFO"newbio->bi_flags=%d\n",newbio->bi_flags);
printk(KERN_INFO"bio->bi_flags=%d\n",bio->bi_flags);
generic_make_request(newbio);
return 0;
}
}
/*
* Open and close.
*/
static int vbd_open(struct inode *inode, struct file *filp)
{
// static int i=10;
vbd_dev_t *vbd_dev = inode->i_bdev->bd_disk->private_data;
dev_t testdev;
{
// static int i=10;
vbd_dev_t *vbd_dev = inode->i_bdev->bd_disk->private_data;
dev_t testdev;
filp_open("/dev/sdb",O_RDWR,0);
printk("********************start*************************\n");
testdev = MKDEV(8,16);
bdev = bdget(testdev);
if(bdev==NULL)
{
printk(KERN_INFO"notice:null device**********\n");
return 0;
}
filp->private_data = vbd_dev;
spin_lock(&vbd_dev->lock);
if (! vbd_dev->users)
{
check_disk_change(inode->i_bdev);
}
vbd_dev->users++;
spin_unlock(&vbd_dev->lock);
return 0;
}
static int vbd_release(struct inode *inode, struct file *filp)
{
struct vbd_dev *dev = inode->i_bdev->bd_disk->private_data;
spin_lock(&dev->lock);
dev->users--;
spin_unlock(&dev->lock);
dev->users--;
spin_unlock(&dev->lock);
return 0;
}
}
/*
* Look for a (simulated) media change.
*/
int vbd_media_changed(struct gendisk *gd)
{
struct vbd_dev *dev = gd->private_data;
return dev->media_change;
}
* Look for a (simulated) media change.
*/
int vbd_media_changed(struct gendisk *gd)
{
struct vbd_dev *dev = gd->private_data;
return dev->media_change;
}
/*
* Revalidate. WE DO NOT TAKE THE LOCK HERE, for fear of deadlocking
* with open. That needs to be reevaluated.
*/
int vbd_revalidate(struct gendisk *gd)
{
struct vbd_dev *dev = gd->private_data;
if (dev->media_change)
{
dev->media_change = 0;
}
return 0;
}
* Revalidate. WE DO NOT TAKE THE LOCK HERE, for fear of deadlocking
* with open. That needs to be reevaluated.
*/
int vbd_revalidate(struct gendisk *gd)
{
struct vbd_dev *dev = gd->private_data;
if (dev->media_change)
{
dev->media_change = 0;
}
return 0;
}
/*
* The ioctl() implementation
*/
* The ioctl() implementation
*/
int vbd_ioctl (struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
unsigned int cmd, unsigned long arg)
{
struct hd_geometry geo;
//struct vbd_dev *dev = filp->private_data;
//static int i=0;
switch(cmd) {
case HDIO_GETGEO:
/*
* Get geometry: since we are a virtual device, we have to make
* up something plausible. So we claim 16 sectors, four heads,
* and calculate the corresponding number of cylinders. We set the
* start of data at sector four.
*/
//struct vbd_dev *dev = filp->private_data;
//static int i=0;
switch(cmd) {
case HDIO_GETGEO:
/*
* Get geometry: since we are a virtual device, we have to make
* up something plausible. So we claim 16 sectors, four heads,
* and calculate the corresponding number of cylinders. We set the
* start of data at sector four.
*/
geo.heads = 4;
geo.sectors = 16;
geo.start = 4;
if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))
return -EFAULT;
return 0;
}
printk(KERN_INFO"ioctl:%d\n",cmd);
return -ENOTTY; /* unknown command */
}
geo.sectors = 16;
geo.start = 4;
if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))
return -EFAULT;
return 0;
}
printk(KERN_INFO"ioctl:%d\n",cmd);
return -ENOTTY; /* unknown command */
}
/*
* The device operations structure.
*/
static struct block_device_operations vbd_ops = {
.owner = THIS_MODULE,
.open = vbd_open,
.release = vbd_release,
.media_changed = vbd_media_changed,
.revalidate_disk = vbd_revalidate,
.ioctl = vbd_ioctl
};
* The device operations structure.
*/
static struct block_device_operations vbd_ops = {
.owner = THIS_MODULE,
.open = vbd_open,
.release = vbd_release,
.media_changed = vbd_media_changed,
.revalidate_disk = vbd_revalidate,
.ioctl = vbd_ioctl
};
/*
* Set up our internal device.
*/
static void setup_device(struct vbd_dev *dev, int which)
{
/*
* Get some memory.
*/
memset (dev, 0, sizeof (struct vbd_dev));
spin_lock_init(&dev->lock);
dev->queue = blk_alloc_queue(GFP_KERNEL);
if (dev->queue == NULL)
return;
if (dev->queue == NULL)
return;
/**/
blk_queue_make_request(dev->queue, vbd_make_request);
blk_queue_hardsect_size(dev->queue, hardsect_size);
dev->queue->queuedata = dev;
blk_queue_make_request(dev->queue, vbd_make_request);
blk_queue_hardsect_size(dev->queue, hardsect_size);
dev->queue->queuedata = dev;
/*
* And the gendisk structure.we just want 1 minor here
*/
dev->gd = alloc_disk(VBD_MINORS);
if (! dev->gd)
{
printk (KERN_NOTICE "alloc_disk failure\n");
return;
}
* And the gendisk structure.we just want 1 minor here
*/
dev->gd = alloc_disk(VBD_MINORS);
if (! dev->gd)
{
printk (KERN_NOTICE "alloc_disk failure\n");
return;
}
/*
* Set some other parameters
*/
dev->gd->major = vbd_major;
dev->gd->first_minor = which*VBD_MINORS;
dev->gd->fops = &vbd_ops;
dev->gd->queue = dev->queue;
dev->gd->private_data = dev;
snprintf (dev->gd->disk_name, 32, "vbd%d", which );
set_capacity(dev->gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE));
add_disk(dev->gd);
return;
}
* Set some other parameters
*/
dev->gd->major = vbd_major;
dev->gd->first_minor = which*VBD_MINORS;
dev->gd->fops = &vbd_ops;
dev->gd->queue = dev->queue;
dev->gd->private_data = dev;
snprintf (dev->gd->disk_name, 32, "vbd%d", which );
set_capacity(dev->gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE));
add_disk(dev->gd);
return;
}
static int __init vbd_init(void)
{
int i;
/*
* Get registered.
*/
vbd_major = register_blkdev(vbd_major, "vbd");
if (vbd_major <= 0) {
printk(KERN_WARNING "vbd: unable to get major number\n");
return -EBUSY;
}
/*
* Allocate the device array, and initialize each one.
*/
Devices = kmalloc(ndevices*sizeof (struct vbd_dev), GFP_KERNEL);
if (Devices == NULL)
{
goto out_unregister;
}
for (i = 0; i < ndevices; i++)
{
setup_device(Devices + i, i);
}
return 0;
{
int i;
/*
* Get registered.
*/
vbd_major = register_blkdev(vbd_major, "vbd");
if (vbd_major <= 0) {
printk(KERN_WARNING "vbd: unable to get major number\n");
return -EBUSY;
}
/*
* Allocate the device array, and initialize each one.
*/
Devices = kmalloc(ndevices*sizeof (struct vbd_dev), GFP_KERNEL);
if (Devices == NULL)
{
goto out_unregister;
}
for (i = 0; i < ndevices; i++)
{
setup_device(Devices + i, i);
}
return 0;
out_unregister:
unregister_blkdev(vbd_major, "vbd");
return -ENOMEM;
}
unregister_blkdev(vbd_major, "vbd");
return -ENOMEM;
}
static void vbd_exit(void)
{
int i;
{
int i;
for (i = 0; i < ndevices; i++)
{
struct vbd_dev *dev = Devices + i;
if (dev->gd)
{
del_gendisk(dev->gd);
put_disk(dev->gd);
}
if (dev->queue)
{
blk_cleanup_queue(dev->queue);
}
}
unregister_blkdev(vbd_major, "vbd");
kfree(Devices);
}
module_init(vbd_init);
module_exit(vbd_exit
{
struct vbd_dev *dev = Devices + i;
if (dev->gd)
{
del_gendisk(dev->gd);
put_disk(dev->gd);
}
if (dev->queue)
{
blk_cleanup_queue(dev->queue);
}
}
unregister_blkdev(vbd_major, "vbd");
kfree(Devices);
}
module_init(vbd_init);
module_exit(vbd_exit
@yahoo.cn 新域名、无限量,快来抢注!
-- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel