Chinaunix首页 | 论坛 | 博客
  • 博客访问: 52286
  • 博文数量: 17
  • 博客积分: 371
  • 博客等级: 一等列兵
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-09 11:18
文章分类

全部博文(17)

文章存档

2011年(17)

分类: LINUX

2011-04-15 22:44:31

注意:由于block_device在2.6.31后有一些变化,本分析建立在2.6.31以后的版本,笔者用的内核为2.6.32
 
 
一,上代码
 
  1. /*
  2.  * A sample, extra-simple block driver.
  3.  * Copyright (C) 2007, 2010 fengGuojin(fgjnew@163.com)
  4.  * Copyright 2003 Eklektix, Inc. Redistributable under the terms
  5.  * of the GNU GPL.
  6.  */

  7. #include <linux/module.h>
  8. #include <linux/moduleparam.h>
  9. #include <linux/init.h>

  10. #include <linux/kernel.h> /* printk() */
  11. #include <linux/fs.h> /* everything... */
  12. #include <linux/errno.h> /* error codes */
  13. #include <linux/types.h> /* size_t */
  14. #include <linux/vmalloc.h>
  15. #include <linux/genhd.h>
  16. #include <linux/blkdev.h>
  17. #include <linux/hdreg.h>

  18. MODULE_LICENSE("Dual BSD/GPL");

  19. static int major_num = 0;
  20. module_param(major_num, int, 0);
  21. static int hardsect_size = 512;
  22. module_param(hardsect_size, int, 0);
  23. static int nsectors = 1024; /* How big the drive is */
  24. module_param(nsectors, int, 0);

  25. /*
  26.  * We can tweak our hardware sector size, but the kernel talks to us
  27.  * in terms of small sectors, always.
  28.  */
  29. #define KERNEL_SECTOR_SIZE 512

  30. /*
  31.  * Our request queue.
  32.  */
  33. static struct request_queue *Queue;

  34. /*
  35.  * The internal representation of our device.
  36.  */
  37. static struct sbd_device {
  38.     unsigned long size;
  39.     spinlock_t lock;
  40.     u8 *data;
  41.     struct gendisk *gd;
  42. } Device;


  43. /*
  44.  * Handle an I/O request.
  45.  */
  46. static void sbd_transfer(struct sbd_device *dev, unsigned long sector,
  47.         unsigned long nsect, char *buffer, int write)
  48. {
  49.     unsigned long offset = sector*hardsect_size;
  50.     unsigned long nbytes = nsect*hardsect_size;
  51.     
  52.     if ((offset + nbytes) > dev->size) {
  53.     printk (KERN_NOTICE "sbd: Beyond-end write (%ld %ld)\n", offset, nbytes);
  54.     return;
  55.     }
  56.     if (write)
  57.     memcpy(dev->data + offset, buffer, nbytes);
  58.     else
  59.     memcpy(buffer, dev->data + offset, nbytes);
  60. }

  61. static void sbd_request(request_queue_t *q)
  62. {
  63.     struct request *req;

  64.     while ((req = elv_next_request(q)) != NULL) {
  65.     if (! blk_fs_request(req)) {
  66.      printk (KERN_NOTICE "Skip non-CMD request\n");
  67.      end_request(req, 0);
  68.      continue;
  69.     }
  70.     sbd_transfer(&Device, req->sector, req->current_nr_sectors,
  71.             req->buffer, rq_data_dir(req));
  72.     end_request(req, 1);
  73.     }
  74. }



  75. /*
  76.  * Ioctl.
  77.  */
  78. int sbd_ioctl (struct inode *inode, struct file *filp,
  79.                  unsigned int cmd, unsigned long arg)
  80. {
  81.     long size;
  82.     struct hd_geometry geo;

  83.     switch(cmd) {
  84.     /*
  85.      * The only command we need to interpret is HDIO_GETGEO, since
  86.      * we can't partition the drive otherwise. We have no real
  87.      * geometry, of course, so make something up.
  88.      */
  89.      case HDIO_GETGEO:
  90.         size = Device.size*(hardsect_size/KERNEL_SECTOR_SIZE);
  91.         geo.cylinders = (size & ~0x3f) >> 6;
  92.         geo.heads = 4;
  93.         geo.sectors = 16;
  94.         geo.start = 4;
  95.         if (copy_to_user((void *) arg, &geo, sizeof(geo)))
  96.             return -EFAULT;
  97.         return 0;
  98.     }

  99.     return -ENOTTY; /* unknown command */
  100. }




  101. /*
  102.  * The device operations structure.
  103.  */
  104. static struct block_device_operations sbd_ops = {
  105.     .owner = THIS_MODULE,
  106.     .ioctl     = sbd_ioctl
  107. };

  108. static int __init sbd_init(void)
  109. {
  110. /*
  111.  * Set up our internal device.
  112.  */
  113.     Device.size = nsectors*hardsect_size;
  114.     spin_lock_init(&Device.lock);
  115.     Device.data = vmalloc(Device.size);
  116.     if (Device.data == NULL)
  117.     return -ENOMEM;
  118. /*
  119.  * Get a request queue.
  120.  */
  121.     Queue = blk_init_queue(sbd_request, &Device.lock);
  122.     if (Queue == NULL)
  123.      goto out;
  124.     blk_queue_hardsect_size(Queue, hardsect_size);
  125. /*
  126.  * Get registered.
  127.  */
  128.     major_num = register_blkdev(major_num, "sbd");
  129.     if (major_num <= 0) {
  130.     printk(KERN_WARNING "sbd: unable to get major number\n");
  131.     goto out;
  132.     }
  133. /*
  134.  * And the gendisk structure.
  135.  */
  136.     Device.gd = alloc_disk(16);
  137.     if (! Device.gd)
  138.     goto out_unregister;
  139.     Device.gd->major = major_num;
  140.     Device.gd->first_minor = 0;
  141.     Device.gd->fops = &sbd_ops;
  142.     Device.gd->private_data = &Device;
  143.     strcpy (Device.gd->disk_name, "sbd0");
  144.     set_capacity(Device.gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE));
  145.     Device.gd->queue = Queue;
  146.     add_disk(Device.gd);

  147.     return 0;

  148.   out_unregister:
  149.     unregister_blkdev(major_num, "sbd");
  150.   out:
  151.     vfree(Device.data);
  152.     return -ENOMEM;
  153. }

  154. static void __exit sbd_exit(void)
  155. {
  156.     del_gendisk(Device.gd);
  157.     put_disk(Device.gd);
  158.     unregister_blkdev(major_num, "sbd");
  159.     blk_cleanup_queue(Queue);
  160.     vfree(Device.data);
  161. }
  162.     
  163. module_init(sbd_init);
  164. module_exit(sbd_exit);

二,start analyse

sbd_request()  

uses the blk_fetch_request()blk_rq_pos()blk_rq_cur_sectors() and __blk_end_request_cur() functions rather than

elv_next_request()req->sectorreq->current_nr_sectors and end_request() respectively. 

 

 

阅读(1793) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~