Linux SCSI

分層 SCSI 架構簡介

Small Computer Systems Interface (SCSI) 是一組標準集,它定義了與大量設備(主要是與存儲相關的設備)通信所需的接口和協議。 Linux 提供了一種 SCSI 子系統,用於與這些設備通信。Linux 是分層架構的一個很好的例子,它將高層的驅動器(比如磁盤驅動器或光驅)連接到物理接口,比如 Fibre Channel 或 Serial Attached SCSI(SAS)。本文向您介紹了 Linux SCSI 子系統,並且討論了這些子系統將來的發展方向。





GNU/Linux 和 SCSI 是很好的一個組合,因爲二者在各自的環境中具有類似的特徵。GNU/Linux 是一種安全可靠的操作系統,可以不間斷地運行。SCSI 適合於可靠和高性能存儲。二者都是開源的。您可以下載和查閱 International Committee on Information Technology Standards (INCITS) T10 Technical Committee 的各種 SCSI 規範。同樣地,您也可以下載 GNU/Linux 源代碼以理解其實現。它們在各自的行業都具有主導性,所以相對其他操作系統而言,GNU/Linux 能更好地支持 SCSI,這一點就不足爲奇了。

SCSI 是一種很有趣的接口,它是早期的接口之一,如今還在不斷演化。第一種 SCSI 標準稱爲 SCSI-1,是由 Shugart Associates 在 1979 年前後創建的。SCSI-1 定義了一種具有 5MHz 數據時鐘的 8-bit 並行接口,能提供最高 5 兆字節每秒(5 MB/s)的數據傳輸速率。


SCSI-2 標準出現於 1985 年,它的出現使數據速率更快(10MHz),總線也更寬(16 位)。被稱爲 Fast/Wide 的 SCSI-2 允許的數據傳輸速率高達 20 MB/s,並具有與 SCSI-1 的向後兼容性,但是速率也會限制到 SCSI-1 的數據速率。


SCSI-3 的開發開始於 1993 年,現已成爲了一組標準集,可以定義協議、命令集和信令方法。在 SCSI-3 中,包含一組命名爲 Ultra 的並行 SCSI 標準和基於串行 SCSI 的協議,比如 IEEE 1394 (FireWire)、Fibre Channel, 、Internet SCSI (iSCSI) 和新興的 SAS。這些標準通過引入存儲網絡技術(比如 FC-AL 或 iSCSI)改變了傳統的存儲理念,將數據速率擴展到了 1 Gbit/s,將最大的可尋址設備數增加到了 100 以上,並將最大的電纜長度擴展到了 25 米。圖 1 展示了從 1986 至 2007 年 SCSI 的數據速率的變化

圖 1. SCSI 數據速率的演化

wKioL1NWWyjBaTphAAAhZz7fXqc961.gif

SCSI 命令

SCSI 傳輸所採用的協議已經時過境遷,SCSI 命令卻保持了最初的元素。SCSI 命令是在 Command Descriptor Block (CDB) 中定義的。CDB 包含了用來定義要執行的特定操作的操作代碼,以及大量特定於操作的參數。

SCSI 命令支持讀寫數據(各有四個變量)以及很多非數據命令,比如 test-unit-ready(設備是否已就緒)、inquiry(檢索有關目標設備的基本信息)、read-capacity(檢索目標設備的存儲容量)等等。目標設備支持何種命令取決於設備的類型。發起者通過 inquiry 命令識別設備類型。表 1 列出了最常用的 SCSI 命令。

表 1. 常見 SCSI 命令
命令用途
Test unit ready查詢設備是否已經準備好進行傳輸
Inquiry請求設備基本信息
Request sense請求之前命令的錯誤信息
Read capacity請求存儲容量信息
Read從設備讀取數據
Write向設備寫入數據
Mode sense請求模式頁面(設備參數)
Mode select在模式頁面配置設備參數

藉助大約 60 種可用命令,SCSI 可適用於許多設備(包括隨機存取設備,比如磁盤和像磁帶這樣的順序存儲設備)。SCSI 也提供了專門的命令以訪問箱體服務(比如存儲箱體內部當前的傳感和溫度)。



Linux 內核中的 SCSI 架構

圖 2 顯示了 SCSI 子系統在 Linux 內核中的位置。內核的頂部是系統調用接口,處理用戶空間調用到內核中合適的目的地的路由(例如 open、read 或 write)。而虛擬文件系統(VFS) 是內核中支持的大多數文件系統的抽象層。它負責將請求路由到合適的文件系統。大多數文件系統都通過緩衝區緩存來相互通信,這種緩存通過緩存最近使用的數據來優化對物理設備的訪問。接下來是塊設備驅動器層,它包括針對底層設備的各種塊驅動器。SCSI 子系統是這種塊設備驅動器之一。

圖 2. SCSI 子系統在 Linux 內核中的位置

wKiom1NWVZHR0saLAAAsZpVQf6E456.gif

與 Linux 內核中的其他主流子系統不同,SCSI 子系統是一種分層的架構,共分爲三層。頂部的那層叫做較高層,代表的是內核針對 SCSI 和主要設備類型的驅動器的最高接口。接下來的是中間層,也稱爲公共層或統一層。在這一層包含 SCSI 堆棧的較高層和較低層的一些公共服務。最後是較低層,代表的是適用於 SCSI 的物理接口的實際驅動器(參見圖 3)。

圖 3. Linux SCSI 子系統的分層架構

wKiom1NWVbCinNQiAAAjqDBXiMY338.gif

在 ./linux/drivers/scsi 可以找到 SCSI 子系統(SCSI 較高層、中間層和各種驅動器)的源代碼。SCSI 數據結構則位於 SCSI 源目錄,在 ./linux/include/scsi 也可以找到。



SCSI 較高層

SCSI 子系統的較高層代表的是內核(設備級)最高級別的接口。它由一組驅動器組成,比如塊設備(SCSI 磁盤和 SCSI CD-ROM)和字符設備(SCSI 磁帶和 SCSI generic)。較高層接受來自上層(比如 VFS)的請求並將其轉換成 SCSI 請求。較高層負責完成 SCSI 命令並將狀態信息通知上層。

SCSI 磁盤驅動器在 ./linux/drivers/scsi/sd.c 內實現。SCSI 磁盤驅動器通過調用register_blkdev(作爲塊驅動器)進行自初始化並通過scsi_register_driver提供一組函數以表示所有 SCSI 設備。其中sd_probesd_init_command這兩個函數很重要。只要有新的 SCSI 設備附加到系統, SCSI 中間層就會調用sd_probe函數。sd_probe函數可決定此設備是否由 SCSI 磁盤驅動器管理,如果是,就創建新的scsi_disk結構來表示它。sd_init_command函數將來自文件系統層的請求轉變成 SCSI 讀或寫命令(爲完成這個 I/O 請求,sd_rw_intr會被調用)。

SCSI 磁帶驅動器在 ./linux/drivers/scsi/st.c 內實現。磁帶驅動器是順序存取設備,會通過register_chrdev_region將自身註冊爲字符設備。SCSI 磁帶驅動器還提供了一個 probe 函數,稱爲st_probe。該函數會創建一種新磁帶設備並將其添加到稱爲scsi_tapes的向量。SCSI 磁帶驅動器的獨特之處在於,如果可能,它可以直接從用戶空間執行 I/O 傳輸。否則,數據會通過驅動器緩衝被分段。

SCSI CD-ROM 驅動器在 ./linux/drivers/scsi/sr.c 內實現。CD-ROM 驅動器是另一種塊設備併爲 SCSI 磁盤驅動器提供類似的函數集。sr_probe函數可用來創建scsi_sd結構以表示 CD-ROM 設備,並用register_cdrom註冊此 CD-ROM。SCSI 磁帶驅動器還會導出sr_init_command,以將請求轉換成 SCSI CD-ROM 讀或寫請求。

SCSI generic 驅動器在 ./linux/drivers/scsi/sg.c 內實現。該驅動器允許用戶應用程序向設備發送 SCSI 命令(比如格式化、模式感知或診斷命令)。通過 sg3utils 包還可以從用戶空間利用 SCSI generic 驅動器。這個用戶空間包包括多種實用工具,可用來發送 SCSI 命令和解析這些命令的響應。



SCSI 中間層

SCSI 中間層是 SCSI 較高層和較低層的公共服務層(可以在 ./linux/drivers/scsi/scsi.c 內部分地實現)。它提供了很多可供較高層和較低層驅動器使用的函數,因而可以充當這兩層間的連接層。中間層很重要,原因是它抽象化了較低層驅動器(LLD)的實現,可以在 ./linux/drivers/scsi/hosts.c 中部分地實現。這意味着可以以同樣的方式使用帶不同接口的 Fibre Channel 主機總線適配器(HBA)。

低層驅動器註冊和錯誤處理都由 SCSI 中間層提供。中間層還提供了較高層和較低層間的 SCSI 命令排隊。SCSI 中間層的一個重要功能是將來自較高層的命令請求轉換成 SCSI 請求。它也負責管理特定於 SCSI 的錯誤恢復。

中間層可以連接 SCSI 子系統的較高層和較低層。它接受對 SCSI 事務的請求並對這些請求進行排隊以便處理 (如 ./linux/drivers/scsi/scsi_lib.c 中所示)。當這些命令完成後,它接受來自 LLD 的 SCSI 響應並通知較較高層此請求已經完成。

中間層最重要的職責之一是錯誤和超時處理。如果 SCSI 命令沒有在合理的時間內完成或者 SCSI 請求返回錯誤,中間層就會管理錯誤或重新發送此請求。中間層還可管理較高層恢復,比如請求 HBA (LLD) 或 SCSI 設備重置。SCSI 錯誤和超時處理程序在 ./linux/drivers/scsi/scsi_error.c 內實現。



SCSI 較低層

在最低層的是一組驅動器,稱爲 SCSI 低層驅動器。它們是一些可與物理設備(比如 HBA)鏈接的特定驅動器。LLD 提供了自公共中間層到特定於設備的 HBA 的一種抽象。每個 LLD 都提供了到特定底層硬件的接口,但所使用的到中間層的接口卻是一組標準接口。

較低層包含大量代碼,原因是它要負責處理各種不同的 SCSI 適配器類型。例如,Fibre Channel 協議包含了針對 Emulex 和 QLogic 的各種適配器的 LLD。面向 Adaptec 和 LSI 的 SAS 適配器的 LLD 也包括在內。



Linux 和 SCSI 的未來展望

毫無疑問,SCSI 的發展前景很好,並且它會與 Linux 緊密相關。隨着 SCSI 的演化,Linux 將會一如既往地爲不斷髮展的技術提供支持。Linux 藉助面向 HBA 的驅動器爲新的 SAS 協議提供支持。隨着協議向更快的速度發展(比如 6 Gb SAS 或 8 Gb FC),Linux 必將處在發展和部署的前沿。

您還會發現 Linux 恰恰就是新 SCSI 協議的先進之處。FCoE(Fibre Channel over Ethernet)頗值得一提。FCoE 是全雙工 Ethernet 網絡(通常是 1Gb 或 10Gb Ethernet)上的一種 Fibre Channel 框架的映射。FCoE 之所以重要,是因爲它將主流的網絡媒介與主流的企業存儲協議連接起來。這種新技術必然受人矚目,而且 Linux 也將不會例外。

針對 SCSI 的端到端數據保護也在開發中,它源於 T10 的新數據完整性標準。這個標準爲每扇區都增加了一個數據完整性字段(DIF)以保護介質上的數據。這個新的 8 字節 DIF 字段包括一個循環冗餘代碼(CRC)用以保護數據,一個參考標籤用以保護數據免遭誤導寫入,以及一個應用程序標籤。應用程序標籤特定於應用程序,並且可以定義數據的用途,例如,一個 PDF 文件的一部分。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章