天天看點

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 資料速率的演化
Linux SCSI

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 核心中的位置
Linux SCSI

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

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

在 ./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_probe

sd_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 也将不會例外。

繼續閱讀