Scsi - Index of
Scsi - Index of Scsi - Index of
具体到usb storage,我们不管信号量和锁在Linux 中是怎么实现的,它们之间是否有区别对我们来说也 无所谓,事实上,usb-storage 中使用的都是锁,即便是信号量,也是把它当成锁来使用,可曾记得我们当初 把 信号量的初始化为1 了?当信号量初始化为1,那么对我们来说,它就相当于退化为一把锁了.而锁,只有两种 状态,上锁和解锁. 此前我们见过很多次两组函数,但我们一直绝口不提. 她们就是scsi_lock()和scsi_unlock(),以及down(&us->dev_semaphore)和 up(&us->dev_semaphore). 先来看第一组.她们是我们自己定义的宏.来自drivers/usb/storage/usb.h. 174 /* The scsi_lock() and scsi_unlock() macros protect the sm_state and the 175 * single queue element srb for write access */ 176 #define scsi_unlock(host) spin_unlock_irq(host->host_lock) 177 #define scsi_lock(host) spin_lock_irq(host->host_lock) 显然,这两个函数就像牛郎织女一样,是一对.而她们的作用,就是利用自旋锁来保护资源,这把锁就是 struct Scsi_Host 的一个成员spinlock_t *host_lock.那么在什么情况下需要使用这两个自旋锁函数来 保护资源呢? 当你要写us->srb 的时候,(不是写us->srb 的元素,而是写us->srb,比如令us->srb=NULL),这种时 候,你需要使用这把自旋锁.另一种情况是,当你调用scsi mid layer(scsi 中层)的函数时,有时候这些函数 要求调用者拥有这把锁,即host_lock. 搜索一下,发现一共有7 处使用了scsi_lock. 我们列举一些来. 第一处,drivers/usb/storage/usb.c:usb_stor_release_resources()函数中, 839 scsi_lock(us->host); 840 us->srb = NULL; 841 scsi_unlock(us->host); 199 这个不用解释了吧,赤裸裸的写us->srb,自然要用scsi_lock/scsi_unlock. 第二处,drivers/usb/storage/transport.c:usb_stor_reset_common()函数中, 1121 scsi_lock(us->host); 1122 usb_stor_report_device_reset(us); 1123 set_bit(US_FLIDX_RESETTING, &us->flags); 1124 clear_bit(US_FLIDX_ABORTING, &us->flags); 1125 scsi_unlock(us->host); 这就是第二种情况,因为这里调用了usb_stor_report_device_reset(),这个函数来自 drivers/usb/storage/scsiglue.c,也是我们定义的, 308 /* Report a driver-initiated device reset to the SCSI layer. 309 * Calling this for a SCSI-initiated reset is unnecessary but harmless. 310 * The caller must own the SCSI host lock. */ 311 void usb_stor_report_device_reset(struct us_data *us) 312 { 313 int i; 314 315 scsi_report_device_reset(us->host, 0, 0); 316 if (us->flags & US_FL_SCM_MULT_TARG) {
317 for (i = 1; i < us->host->max_id; ++i) 318 scsi_report_device_reset(us->host, 0, i); 319 } 320 } 注意到,她里边调用了scsi_report_device_reset(),后者来自drivers/scsi/scsi_error.c,这正是scsi mid layer 定义的函数,这个函数的注释说得很清楚,调用她时必须要拥有host lock. 有人说还有第三种情况,drivers/usb/storage/usb.c,usb_stor_control_thread()函数中, 318 /* lock access to the state */ 319 scsi_lock(host); 320 321 /* has the command timed out *already* ? */ 322 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { 323 us->srb->result = DID_ABORT
- Page 145 and 146: 到北京,每每只有在夜深人
- Page 147 and 148: 580 /* 581 * If we have a failure,
- Page 149 and 150: 666 memcpy(srb->cmnd, old_cmnd, MAX
- Page 151 and 152: 950 struct bulk_cb_wrap *bcb = (str
- Page 153 and 154: 1034 /* get the status again */ 103
- Page 155 and 156: 426 /* store the actual length of t
- Page 157 and 158: 后她会给host 返回一个CSW.CB
- Page 159 and 160: 296 } 297 298 US_DEBUGP("-- transfe
- Page 161 and 162: 491 * scatter-gather or not, and ac
- Page 163 and 164: 迷雾重重的 Bulk 传输(五) us
- Page 165 and 166: 然后把她赋给了result.而us->
- Page 167 and 168: 而bcs->Status,标志命令执行
- Page 169 and 170: 就必须设置US_FL_IGNORE_RESIDUE
- Page 171 and 172: 485 }; 486 这是一个字符数组
- Page 173 and 174: srb->sense_buffer 里边的东西.S
- Page 175 and 176: 一个类似的函数,名叫usb_sto
- Page 177 and 178: 这种命令应该由mid level 来
- Page 179 and 180: Disk /dev/sda: 146.1 GB, 1461631057
- Page 181 and 182: through to the most significant bit
- Page 183 and 184: 1192 USB_TYPE_CLASS | USB_RECIP_INT
- Page 185 and 186: 315 行,scsi_report_device_reset(),
- Page 187 and 188: 285 US_DEBUGP("No reset during disc
- Page 189 and 190: 229 /* Wait for the aborted command
- Page 191 and 192: 两个函数中需要判断它,一
- Page 193 and 194: associate_dev()相对应.我们来
- Page 195: 束for 死循环,从而usb_stor_con
317 for (i = 1; i < us->host->max_id; ++i)<br />
318 scsi_report_device_reset(us->host, 0, i);<br />
319 }<br />
320 }<br />
注意到,她里边调用了scsi_report_device_reset(),后者来自drivers/scsi/scsi_error.c,这正是scsi<br />
mid layer 定义的函数,这个函数的注释说得很清楚,调用她时必须要拥有host lock.<br />
有人说还有第三种情况,drivers/usb/storage/usb.c,usb_stor_control_thread()函数中,<br />
318 /* lock access to the state */<br />
319 scsi_lock(host);<br />
320<br />
321 /* has the command timed out *already* ? */<br />
322 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {<br />
323 us->srb->result = DID_ABORT