1. 程式人生 > >iscsi:IO操作流程(三)

iscsi:IO操作流程(三)

概述

當我們講到scsi命令這個概念時,需要根據上下文去理解。可能指代兩個概念:
- 一種含義指SCSI協議規劃中定義的SCSI 命令描述塊(Command descriptor block (CDB))。此描述塊定義了需要target處理的具體的操作。遵循特定的資料格式,其格式根據操作的不同而不同。SCSI規範中針對每個命令的CDB都有詳細的說明。描述塊會經過傳輸層完整的傳送到scsi target用於解析並執行。
- 另外一種含義指核心中定義的scsi_cmnd結構。該結構定義於linux/include/scsi/scsi_cmnd.h中,描述了請求在SCSI子系統執行所需要的資料結構。每個請求都會建立一個scsi_cmnd資料結構。它創建於請求的初始化,結束於命令被正確的執行或者在操作中出現錯誤。其儲存的資訊不僅僅包括了最終傳送給scsi target的資料,也包括了在scsi子系統和scsi底層驅動執行中需要的執行時資訊。

CBD格式

隨著技術的發展 ,儲存裝置的容量持續增長。原有的SCSI指令的定址空間不能滿足新的要求,於是就定了新的可支援更大空間的CBD格式。考慮到向前相容,SCSI協議沒有取消原有的指令,而是重新定義操作碼。於是,針對一種服務(如讀、寫)定義了多種指令格式。
CBD格式分為定長格式和變長格式。
定長格式的CBD包括6、10、12、16四種格式,數字表示CBD的長度(單位:位元組)。所有定長指令的第一個位元組均為操作碼,最後一個位元組為控制塊。其它域取決於指令。
變長格式,其長度取決於具體的指令。如READ(32)、WRITE(32)分別為32位元組。變長格式第一個位元組為操作碼,固定為操作碼(7Fh),其具體服務(如讀、寫)放在SERVICE ACTION

域,即CBD的第8、第9位元組。變長格式的前10個位元組是固定的。
無論是定長格式還是變長格式,都包括固定部分,即所有的指令都有的。這樣有利於程式設計。系統可以將CBD前幾個位元組進行統一的解析,再進一步的根據操作碼判斷後面是否有資料段需要進一步解析。
CDB在核心中表現為一個連續的記憶體空間。通常它的儲存空間在請求初始化時被建立,隨著請求完成被釋放。請求初始化過程中給cmnd分配了16個位元組。
當CDB長度大於32時,驅動程式它初始化時建立的專用快取池sd_cdb_pool上申請。

讀命令分析

定長讀命令

READ讀命令可以分成兩種格式。READ(10)、READ(12)、READ(16)格式一致,歸為第一類。READ32歸為第二類。
READ(10)、READ(12)、READ(16)所包括的屬性一致。兩者別在於LBA與資料傳輸位元組數兩個欄位的長度,這兩個欄位長度決定了SCSI指令所能支援的最大容量和一次IO最大的資料長度。自SCSI-3始,規範建議實現方將READ(10-12)遷移到READ16上。
READ(16) CBD格式如下圖:
這裡寫圖片描述


各個欄位含義:

欄位 含義 實現
OPERATION CODE 指令操作碼|呼叫sd_setup_read_write_cmnd設定
RDPROTECT DIF支援相關屬性 呼叫sd_setup_read_write_cmnd設定;設定值取決於磁碟DIF保護方式
DPO 禁用頁面快取(Disable Page Out)。
設定1意為執行此操作時,不進行快取替換
設定為0意為讀取時同時在裝置快取中保留此資料
Linux永遠設為0
FUA 強制訪問介質。
如果設定為1,意味著target強制從介質中讀取資料,而非從快取中
在構造IO請求(struct request)時根據應用要求設定;
RARC 重構輔助模式。 scsi層未處理
LOGICAL BLOCK ADDRESS 讀命令的起始地址 與請求的起始地址一致。以扇區(512位元組)為單位
TRANSFER LENGTH 讀寫資料長度 與請求的讀寫長度一致
CONTROL 命令控制塊 SCSI子系統未設定

變長讀命令

變長由自第12位元組始的8位元組表示LBA,由第28位元組始的4個位元組表示資料長度。其支援的最大容量與最大扇區數與READ16相同。其它變數的含義與READ(16),不詳細解釋。
比定長CBD多出來的位元組主要是用於資料校驗。T10是用於解決靜默錯誤的一種機制。
資料在讀寫環境中要經過多個部件、多個傳輸渠道和多層次的軟體系統,考慮到效能,系統設計過程中並非每層次都對資料進行檢測。如此,最終固化的到磁碟上的資料可能是不正確的。為避免此類錯誤存在,ANSI T10 定義了一種通過對每個資料塊加入保護資訊(PI:Protection Information)也曾被稱作資料完整性域(DIF:Data Integrity Field)的方法來保護資料完整性。只有開啟T10資訊檢驗且採用type2 保護資訊時,才使用READ(10)命令格式。
P10在企業Oracle資料庫應用比較廣泛,且是儲存一大亮點,所以主流的儲存廠商都支援該特性,如EMC VNX系列支援自定義PI、VMAX支援標準的T10 PI,且支援DIX;HDS HUS系列支援自定義PI、HDS VSP支援PI;IBM DS8000支援標準的T10 PI,DS5000某些特定型號支援PI;HP P10000支援標準的T10 PI,華為 OceanStor 18000和V3全系列。 1
這裡寫圖片描述

寫命令分析

寫命令與讀命令在格式上非常相似,也分為多種格式。
這裡寫圖片描述
不同的寫操作對應的服務是一致的。在Target端可對應於相同的實現。以WRITE(10)為例。其操作碼為24A。同時,也包括了用於DIF處理的WRPROTECT域,用於快取控制的DPO、FUA域。

scsi_cmnd

scsi_cmnd結構體記錄了scsi_cmnd需要處理的所有的上下文。系統在初始化request時就為scsi_cmnd申請空間。當request在子系統處理完成,scsi上層驅動根據request建立scsi_cmnd。面向IO的scsi_cmndrequest是一對一的關係。
scsi_cmnd包含了scsi指令處理所需要的資訊,包括CBD、資料、sense data等域。除此之外,還包括一些控制域。
scsi_cmnd包含了scsi裝置的相關資訊,用於確定交scsi_cmnd針對於哪個裝置。在
scsi_cmnd流轉時,裝置型別相關的邏輯處理完成,系統更加關注指令和資料在通訊鏈路上的流轉。即關注匯流排、主機介面卡、傳輸層等資訊。
scsi_cmnd生命週期中可能被掛接到多個不同的佇列,代表不同的控制面。大多資料情況,scsi_cmnd連結到主機介面卡的命令處理佇列中;在處理過程發生故障時,它又被錯誤處理相關的佇列中暫存,一旦故障恢復,再進行繼續處理;如果因為裝置忙等原因,主機介面卡不能接收scsi命令時,scsi_cmnd將放到延時處理連結串列中,等合適的時機再行處理。