免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3950 | 回复: 4
打印 上一主题 下一主题

求助:内存块设备分区提示无法读取。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-08-03 09:57 |只看该作者 |倒序浏览
本帖最后由 c04n05 于 2011-08-03 12:09 编辑

http://bbs.chinaunix.net/thread-2017377-2-1.html  看的这个帖子,试验了下代码。如下:
  1. #include <linux/kernel.h>
  2. #include <linux/init.h>
  3. #include <linux/module.h>
  4. #include <linux/fs.h>
  5. #include <linux/blkdev.h>
  6. #include <linux/genhd.h>
  7. #include <linux/version.h>

  8. #define SIMP_BLKDEV_DISKNAME           "simp_blkdev"
  9. #define SIMP_BLKDEV_DEVICEMAJOR        COMPAQ_SMART2_MAJOR
  10. #define SIMP_BLKDEV_BYTES              (16*1024*1024)//16MB
  11. #define SIMP_BLKDEV_MAXPARTITIONS      (64)

  12. MODULE_LICENSE("GPL");

  13. static struct gendisk *simp_blkdev_disk;
  14. static struct request_queue *simp_blkdev_queue;

  15. unsigned char simp_blkdev_data[SIMP_BLKDEV_BYTES];

  16. struct block_device_operations simp_blkdev_fops = {
  17.     .owner = THIS_MODULE,
  18. };

  19. static int simp_blkdev_make_request(struct request_queue *q, struct bio *bio)
  20. {
  21.     struct bio_vec *bvec;
  22.     int i;
  23.     void *dsk_mem;

  24.     if ((bio->bi_sector << 9) + bio->bi_size > SIMP_BLKDEV_BYTES)
  25.     {
  26.         printk(KERN_ERR SIMP_BLKDEV_DISKNAME ":bad request:block=%llu, count=%u\n", (unsigned long long)bio->bi_sector, bio->bi_size);
  27.         
  28. #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
  29.         bio_endio(bio, 0, -EIO);
  30. #else
  31.         bio_endio(bio, -EIO);
  32. #endif
  33.         return 0;
  34.     }

  35.     dsk_mem = simp_blkdev_data + (bio->bi_sector << 9);
  36.    
  37.     bio_for_each_segment(bvec, bio, i)
  38.     {
  39.         void *iovec_mem;
  40.         
  41.         switch (bio_rw(bio))
  42.         {
  43.         case READ:
  44.         case READA:
  45.             iovec_mem = kmap(bvec->bv_page) + bvec->bv_offset;
  46.             memcpy(iovec_mem, dsk_mem, bvec->bv_len);
  47.             kunmap(bvec->bv_page);
  48.             break;
  49.         
  50.         case WRITE:
  51.             iovec_mem = kmap(bvec->bv_page) + bvec->bv_offset;
  52.             memcpy(dsk_mem, iovec_mem, bvec->bv_len);
  53.             kunmap(bvec->bv_page);

  54.         default:
  55.             printk(KERN_ERR SIMP_BLKDEV_DISKNAME ":unknown value of bio_rw:%lu\n", bio_rw(bio));
  56. #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
  57.             bio_endio(bio, 0, -EIO);
  58. #else
  59.             bio_endio(bio, -EIO);
  60. #endif
  61.             return 0;
  62.         }
  63.         dsk_mem += bvec->bv_len;
  64.     }
  65. #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
  66.     bio_endio(bio, 0, -EIO);
  67. #else
  68.     bio_endio(bio, -EIO);
  69. #endif
  70.     return 0;
  71. }

  72. static int __init simp_blkdev_init(void)
  73. {
  74.     int ret = 0;

  75.     simp_blkdev_disk = alloc_disk(SIMP_BLKDEV_MAXPARTITIONS);
  76.     if (!simp_blkdev_disk)
  77.     {
  78.         ret = -ENOMEM;
  79.         goto err_alloc_disk;
  80.     }

  81.     simp_blkdev_queue = blk_alloc_queue(GFP_KERNEL);
  82.     if (!simp_blkdev_queue)
  83.     {
  84.         ret = -ENOMEM;
  85.         goto err_init_queue;
  86.     }   

  87.     blk_queue_make_request(simp_blkdev_queue, simp_blkdev_make_request);

  88.     strcpy(simp_blkdev_disk->disk_name, SIMP_BLKDEV_DISKNAME);
  89.     simp_blkdev_disk->major = SIMP_BLKDEV_DEVICEMAJOR;
  90.     simp_blkdev_disk->first_minor = 0;
  91.     simp_blkdev_disk->fops = &simp_blkdev_fops;
  92.     simp_blkdev_disk->queue = simp_blkdev_queue;
  93.     set_capacity(simp_blkdev_disk, SIMP_BLKDEV_BYTES>>9/*equals SIMP_BLKDEV_BYTES/512*/);

  94.     add_disk(simp_blkdev_disk);
  95.     return 0;

  96. err_alloc_disk:
  97.     return ret;

  98. err_init_queue:
  99.     put_disk(simp_blkdev_disk);
  100.     return ret;
  101.    
  102. }

  103. static void __exit simp_blkdev_exit(void)
  104. {
  105.     put_disk(simp_blkdev_disk);
  106.     blk_cleanup_queue(simp_blkdev_queue);
  107.     del_gendisk(simp_blkdev_disk);

  108. }

  109. module_init(simp_blkdev_init);
  110. module_exit(simp_blkdev_exit);
复制代码
编译完成之后,insmod。发现有/dev/simp_blkdev了
接下来使用fdisk
[root@TM-0166 blockDeviceTest]# fdisk /dev/simp_blkdev

Unable to read /dev/simp_blkdev
[root@TM-0166 blockDeviceTest]# tail -n 30 /var/log/messages
Aug  3 09:20:26 TM-0166 gdm-simple-slave[2497]: DEBUG: Writing wtmp session record to /var/log/wtmp
Aug  3 09:20:26 TM-0166 gdm-simple-slave[2497]: DEBUG: Adding new utmp record
Aug  3 09:20:26 TM-0166 gdm-simple-slave[2497]: DEBUG: GdmSimpleSlave: session started 2649
Aug  3 09:20:29 TM-0166 pulseaudio[2703]: main.c: This program is not intended to be run as root (unless --system is specified).
Aug  3 09:20:29 TM-0166 pulseaudio[2703]: pid.c: Stale PID file, overwriting.
Aug  3 09:20:29 TM-0166 pulseaudio[2703]: alsa-util.c: Device front:0 doesn't support 44100 Hz, changed to 44099 Hz.
Aug  3 09:20:32 TM-0166 gconfd (root-2617): Resolved address "xml:readwrite:/root/.gconf" to a writable configuration source at position 0
Aug  3 09:20:33 TM-0166 pulseaudio[2703]: module-x11-xsmp.c: X11 session manager not running.
Aug  3 09:20:33 TM-0166 pulseaudio[2703]: module.c: Failed to load  module "module-x11-xsmp" (argument: "": initialization failed.
Aug  3 09:20:38 TM-0166 gnome-keyring-daemon[2648]: adding removable location: volume_label_VMware_Tools at /media/VMware Tools
Aug  3 09:20:38 TM-0166 hald: mounted /dev/sr0 on behalf of uid 0
Aug  3 09:21:44 TM-0166 kernel:  simp_blkdev:<3>Buffer I/O error on device simp_blkdev, logical block 0
Aug  3 09:21:44 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 0
Aug  3 09:21:44 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 0
Aug  3 09:21:44 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 0
Aug  3 09:21:44 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 0
Aug  3 09:21:44 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 0
Aug  3 09:21:44 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 0
Aug  3 09:21:44 TM-0166 kernel: Dev simp_blkdev: unable to read RDB block 0
Aug  3 09:21:44 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 0
Aug  3 09:21:44 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 0
Aug  3 09:21:44 TM-0166 kernel:  unable to read partition table
Aug  3 09:22:23 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 0
Aug  3 09:22:23 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 1
Aug  3 09:22:23 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 2
Aug  3 09:22:23 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 3
Aug  3 09:22:23 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 0
Aug  3 09:22:23 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 4095
Aug  3 09:22:23 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 4095
Aug  3 09:22:23 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 0

内核:[root@TM-0166 blockDeviceTest]# uname -r
2.6.25-14.fc9.i686
gcc version 4.3.0 20080428 (Red Hat 4.3.0- (GCC)

论坛徽章:
0
2 [报告]
发表于 2011-08-03 13:01 |只看该作者
bio_endio(bio, -EIO);
返回-EIO,读失败

论坛徽章:
0
3 [报告]
发表于 2011-08-03 14:34 |只看该作者
本帖最后由 c04n05 于 2011-08-03 14:39 编辑

回复 2# fei1700
[root@TM-0166 blockDeviceTest]# cat /proc/buddyinfo
Node 0, zone      DMA     22      9     10      7     11      9      5      2      2      0      0
Node 0, zone   Normal     56     50     30     74     24     15      2     11     14     12      0
[root@TM-0166 blockDeviceTest]#

感谢您的指点。
根据后文来看。应该是我这机器没有高端内存所致?
如果是这样的话,类似这段代码的
            iovec_mem = kmap(bvec->bv_page) + bvec->bv_offset;
            memcpy(iovec_mem, dsk_mem, bvec->bv_len);
            kunmap(bvec->bv_page);
又应该变成什么样子呢?

论坛徽章:
0
4 [报告]
发表于 2011-08-03 14:47 |只看该作者
Aug  3 09:21:44 TM-0166 kernel: Buffer I/O error on device simp_blkdev, logical block 0
Aug  3 09:21:44 TM-0166 kernel:  unable to read partition table

如果你要是指这2个错误的话,那就不是高端内存的问题吧

Buffer I/O error是因为bio_endio(bio, -EIO); 传进去的是-EIO,原文后面都有改成bio_endio(bio, 0);这个返回0的,才不会返回Buffer I/O error
unable to read partition table是没读到分区表,如果内容不是有效的分区表都会这么现实,你只是memcpy一段废数据,肯定有这个错误,但如果块设备本身不带分区表,这个错误也应该可以忽略

论坛徽章:
0
5 [报告]
发表于 2011-08-03 15:19 |只看该作者
回复 4# fei1700
看来就是这个错误了。我把这个函数里面的-EIO改成0 之后就ok了。。。
不过为啥我的机器里面没有那个高端内存呢?


还有另外一个问题,一旦我卸载这个模块。就提示Segmentation fault 然后系统挂掉了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP