You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
输中的函数usb_stor_bulk_transfer_sglist(),她会调用set_bit 函数来设置这个flag. 于是这里也判<br />
断,<br />
如果确实设置了,那么此时就可以调用usb_sg_cancel 来把sg 取消.<br />
192<br />
看得出,usb_stor_stop_transport()的决心很坚定,目标很简单,就是要让你的传输进行不下去,有urb<br />
就取消urb,有sg 就取消sg,大有人挡杀人佛当杀佛的魄力和勇气.<br />
这时,在230 行,咱们看到了等待函数,wait_for_completion(&us->notify),command_abort()函数<br />
进入等待.谁来唤醒它呢?usb_stor_control_thread()中的complete(&(us->notify))唤醒她.<br />
一种情况,您这里睡眠中,usb 设备断开了,于是usb_stor_control_thread 要退出来,于是它会调用<br />
complete_and_exit()来唤醒command_abort()并且退出usb_stor_control_thread(),这样一来的<br />
话那么世界从此就清静了.<br />
第二种情况,一个scsi 命令还没有开始执行,或者说即将要开始执行的时候,我们调用了<br />
command_abort(),那么对应于usb_stor_control_thread()中的322 到325 那几行的if 语句,发现<br />
US_FLIDX_TIMED_OUT flag 被设置了,于是,命令也甭执行了,直接goto SkipForAbort,然后调用<br />
complete(&(us->notify))唤醒咱们这里进入睡眠的进程.同时,对于usb_stor_control_thread()这边<br />
来说,将us->srb 设置为NULL 就一切ok 了,可以开始下一轮循环了.<br />
第三种情况, 一个scsi 命令执行完了之后,我们才执行的command_abort,那么这种情况下,由于我们<br />
设置了US_FLIDX_TIMED_OUT 标志,对应于usb_stor_control_thread()那边的396,397 行的if 语<br />
句,也没什么特别的,同样的,执行complete(&(us->notify))唤醒咱们这个进入睡眠的进程吧.并且将<br />
us->srb 置为NULL.<br />
最后,234,235 行,清除这两个US_FLIDX_ABORTING 和US_FLIDX_TIMED_OUT 这两个flag,接<br />
下来的传输还是外甥打灯笼-照旧.而command_abort()函数本身当然返回SUCCESS.阻止了别人,她就<br />
成功了.所以它返回SUCCESS.<br />
至此我们就算讲完了这三个负责错误处理的函数了.那么关于这两个flag 的故事呢.让我们来看看.实际<br />
上你搜索一下整个内核目录,只有command_abort()函数中set 了这两个flag,而如果<br />
command_abort()执行成功了,会在返回之前,把两个flag 给清除掉.而需要测试<br />
US_FLIDX_TIMED_OUT 这个flag 的地方,仅仅只有usb_stor_control_thread()中和<br />
usb_stor_invoke_transport()中.关于前者正是我们刚才所讲的那样,除了唤醒command_abort()以<br />
外,就是设置us->srb 为NULL,但总的来说,基本上对scsi 那边没有什么影响.而在<br />
usb_stor_invoke_transport()中,如果我们遇到了US_FLIDX_TIMED_OUT 被设置,那么情况会有所<br />
不同,因为这时候我们是在与scsi 层打交道,我们是因为要执行一个scsi 命令才进入到<br />
usb_stor_invoke_transport()的,所以在这种情况下如果遇到了abort,那么我们至少得给scsi 一个交<br />
待,<br />
正如我们在usb_stor_invoke_transport()中第724 行那一小段看到的那样,我们回复给scsi 层的是<br />
srb->result,我们把它设成了DID_ABORT