当前位置:嗨网首页>书籍在线阅读

18-vmem_disk IO请求处理

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

13.7.4 vmem_disk I/O请求处理

在vmem_disk驱动中,通过模块参数request_mode的方式来支持3种不同的请求处理模式以加深读者对它们的理解,代码清单13.19列出了vmem_disk驱动的请求处理代码。

代码清单13.19 vmem.disk设备驱动的请求处理函数

1 /*

2 * 处理一个I/O request.

3 */

4 static void vmem_disk_transfer(struct vmem_disk_dev *dev, unsigned long sector,

5 unsigned long nsect, char *buffer, int write)

6 {

7 unsigned long offset = sector*KERNEL_SECTOR_SIZE;

8 unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;

9

10 if ((offset + nbytes) > dev->size) {

11 printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);

12 return;

13 }

14 if (write)

15 memcpy(dev->data + offset, buffer, nbytes);

16 else

17 memcpy(buffer, dev->data + offset, nbytes);

18 }

19

20 /*

21 * request函数的简单形式

22 */

23 static void vmem_disk_request(struct request_queue *q)

24 {

25 struct request *req;

26

27 while ((req = elv_next_request(q)) != NULL) {

28 struct vmem_disk_dev *dev = req->rq_disk->private_data;

29 if (! blk_fs_request(req)) {

30 printk (KERN_NOTICE "Skip non-fs request\n");

31 end_request(req, 0);

32 continue;

33 }

34

35 vmem_disk_transfer(dev, req->sector, req->current_nr_sectors,

36 req->buffer, rq_data_dir(req));

37

38 end_request(req, 1);

39 }

40 }

41

42

43 /*

44 * 传输一个单独的BIO

45 */

46 static int vmem_disk_xfer_bio(struct vmem_disk_dev dev, struct bio bio)

47 {

48 int i;

49 struct bio_vec *bvec;

50 sector_t sector = bio->bi_sector;

51

52 / Do each segment independently. /

53 bio_for_each_segment(bvec, bio, i) {

54 char *buffer = __bio_kmap_atomic(bio, i, KM_USER0);

55 vmem_disk_transfer(dev, sector, bio_cur_sectors(bio),

56 buffer, bio_data_dir(bio) == WRITE);

57 sector += bio_cur_sectors(bio);

58 __bio_kunmap_atomic(bio, KM_USER0);

59 }

60 return 0; / Always "succeed" /

61 }

62

63 /*

64 * 传输一个完整的request

65 */

66 static int vmem_disk_xfer_request(struct vmem_disk_dev dev, struct request req)

67 {

68

69 struct req_iterator iter;

70 int nsect = 0;

71 struct bio_vec *bvec;

72

73 rq_for_each_segment(bvec, req, iter) {

74 char *buffer = __bio_kmap_atomic(iter.bio, iter.i, KM_USER0);

75 sector_t sector = iter.bio->bi_sector;

76 vmem_disk_transfer(dev, sector, bio_cur_sectors(iter.bio),

77 buffer, bio_data_dir(iter.bio) == WRITE);

78 sector += bio_cur_sectors(iter.bio);

79 __bio_kunmap_atomic(iter.bio, KM_USER0);

80 nsect += iter.bio->bi_size/KERNEL_SECTOR_SIZE;

81 }

82 return nsect;

83 }

84

85

86 /*

87 * 更强大的request处理

88 */

89 static void vmem_disk_full_request(struct request_queue *q)

90 {

91 struct request *req;

92 int sectors_xferred;

93 struct vmem_disk_dev *dev = q->queuedata;

94

95 while ((req = elv_next_request(q)) != NULL) {

96 if (! blk_fs_request(req)) {

97 printk (KERN_NOTICE "Skip non-fs request\n");

98 end_request(req, 0);

99 continue;

100 }

101 sectors_xferred = vmem_disk_xfer_request(dev, req);

102 end_request (req, 1);

103 }

104 }

105

106 /*

107 * "制造请求"方式

108 */

109 static int vmem_disk_make_request(struct request_queue q, struct bio bio)

110 {

111 struct vmem_disk_dev *dev = q->queuedata;

112 int status;

113

114 status = vmem_disk_xfer_bio(dev, bio);

115 bio_endio(bio, status);

116 return 0;

117 }

上述代码中的1~40行、43~104行、106~117行分别对应了RM_SIMPLE、RM_FULL、RM_NOQUEUE这3种不同的请求处理方式。

vmem_disk的驱动位于VirtualBox虚拟机映像的/home/lihacker/develop/svn/ldd6410-read-only/ training/kernel/drivers/ vmem_disk下面,已经有编写好的Makefile,直接在其中运行make命令即可得到vmem_disk.ko模块。