討論下Linux下SCSI棧的IO錯誤處理策略


討論下Linux下SCSI棧的IO錯誤處理策略

(一)盡快報錯  or  盡力重試?

先討論一個問題:如果上級交給的任務暫時無法完成,那么我們應該:

(策略1)應該盡快向上報錯(abort),等待上級做出下一步的指令。

(策略2)暫不報告失敗,而是帶着未完成的任務,去修復和重試。

(二)Linux的SCSI對錯誤的處理策略

目前Linux的SCSI棧,默認的策略是暫時不要向上報錯,而是修復和重試。希望能對上級屏蔽底層錯誤,返回一個重試后的成功的結果。

 

如果SCSI設備驅動完整的注冊了各個修復函數(scsi_en_XX_reset ),

那么底層回錯的結果就是, 從下向上,逐級修復, 最后把堆積的IO再提交一遍。

如果SCSI設備驅動沒有注冊scsi_en_XX_reset函數,那么就沒有相關修復處理。

 

static void scsi_unjam_host(struct Scsi_Host *shost)

{

    略 。。。

    if (!scsi_eh_get_sense(&eh_work_q, &eh_done_q))

          scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q);

    略 。。。

    scsi_eh_flush_done_q(&eh_done_q);

}

 

void scsi_eh_ready_devs(struct Scsi_Host *shost,

      struct list_head *work_q,

      struct list_head *done_q)

{

  if (!scsi_eh_stu(shost, work_q, done_q))

     if (!scsi_eh_bus_device_reset(shost, work_q, done_q))

        if (!scsi_eh_target_reset(shost, work_q, done_q))

           if (!scsi_eh_bus_reset(shost, work_q, done_q))

             if (!scsi_eh_host_reset(shost, work_q, done_q))

                 scsi_eh_offline_sdevs(work_q,done_q);

}

這段代碼看的我心驚膽戰。

這個反復重試的策略,對單機系統是合理的,但是對分布式系統不合理。

本來分布式系統可以選擇這個盤,也可以選擇那個盤,但肯定不會選擇故障的盤。早點讓上級知道,能更快的把后續讀寫任務切到其他盤。然后故障盤再執行硬件修復(比如Smart查詢,壞道掃描,硬盤上下電)就從容了。再說,如果遇到硬件故障,簡單的重試大概率還是失敗。

 

(三)學習結論:

(策略1)如果是集中式的單控系統,讀寫任務遷移困難,那么遇到困難先別急着abort,還是盡量重試吧。

(策略2)如果是分布式系統,讀寫任務可以遷移,那么應該盡快abort,因為分布式系統的可靠性從來不是構築在單設備可靠性之上,而是用冗余來彌補單設備可靠性的不足。如果底層早點報錯,那么上層就能早點切換。

 

##############################

相關函數序列如下:

(1)SCSI層的提交,然后等待硬盤執行完畢后返回中斷

scsi_queue_rq

   => scsi_dispatch_cmd

      ==> Scsi_Host->hostt->queuecommand

      ==> scsi_cmnd->scsi_done

 

scsi_execute_req

   => scsi_execute

     ==> __scsi_execute

        ===> blk_execute_rq

 

(2)硬盤返回處理:返回成功 or 返回失敗 or 不按時返回

(2.1)中斷前半部-硬中斷回調

handle_level_irq

  _base_interrupt

       mpt_callbacks

       _scsih_io_done

           scsi_cmnd->scsi_done

               scsi_mq_done

                    blk_mq_complete_request

                       blk_mq_complete_request_remote

                          blk_mq_trigger_softirq

                              raise_softirq_irqoff

                              // 放到軟中斷中去處理:BLOCK_SOFTIRQ

 

(2.2)中斷后半部-軟中斷回調

 do_softirq

   do_softirq_own_stack

     _do_softirq

       softirq_action->action

       // subsys_initcall(blk_softirq_init)

       // BLOCK_SOFTIRQ    <---> blk_done_softirq

       blk_done_softirq

            request_queue->softirq_done_fn

            scsi_softirq_done

                 scsi_decide_disposition

                        //  SCSI操作完成

                       (A)scsi_finish_command

                            scsi_io_completion

                                scsi_end_request

                                   blk_update_request

                                       req_bio_endio

                                            bio_endio

                                                 bio->bi_end_io

                                                      end_bio_bh_io_sync

 

                                blk_finish_request

                                  request->end_io

                                  // blk_end_sync_rq

                           scsi_run_queue

                     (B) scsi_queue_insert

                            _scsi_queue_insert

                              blk_requeue_request

                                 elv_requeue_request

                              kblockd_schedule_work

                     (C) scsi_eh_scmd_add

 

(2.3)返回錯誤的處理 

我再強調下結論,分布式系統要盡快返回結果。

先abort,然后再修復底層故障。

不要一邊Hung住未完成的IO,一邊來修復底層故障!

  scsi_error_handler //while循環任務   

    (A)eh_strategy_handler //自定義處理策略

       # ata_scsi_error

   

    (B)scsi_unjam_host  //SCSI默認處理策略

      scsi_eh_ready_devs

         scsi_eh_bus_device_reset

         scsi_eh_target_reset

         scsi_eh_bus_reset

         scsi_eh_host_reset

         scsi_eh_flush_done_q

(3)超時檢查

blk_mq_check_expired

    blk_mq_rq_timed_out

       request->q->mq_ops->timeout

           scsi_timeout

               scsi_times_out

                   scsi_eh_scmd_add

                       scsi_eh_wakeup

                           Scsi_Host->ehandler

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM