Chinaunix首页 | 论坛 | 博客
  • 博客访问: 805912
  • 博文数量: 127
  • 博客积分: 2669
  • 博客等级: 少校
  • 技术积分: 1680
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-23 11:39
文章分类

全部博文(127)

文章存档

2014年(5)

2013年(19)

2012年(25)

2011年(9)

2010年(25)

2009年(44)

分类: LINUX

2013-08-04 20:11:11

从代码中可以看出,函数会对传入的scsi command中的prot_sdb包含的scatterlist中每个page中的数据块调用kmap_atomic映射到线性地址,然后生成校验码,生成校验码的具体算法由scsi_debug_guard指定,如果设置为1,则直接调用了lib下的ip_compute_csum生成校验,否则调用SBC标准中规定的CRC计算方法,具体可见SBC标准第4.22.4.2小节。

返回resp_write函数:

       write_lock_irqsave(&atomic_rw, iflags);

       ret = do_device_access(SCpnt, devip, lba, num, 1);

       if (scsi_debug_unmap_granularity)

              map_region(lba, num);

       write_unlock_irqrestore(&atomic_rw, iflags);

       if (-1 == ret)

              return (DID_ERROR << 16);

       else if ((ret < (num * scsi_debug_sector_size)) &&

               (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))

              printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "

                     " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret);

 

       return 0;

}

do_device_access函数定义如下,从中可以看出,函数实现相当简洁,根据是否为write调用fetch_to_dev_buffer 或者fill_from_dev_buffer,即如果为写,将数据拷贝入虚拟出来的设备的内存中,否则从设备的内存中读取数据。

static int do_device_access(struct scsi_cmnd *scmd,

                         struct sdebug_dev_info *devi,

                         unsigned long long lba, unsigned int num, int write)

{

       int ret;

       unsigned long long block, rest = 0;

       int (*func)(struct scsi_cmnd *, unsigned char *, int);

 

       func = write ? fetch_to_dev_buffer : fill_from_dev_buffer;

 

       block = do_div(lba, sdebug_store_sectors);

       if (block + num > sdebug_store_sectors)

              rest = block + num - sdebug_store_sectors;

 

       ret = func(scmd, fake_storep + (block * scsi_debug_sector_size),

                 (num - rest) * scsi_debug_sector_size);

       if (!ret && rest)

              ret = func(scmd, fake_storep, rest * scsi_debug_sector_size);

 

       return ret;

}

在完成resp_write之后,针对之前fault injection中设置的标志位返回相关的错误码,例如ABORTED_COMMANDILLEGAL_REQUEST,否则正常返回。

总结

到此可以看出scsi_debug是在完全参照着SCSI相关标准实现的,对于其他真实的物理设备的驱动也同样需要实现此处scsi_debug实现的各种填表工作,在此之上实现自己的业务逻辑。SCSI标准在主机和外设之间定义了一个标准的接口,外设只需做到scsi_debug的工作,就不需要为设备的兼容性和移植性担忧,这也正是各大厂商始终推动着SCSI标准不断发展的原因。

参考资料

  1. Information Storage and Management. EMC.

  2. Guide to the implementation of SCSI in Linux 2.6.X kernel.

  3. SCSI标准(SAMSPCSBC)

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