Scsi - Index of

Scsi - Index of Scsi - Index of

07.06.2013 Views

具体到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

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!