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