SCSI 介面指南

作者:

James Bottomley

作者:

Rob Landley

介紹

協議與匯流排

很久以前,小型計算機系統介面定義了一種並行 I/O 匯流排和一種資料協議,用於將各種外圍裝置(磁碟驅動器、磁帶驅動器、調變解調器、印表機、掃描器、光碟機、測試裝置和醫療裝置)連線到主機。

儘管舊的並行(快速/寬/超寬)SCSI 匯流排已基本不再使用,但 SCSI 命令集的使用範圍比以往任何時候都更廣泛,可以透過多種不同的匯流排與裝置通訊。

SCSI 協議是一種大端對等基於資料包的協議。 SCSI 命令長度為 6、10、12 或 16 個位元組,通常後跟關聯的資料有效負載。

SCSI 命令幾乎可以透過任何型別的匯流排傳輸,並且是連線到 USB、SATA、SAS、光纖通道、FireWire 和 ATAPI 裝置的儲存裝置的預設協議。 SCSI 資料包也通常透過 InfiniBand、TCP/IP (iSCSI),甚至 並行埠 進行交換。

Linux SCSI 子系統的設計

SCSI 子系統使用三層設計,包括上層、中層和下層。 每個涉及 SCSI 子系統的操作(例如從磁碟讀取扇區)都會使用每一層的驅動程式:一個上層驅動程式、一個下層驅動程式和 SCSI 中間層。

SCSI 上層以 I/O 和 ioctl() 的塊和字元裝置節點的形式提供使用者空間和核心之間的介面。 SCSI 下層包含特定硬體裝置的驅動程式。

兩者之間是 SCSI 中間層,類似於網路路由層,例如 IPv4 堆疊。 SCSI 中間層在上面的 /dev 節點和下面的相應裝置之間路由基於資料包的資料協議。 它管理命令佇列,提供錯誤處理和電源管理功能,並響應 ioctl() 請求。

SCSI 上層

上層透過提供裝置節點來支援使用者核心介面。

sd (SCSI 磁碟)

sd (sd_mod.o)

sr (SCSI CD-ROM)

sr (sr_mod.o)

st (SCSI 磁帶)

st (st.o)

sg (SCSI 通用)

sg (sg.o)

ch (SCSI 媒體更換器)

ch (ch.c)

SCSI 中間層

SCSI 中間層實現

include/scsi/scsi_device.h

struct scsi_vpd

SCSI 重要產品資料

定義:

struct scsi_vpd {
    struct rcu_head rcu;
    int len;
    unsigned char   data[];
};

成員

rcu

用於 kfree_rcu()

len

**data** 的長度(以位元組為單位)。

data

VPD 資料,如各種 T10 SCSI 標準文件中所定義。

shost_for_each_device

shost_for_each_device (sdev, shost)

迭代主機的所有裝置

引數

sdev

用作遊標的 struct scsi_device

shost

要迭代的 struct scsi_host

描述

迭代器,返回連線到 **shost** 的每個裝置。 此迴圈獲取每個裝置上的引用並在末尾釋放它。 如果你跳出迴圈,則必須呼叫 scsi_device_put(sdev)。

__shost_for_each_device

__shost_for_each_device (sdev, shost)

迭代主機的所有裝置(已解鎖)

引數

sdev

用作遊標的 struct scsi_device

shost

要迭代的 struct scsi_host

描述

迭代器,返回連線到 **shost** 的每個裝置。 它不獲取 scsi_device 上的引用,因此整個迴圈必須受 shost->host_lock 保護。

注意

使用它的唯一原因是需要訪問中斷上下文中的裝置列表。 否則,你真的想要使用 shost_for_each_device。

int scsi_device_supports_vpd(struct scsi_device *sdev)

測試裝置是否支援 VPD 頁面

引數

struct scsi_device *sdev

要測試的 struct scsi_device

描述

如果設定了“try_vpd_pages”標誌,則它優先。 否則,如果 SCSI 級別至少為 SPC-3 並且未設定“skip_vpd_pages”,我們將假定支援 VPD 頁面。

drivers/scsi/scsi.c

SCSI 中間層的主檔案。

int scsi_change_queue_depth(struct scsi_device *sdev, int depth)

更改裝置的佇列深度

引數

struct scsi_device *sdev

有問題的 SCSI 裝置

int depth

允許排隊到驅動程式的命令數

描述

設定裝置佇列深度並返回新值。

int scsi_track_queue_full(struct scsi_device *sdev, int depth)

跟蹤 QUEUE_FULL 事件以調整佇列深度

引數

struct scsi_device *sdev

有問題的 SCSI 裝置

int depth

此裝置上未完成的 SCSI 命令的當前數量,不包括返回為 QUEUE_FULL 的命令。

描述

此函式將跟蹤特定的

SCSI 裝置上的連續 QUEUE_FULL 事件,以確定是否以及何時需要調整裝置上的佇列深度。

鎖定狀態:條目上未持有任何鎖

返回

0 - 不需要更改,>0 - 將佇列深度調整為此新深度,
-1 - 使用 host->cmd_per_lun 作為未標記的命令深度回退到未標記的操作

註釋

底層驅動程式可以隨時呼叫它,我們將執行

“正確的事”。 我們是中斷上下文安全的。

“正確的事情”。我們是中斷上下文安全的。

int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf, int buf_len)

從 SCSI 裝置獲取重要產品資料

引數

struct scsi_device *sdev

要詢問的裝置

u8 page

要返回的 Vital Product Data

unsigned char *buf

儲存 VPD 的位置

int buf_len

VPD 緩衝區區域中的位元組數

描述

SCSI 裝置可以選擇性地提供 Vital Product Data。 每個 VPD“頁面”都在相應的 SCSI 文件(例如 SPC、SBC)中定義。 如果裝置支援此 VPD 頁面,則此例程將使用該頁面的資料填充 **buf** 並返回 0。 如果不支援 VPD 頁面或無法檢索其內容,則返回 -EINVAL。

int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, unsigned int len, unsigned char opcode, unsigned short sa)

查明是否支援給定命令

引數

struct scsi_device *sdev

要查詢的 scsi 裝置

unsigned char *buffer

暫存緩衝區(長度必須至少為 20 位元組)

unsigned int len

緩衝區長度

unsigned char opcode

要查詢的命令的操作碼

unsigned short sa

要查詢的命令的服務操作

描述

使用 REPORT SUPPORTED OPERATION CODES 檢查對使用 **opcode** 和 **sa** 標識的命令的支援。 如果命令沒有服務操作,則 **sa** 必須為 0。 如果 RSOC 失敗,則返回 -EINVAL;如果不支援該命令,則返回 0;如果裝置宣告支援該命令,則返回 1。

int scsi_device_get(struct scsi_device *sdev)

獲取對 scsi_device 的額外引用

引數

struct scsi_device *sdev

要獲取引用的裝置

描述

獲取對 scsi_device 的引用並遞增底層 LLDD 模組的使用計數。 呼叫此函式時,你必須持有父 Scsi_Host 的 host_lock 或已經具有引用。

如果裝置被刪除或取消,或者 LLD 模組正在解除安裝過程中,則此操作將失敗。

void scsi_device_put(struct scsi_device *sdev)

釋放對 scsi_device 的引用

引數

struct scsi_device *sdev

要釋放引用的裝置。

描述

釋放對 scsi_device 的引用並遞減底層 LLDD 模組的使用計數。 一旦最後一個使用者消失,該裝置將被釋放。

void starget_for_each_device(struct scsi_target *starget, void *data, void (*fn)(struct scsi_device*, void*))

幫助程式遍歷目標的所有裝置

引數

struct scsi_target *starget

我們要迭代的裝置的目標。

void *data

傳遞給每個函式呼叫的不透明資料。

void (*fn)(struct scsi_device *, void *)

要在每個裝置上呼叫的函式

描述

這將遍歷 **starget** 的每個裝置。 這些裝置具有一個引用,必須透過 scsi_host_put 在跳出迴圈時釋放該引用。

void __starget_for_each_device(struct scsi_target *starget, void *data, void (*fn)(struct scsi_device*, void*))

遍歷目標的所有裝置的助手函式 (未鎖定)

引數

struct scsi_target *starget

我們要迭代的裝置的目標。

void *data

回撥函式 fn() 的引數

void (*fn)(struct scsi_device *, void *)

為每個裝置呼叫的回撥函式

描述

此函式遍歷 starget 的每個裝置。它_不_獲取對 scsi_device 的引用,因此整個迴圈必須由 shost->host_lock 保護。

注意

驅動程式可能想要使用此函式的唯一原因是,它們需要在 irq 上下文中訪問裝置列表。否則,您真的想使用 starget_for_each_device 代替。

struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *starget, u64 lun)

查詢給定目標的裝置 (未鎖定)

引數

struct scsi_target *starget

SCSI 目標指標

u64 lun

SCSI 邏輯單元號

描述

查詢具有指定 lun 的 scsi_device 以用於給定的 starget。返回的 scsi_device 沒有額外的引用。您必須在此呼叫以及對返回的 scsi_device 的任何訪問中持有主機的 host_lock。狀態為 SDEV_DEL 的 scsi_device 將被跳過。

注意

驅動程式應該使用此函式的唯一原因是,它們需要在 irq 上下文中訪問裝置列表。否則,您真的想使用 scsi_device_lookup_by_target 代替。

struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *starget, u64 lun)

查詢給定目標的裝置

引數

struct scsi_target *starget

SCSI 目標指標

u64 lun

SCSI 邏輯單元號

描述

查詢具有指定 lun 的 scsi_device 以用於給定的 starget。返回的 scsi_device 有一個額外的引用,一旦您完成使用它,就需要使用 scsi_device_put 釋放該引用。

struct scsi_device *__scsi_device_lookup(struct Scsi_Host *shost, uint channel, uint id, u64 lun)

查詢給定主機的裝置 (未鎖定)

引數

struct Scsi_Host *shost

SCSI 主機指標

uint channel

SCSI 通道 (如果只有一個通道,則為零)

uint id

SCSI 目標編號 (物理單元編號)

u64 lun

SCSI 邏輯單元號

描述

查詢具有指定 channelidlun 的 scsi_device 以用於給定的主機。返回的 scsi_device 沒有額外的引用。您必須在此呼叫以及對返回的 scsi_device 的任何訪問中持有主機的 host_lock。

注意

驅動程式可能想要使用此函式的唯一原因是,它們需要在 irq 上下文中訪問裝置列表。否則,您真的想使用 scsi_device_lookup 代替。

struct scsi_device *scsi_device_lookup(struct Scsi_Host *shost, uint channel, uint id, u64 lun)

查詢給定主機的裝置

引數

struct Scsi_Host *shost

SCSI 主機指標

uint channel

SCSI 通道 (如果只有一個通道,則為零)

uint id

SCSI 目標編號 (物理單元編號)

u64 lun

SCSI 邏輯單元號

描述

查詢具有指定 channelidlun 的 scsi_device 以用於給定的主機。返回的 scsi_device 有一個額外的引用,一旦您完成使用它,就需要使用 scsi_device_put 釋放該引用。

drivers/scsi/scsicam.c

SCSI 通用訪問方法支援函式,用於 HDIO_GETGEO 等。

unsigned char *scsi_bios_ptable(struct block_device *dev)

從裝置的第一個扇區中讀取 PC 分割槽表。

引數

struct block_device *dev

來自此裝置

描述

從裝置讀取第一個扇區並返回從偏移量 0x1be 開始的 0x42 位元組。

從偏移量 0x1be 開始。

返回

kmalloc(GFP_KERNEL) 記憶體中的分割槽表,如果出錯,則為 NULL。

bool scsi_partsize(struct block_device *bdev, sector_t capacity, int geom[3])

從 PC 分割槽表解析柱面/磁頭/扇區

引數

struct block_device *bdev

要解析的塊裝置

sector_t capacity

磁碟的大小,以扇區為單位

int geom[3]

以 [hds, cylinders, sectors] 形式輸出

描述

確定用於建立分割槽表的 BIOS 對映/幾何圖形,並將結果儲存在 geom 中。

返回

失敗時為 false,成功時為 true

int scsicam_bios_param(struct block_device *bdev, sector_t capacity, int *ip)

確定磁碟的柱面/磁頭/扇區幾何圖形。

引數

struct block_device *bdev

哪個裝置

sector_t capacity

磁碟的大小,以扇區為單位

int *ip

返回值: ip[0]=heads, ip[1]=sectors, ip[2]=cylinders

描述

確定用於 SCSI-CAM 系統中的驅動器的 BIOS 對映/幾何圖形,並將結果儲存在 ip 中,如 HDIO_GETGEO ioctl() 所需。

SCSI-CAM 系統,根據 HDIO_GETGEO ioctl() 的要求,將結果儲存在 ip 中。

返回

失敗時為 -1,成功時為 0。

drivers/scsi/scsi_error.c

常見的 SCSI 錯誤/超時處理例程。

void scsi_schedule_eh(struct Scsi_Host *shost)

為 SCSI 主機安排 EH

引數

struct Scsi_Host *shost

要在其上呼叫錯誤處理的 SCSI 主機。

描述

在沒有 scmd 的情況下安排 SCSI EH。

int scsi_block_when_processing_errors(struct scsi_device *sdev)

防止命令排隊。

引數

struct scsi_device *sdev

我們正在執行恢復的裝置。

描述

我們阻塞直到主機退出錯誤恢復,然後檢查主機或裝置是否離線。

返回值

當裝置因錯誤恢復而離線時,返回 0。1 OK 繼續。

enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd)

檢查 scsi cmd 感知

引數

struct scsi_cmnd *scmd

要檢查感知的 Cmd。

描述

返回值

SUCCESS 或 FAILED 或 NEEDS_RETRY 或 ADD_TO_MLQUEUE

底層驅動程式可以隨時呼叫它,我們將執行

當檢測到延遲錯誤時,當前命令尚未執行,需要重試。

void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, unsigned char *cmnd, int cmnd_size, unsigned sense_bytes)

儲存 scsi 命令資訊作為錯誤恢復的一部分

引數

struct scsi_cmnd *scmd

要劫持的 SCSI 命令結構

struct scsi_eh_save *ses

用於儲存還原資訊的結構

unsigned char *cmnd

要傳送的 CDB。如果不需要新的 cmnd,則可以為 NULL

int cmnd_size

cmnd 的大小(以位元組為單位)(必須 <= MAX_COMMAND_SIZE)

unsigned sense_bytes

要複製的感知資料的大小。或 0(如果 != 0,則忽略 cmnd

描述

此函式用於在重新執行之前儲存 scsi 命令資訊,作為錯誤恢復過程的一部分。如果 sense_bytes 為 0,則傳送的命令必須是不傳輸任何資料的命令。如果 sense_bytes != 0,則忽略 cmnd,並且此函式會設定 REQUEST_SENSE 命令和 cmnd 緩衝區以將 sense_bytes 讀取到 scmd->sense_buffer 中。

void scsi_eh_restore_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses)

作為錯誤恢復的一部分還原 scsi 命令資訊

引數

struct scsi_cmnd* scmd

要還原的 SCSI 命令結構

struct scsi_eh_save *ses

來自對 scsi_eh_prep_cmnd 的相應呼叫的已儲存資訊

描述

撤消上述 scsi_eh_prep_cmnd() 所做的任何損害。

void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)

處理 eh 完成的 cmd。

引數

struct scsi_cmnd *scmd

eh 已完成的原始 SCSI cmd。

struct list_head *done_q

已處理命令的佇列。

底層驅動程式可以隨時呼叫它,我們將執行

我們不想在使用我們仍在處理錯誤時使用正常的命令完成 - 它可能會導致其他命令排隊,這將擾亂我們正在做的事情。因此,我們真的想保留一個待處理命令的列表以進行最終完成,並且一旦我們準備好離開錯誤處理,我們就會真正處理完成。

int scsi_eh_get_sense(struct list_head *work_q, struct list_head *done_q)

獲取裝置感知資料。

引數

struct list_head *work_q

要處理的命令佇列。

struct list_head *done_q

已處理命令的佇列。

描述

看看我們是否需要請求感知資訊。如果是這樣,現在就獲取它,以便我們更好地瞭解該怎麼做。

底層驅動程式可以隨時呼叫它,我們將執行

這會產生不幸的副作用,即如果 shost 介面卡不自動請求感知資訊,我們最終會在請求它之前將其關閉。

所有驅動程式現在都應該在內部請求感知資訊,所以現在我不得不說,如果你最終進入這裡,那你就倒黴了。

XXX: 從長遠來看,此程式碼應該消失,但這需要首先稽核所有 LLDD。

首先是所有 LLDD。

void scsi_eh_ready_devs(struct Scsi_Host *shost, struct list_head *work_q, struct list_head *done_q)

檢查裝置就緒狀態,如果未就緒則恢復。

引數

struct Scsi_Host *shost

要恢復的主機。

struct list_head *work_q

待處理命令的 list_head

struct list_head *done_q

已處理命令的 list_head

void scsi_eh_flush_done_q(struct list_head *done_q)

完成已處理的命令或重試它們。

引數

struct list_head *done_q

已處理命令的 list_head。

void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)

報告觀察到的匯流排重置

引數

struct Scsi_Host *shost

有問題的 Host

int channel

觀察到重置的通道。

描述

底層驅動程式使用的實用程式函式,用於報告它們已在正在處理的總線上觀察到匯流排重置。

鎖定狀態: 必須持有主機鎖。

返回

底層驅動程式可以隨時呼叫它,我們將執行

只有當重置來自未知位置時,才需要呼叫此函式

由中間層本身發起的重置不需要呼叫此函式,但這樣做應該無害。

此函式的主要目的是確保正確處理 CHECK_CONDITION。

void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target)

報告觀察到的裝置重置

引數

struct Scsi_Host *shost

有問題的 Host

int channel

觀察到重置的通道

int target

觀察到重置的目標

描述

底層驅動程式使用的實用程式函式,用於報告它們已在正在處理的裝置上觀察到裝置重置。

鎖定狀態:必須持有主機鎖

返回

底層驅動程式可以隨時呼叫它,我們將執行

只有當重置來自未知位置時,才需要呼叫此函式

由中間層本身發起的重置不需要呼叫此函式,但這樣做應該無害。

此函式的主要目的是確保正確處理 CHECK_CONDITION。

bool scsi_get_sense_info_fld(const u8 *sense_buffer, int sb_len, u64 *info_out)

從 sense 資料(固定格式或描述符格式)獲取資訊欄位

引數

const u8 *sense_buffer

sense 資料的位元組陣列

int sb_len

sense_buffer 中的有效位元組數

u64 *info_out

指向 64 位整數的指標,如果找到 8 位元組或 4 位元組的資訊欄位,則將放置在此處。

描述

返回值

如果找到資訊欄位,則為 true;如果未找到,則為 false。

drivers/scsi/scsi_devinfo.c

管理 scsi_dev_info_list,它跟蹤黑名單和白名單裝置。

int scsi_dev_info_list_add_keyed(int compatible, char *vendor, char *model, char *strflags, blist_flags_t flags, enum scsi_devinfo_key key)

新增一個 dev_info 列表條目。

引數

int compatible

如果為 true,則以 null 結尾短字串。否則,使用空格填充。

char *vendor

供應商字串

char *model

型號(產品)字串

char *strflags

整數字符串

blist_flags_t flags

如果 strflags 為 NULL,則使用此標誌值

enum scsi_devinfo_key key

指定要使用的列表

描述

vendormodelstrflagsflagkey 指定的列表中建立並新增一個 dev_info 條目。如果 compatible,則新增到列表的尾部,不使用空格填充,並設定 devinfo->compatible。 scsi_static_device_list 條目使用 compatible 1 和 clfags NULL 新增。

返回

0 OK,失敗時返回 -error。

blist_flags_t scsi_get_device_flags_keyed(struct scsi_device *sdev, const unsigned char *vendor, const unsigned char *model, enum scsi_devinfo_key key)

從動態裝置列表中獲取裝置特定標誌

引數

struct scsi_device *sdev

要獲取標誌的 scsi_device

const unsigned char *vendor

供應商名稱

const unsigned char *model

型號名稱

enum scsi_devinfo_key key

要查詢的列表

描述

搜尋 key 指定的 scsi_dev_info_list 中與 vendormodel 匹配的條目,如果找到,則返回匹配的標誌值,否則返回主機或全域性預設設定。 在掃描時呼叫。

int scsi_dev_info_add_list(enum scsi_devinfo_key key, const char *name)

新增新的 devinfo 列表

引數

enum scsi_devinfo_key key

要新增的列表的鍵

const char *name

要新增的列表的名稱(用於 /proc/scsi/device_info)

描述

新增請求的列表,成功時返回零,如果該鍵已註冊到列表,則返回 -EEXIST,否則返回其他錯誤。

int scsi_dev_info_remove_list(enum scsi_devinfo_key key)

銷燬新增的 devinfo 列表

引數

enum scsi_devinfo_key key

要銷燬的列表的鍵

描述

首先迭代整個列表,釋放所有值,然後釋放列表本身。 成功時返回 0,如果找不到該鍵,則返回 -EINVAL。

drivers/scsi/scsi_ioctl.c

處理 SCSI 裝置的 ioctl() 呼叫。

int scsi_set_medium_removal(struct scsi_device *sdev, char state)

傳送命令以允許或阻止介質移除

引數

struct scsi_device *sdev

目標 scsi 裝置

char state

要設定的移除狀態(阻止或允許)

返回

  • 如果 sdev 不可移動或不可鎖定或成功,則返回 0

  • 如果 > 0,則非 0 是 SCSI 結果程式碼;如果 < 0,則為核心錯誤程式碼。

  • 成功時,將 sdev->locked 設定為新狀態。

bool scsi_cmd_allowed(unsigned char *cmd, bool open_for_write)

檢查是否允許給定命令。

引數

unsigned char *cmd

要檢查的 SCSI 命令

bool open_for_write

是否為寫入開啟檔案/塊裝置?

描述

只有一部分命令允許非特權使用者使用。 用於格式化介質、更新韌體等的命令是不允許的。

返回

如果允許 cmd,則返回 true,否則返回 false

int scsi_ioctl(struct scsi_device *sdev, bool open_for_write, int cmd, void __user *arg)

將 ioctl 分派到 scsi 裝置

引數

struct scsi_device *sdev

接收 ioctl 的 scsi 裝置

bool open_for_write

是否為寫入開啟檔案/塊裝置?

int cmd

是哪個 ioctl

void __user *arg

與 ioctl 相關的資料

描述

scsi_ioctl() 函式與大多數 ioctl 不同之處在於,它不採用主/次編號作為 dev 欄位。 而是,它採用指向 struct scsi_device 的指標。

返回

cmd 而異

int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev, int cmd, bool ndelay)

防止命令排隊

引數

struct scsi_device *sdev

目標 scsi 裝置

int cmd

是哪個 ioctl

bool ndelay

無延遲(非阻塞)

描述

即使裝置未完全執行,我們也可以處理重置。

返回

成功時返回 0,<0 表示錯誤程式碼。

drivers/scsi/scsi_lib.c

SCSI 佇列庫。

void scsi_failures_reset_retries(struct scsi_failures *failures)

將所有故障重置為零

引數

struct scsi_failures *failures

設定了特定故障模式的 struct scsi_failures

int scsi_execute_cmd(struct scsi_device *sdev, const unsigned char *cmd, blk_opf_t opf, void *buffer, unsigned int bufflen, int timeout, int ml_retries, const struct scsi_exec_args *args)

插入請求並等待結果

引數

struct scsi_device *sdev

scsi_device

const unsigned char *cmd

scsi 命令

blk_opf_t opf

塊層請求 cmd_flags

void *buffer

資料緩衝區

unsigned int bufflen

緩衝區長度

int timeout

以 HZ 為單位的請求超時

int ml_retries

SCSI 中間層將重試請求的次數

const struct scsi_exec_args *args

可選引數。 有關欄位說明,請參閱結構定義

描述

如果執行了命令,則返回 scsi_cmnd 結果欄位;如果未執行命令,則返回負 Linux 錯誤程式碼。

blk_status_t scsi_alloc_sgtables(struct scsi_cmnd *cmd)

分配和初始化資料和完整性散列表

引數

struct scsi_cmnd *cmd

要初始化的 SCSI 命令資料結構。

描述

初始化 cmd->sdb,如果為 cmd 啟用了資料完整性,則還初始化 cmd->prot_sdb

返回

  • BLK_STS_OK - 成功時

  • BLK_STS_RESOURCE - 如果故障可以重試

  • BLK_STS_IOERR - 如果故障是致命的

struct request *scsi_alloc_request(struct request_queue *q, blk_opf_t opf, blk_mq_req_flags_t flags)

分配塊請求並部分初始化其 scsi_cmnd

引數

struct request_queue *q

裝置的請求佇列

blk_opf_t opf

請求操作碼

blk_mq_req_flags_t flags

塊層分配標誌

返回

成功時返回 struct request 指標,失敗時返回 NULL

struct scsi_device *scsi_device_from_queue(struct request_queue *q)

返回與 request_queue 關聯的 sdev

引數

struct request_queue *q

要從中返回 sdev 的請求佇列

描述

返回與請求佇列關聯的 sdev,如果 request_queue 未引用 SCSI 裝置,則返回 NULL。

void scsi_block_requests(struct Scsi_Host *shost)

底層驅動程式使用的實用程式函式,用於防止將更多命令排隊到裝置。

引數

struct Scsi_Host *shost

相關主機

描述

除了底層驅動程式呼叫 scsi_unblock_requests() 之外,沒有任何計時器或其他方法可以解除對請求的阻止。

void scsi_unblock_requests(struct Scsi_Host *shost)

底層驅動程式使用的實用函式,用於允許將更多命令排隊到裝置。

引數

struct Scsi_Host *shost

相關主機

描述

除了底層驅動程式呼叫 scsi_unblock_requests() 之外,沒有任何計時器或其他方法可以解除對請求的阻止。 這樣做是為了作為一個 API 函式,以便對 SCSI 中間層內部的更改不會要求對使用此功能的驅動程式進行大規模更改。

int scsi_mode_select(struct scsi_device *sdev, int pf, int sp, unsigned char *buffer, int len, int timeout, int retries, struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr)

發出模式選擇

引數

struct scsi_device *sdev

要查詢的 SCSI 裝置

int pf

頁面格式位 (1 == 標準,0 == 廠商特定)

int sp

儲存頁面位 (0 == 不儲存,1 == 儲存)

unsigned char *buffer

請求緩衝區 (不得小於 8 個位元組)

int len

請求緩衝區的長度。

int timeout

命令超時

int retries

失敗之前的重試次數

struct scsi_mode_data *data

返回一個抽象模式頭資料的結構

struct scsi_sense_hdr *sshdr

放置 sense 資料的空間 (如果不需要收集 sense 資料,則為 NULL)。必須是 SCSI_SENSE_BUFFERSIZE 大小。

如果成功則返回零;如果出錯,則返回負錯誤號或 SCSI 狀態

int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, int subpage, unsigned char *buffer, int len, int timeout, int retries, struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr)

發出模式感測,如有必要,從 10 位元組回退到 6 位元組。

引數

struct scsi_device *sdev

要查詢的 SCSI 裝置

int dbd

設定以防止模式感測返回塊描述符

int modepage

正在請求的模式頁

int subpage

正在請求的模式頁的子頁

unsigned char *buffer

請求緩衝區 (不得小於 8 個位元組)

int len

請求緩衝區的長度。

int timeout

命令超時

int retries

失敗之前的重試次數

struct scsi_mode_data *data

返回一個抽象模式頭資料的結構

struct scsi_sense_hdr *sshdr

放置 sense 資料的空間 (如果不需要收集 sense 資料,則為 NULL)。必須是 SCSI_SENSE_BUFFERSIZE 大小。

如果成功則返回零,如果失敗則返回負錯誤號

int scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries, struct scsi_sense_hdr *sshdr)

測試單元是否就緒

引數

struct scsi_device *sdev

要更改狀態的 SCSI 裝置。

int timeout

命令超時

int retries

失敗之前的重試次數

struct scsi_sense_hdr *sshdr

解碼後的 sense 資訊的輸出指標。

如果 TUR 失敗,則返回零表示不成功,否則返回錯誤。 對於可移動介質,UNIT_ATTENTION 設定 ->changed 標誌。

int scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)

使給定的裝置透過裝置狀態模型。

引數

struct scsi_device *sdev

要更改狀態的 SCSI 裝置。

enum scsi_device_state state

要更改為的狀態。

如果成功則返回零,如果請求的轉換是非法的則返回錯誤。

void sdev_evt_send(struct scsi_device *sdev, struct scsi_event *evt)

將斷言的事件傳送到 uevent 執行緒

引數

struct scsi_device *sdev

scsi_device 上發生的事件

struct scsi_event *evt

要傳送的事件

非同步斷言 SCSI 裝置事件。

struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type, gfp_t gfpflags)

分配一個新的 SCSI 事件

引數

enum scsi_device_event evt_type

要分配的事件型別

gfp_t gfpflags

用於分配的 GFP 標誌

分配並返回一個新的 scsi_event。

void sdev_evt_send_simple(struct scsi_device *sdev, enum scsi_device_event evt_type, gfp_t gfpflags)

將斷言的事件傳送到 uevent 執行緒

引數

struct scsi_device *sdev

scsi_device 上發生的事件

enum scsi_device_event evt_type

要傳送的事件型別

gfp_t gfpflags

用於分配的 GFP 標誌

非同步斷言 SCSI 裝置事件,給定事件型別。

int scsi_device_quiesce(struct scsi_device *sdev)

阻止除電源管理之外的所有命令。

引數

struct scsi_device *sdev

要暫停的 SCSI 裝置。

這透過嘗試轉換到 SDEV_QUIESCE 狀態 (必須是合法的轉換) 來實現。 當裝置處於此狀態時,只會接受電源管理請求,所有其他請求將被延遲。

必須使用使用者上下文呼叫,可能會休眠。

如果成功則返回零,如果失敗則返回錯誤。

void scsi_device_resume(struct scsi_device *sdev)

重新啟動已暫停裝置的使用者發出的命令。

引數

struct scsi_device *sdev

要恢復的 SCSI 裝置。

將裝置從暫停狀態移動回執行狀態並重新啟動佇列。

必須使用使用者上下文呼叫,可能會休眠。

int scsi_internal_device_block_nowait(struct scsi_device *sdev)

嘗試轉換到 SDEV_BLOCK 狀態

引數

struct scsi_device *sdev

要阻止的裝置

描述

暫停指定裝置上的 SCSI 命令處理。 不會休眠。

如果成功則返回零,如果失敗則返回負錯誤程式碼。

底層驅動程式可以隨時呼叫它,我們將執行

此例程將裝置轉換到 SDEV_BLOCK 狀態 (必須是合法的轉換)。 當裝置處於此狀態時,命令處理將被暫停,直到裝置離開 SDEV_BLOCK 狀態。 另請參閱 scsi_internal_device_unblock_nowait()

int scsi_internal_device_unblock_nowait(struct scsi_device *sdev, enum scsi_device_state new_state)

在阻止請求後恢復裝置

引數

struct scsi_device *sdev

要恢復的裝置

enum scsi_device_state new_state

取消阻止後要將裝置設定為的狀態

描述

重新啟動先前暫停的 SCSI 裝置的裝置佇列。 不會休眠。

如果成功則返回零,如果失敗則返回負錯誤程式碼。

底層驅動程式可以隨時呼叫它,我們將執行

此例程將裝置轉換到 SDEV_RUNNING 狀態或其中一個離線狀態 (必須是合法的轉換),允許中間層推動此裝置的佇列。

void scsi_block_targets(struct Scsi_Host *shost, struct device *dev)

將所有 SCSI 子裝置轉換到 SDEV_BLOCK 狀態

引數

struct Scsi_Host *shost

此裝置所屬的 Scsi_Host

struct device *dev

一個或多個 scsi_target 裝置的父裝置

描述

迭代 **dev** 的所有子裝置,這些子裝置應該是 scsi_target 裝置,並將所有下級 SCSI 裝置切換到 SDEV_BLOCK 狀態。 等待正在進行的 scsi_queue_rq() 呼叫完成。 可能會休眠。

注意

**dev** 本身不得是 scsi_target 裝置。

int scsi_host_block(struct Scsi_Host *shost)

嘗試將所有邏輯單元轉換到 SDEV_BLOCK 狀態

引數

struct Scsi_Host *shost

要阻止的裝置

描述

暫停與 SCSI 主機關聯的所有邏輯單元的 SCSI 命令處理,並等待掛起的 scsi_queue_rq() 呼叫完成。

如果成功則返回零,如果失敗則返回負錯誤程式碼。

void *scsi_kmap_atomic_sg(struct scatterlist *sgl, int sg_count, size_t *offset, size_t *len)

查詢並原子地對映一個 sg 元素

引數

struct scatterlist *sgl

分散-聚集列表

int sg_count

sg 中的段數

size_t *offset

sg 中的位元組偏移量,返回時為對映區域中的偏移量

size_t *len

要對映的位元組數,返回時為對映的位元組數

描述

返回對映頁面開始的虛擬地址

void scsi_kunmap_atomic_sg(void *virt)

原子地取消對映一個虛擬地址,該地址先前已使用 scsi_kmap_atomic_sg 對映

引數

void *virt

要取消對映的虛擬地址

int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len)

返回唯一的裝置標識

引數

struct scsi_device *sdev

SCSI 裝置

char *id

標識的緩衝區

size_t id_len

緩衝區的長度

描述

基於裝置 VPD 頁面 0x83 中的資訊,將唯一的裝置標識複製到 **id** 中。 該字串將格式化為 SCSI 名稱字串。

如果成功,則返回標識的長度,如果失敗,則返回錯誤。 如果識別符號長於提供的緩衝區,則返回實際的識別符號長度,並且緩衝區不會被零填充。

int scsi_vpd_tpg_id(struct scsi_device *sdev, int *rel_id)

返回目標埠組識別符號

引數

struct scsi_device *sdev

SCSI 裝置

int *rel_id

指向返回相對目標埠的指標 (如果不是 NULL)

描述

從裝置的 VPD 頁面 0x83 中的資訊返回目標埠組識別符號。 (可選)成功時將 **rel_id** 設定為相對目標埠。

返回

識別符號,如果失敗,則返回錯誤。

void scsi_build_sense(struct scsi_cmnd *scmd, int desc, u8 key, u8 asc, u8 ascq)

為命令構建 sense 資料

引數

struct scsi_cmnd *scmd

應為其格式化 sense 資料的 scsi 命令

int desc

Sense 格式(非零 == 描述符格式, 0 == 固定格式)

u8 key

Sense 鍵

u8 asc

附加 sense 程式碼

u8 ascq

附加 sense 程式碼限定符

drivers/scsi/scsi_lib_dma.c

依賴於 DMA 的 SCSI 庫函式 (對映和取消對映 scatter-gather 列表).

int scsi_dma_map(struct scsi_cmnd *cmd)

針對命令的 sg 列表執行 DMA 對映

引數

struct scsi_cmnd *cmd

scsi 命令

描述

返回實際使用的 sg 列表數量,如果 sg 列表為 NULL 則返回 0,如果對映失敗則返回 -ENOMEM。

void scsi_dma_unmap(struct scsi_cmnd *cmd)

取消對映 scsi_dma_map 對映的命令 sg 列表

引數

struct scsi_cmnd *cmd

scsi 命令

drivers/scsi/scsi_proc.c

此檔案中的函式提供 PROC 檔案系統和 SCSI 裝置驅動程式之間的介面。它主要用於除錯、統計以及將資訊直接傳遞到低階驅動程式。例如,用於管理 /proc/scsi/*

struct scsi_proc_entry

(主機模板,SCSI proc 目錄) 關聯

定義:

struct scsi_proc_entry {
    struct list_head        entry;
    const struct scsi_host_template *sht;
    struct proc_dir_entry   *proc_dir;
    unsigned int            present;
};

成員

條目

scsi_proc_list 中的條目。

sht

與 procfs 目錄關聯的 SCSI 主機模板。

proc_dir

與 SCSI 主機模板關聯的 procfs 目錄。

present

sht 例項化的 SCSI 主機的數量。

struct proc_dir_entry *scsi_template_proc_dir(const struct scsi_host_template *sht)

返回 SCSI 主機模板的 procfs 目錄

引數

const struct scsi_host_template *sht

SCSI 主機模板指標。

int scsi_proc_hostdir_add(const struct scsi_host_template *sht)

在 /proc 中為 scsi 主機建立目錄

引數

const struct scsi_host_template *sht

此目錄的所有者

描述

將 sht->proc_dir 設定為新目錄。

void scsi_proc_hostdir_rm(const struct scsi_host_template *sht)

刪除 /proc 中 scsi 主機的目錄

引數

const struct scsi_host_template *sht

目錄的所有者

void scsi_proc_host_add(struct Scsi_Host *shost)

將此主機的條目新增到相應的 /proc 目錄

引數

struct Scsi_Host *shost

要新增的主機

void scsi_proc_host_rm(struct Scsi_Host *shost)

從 /proc 中刪除此主機的條目

引數

struct Scsi_Host *shost

哪個主機

int proc_print_scsidevice(struct device *dev, void *data)

返回有關此主機的資料

引數

struct device *dev

一個 scsi 裝置

void *data

要輸出到的 struct seq_file

描述

列印主機、通道、Id、Lun、供應商、型號、版本、型別和修訂。

int scsi_add_single_device(uint host, uint channel, uint id, uint lun)

響應使用者探測/新增裝置請求

引數

uint host

使用者提供的十進位制整數

uint channel

使用者提供的十進位制整數

uint id

使用者提供的十進位制整數

uint lun

使用者提供的十進位制整數

描述

透過寫入“scsi add-single-device”到 /proc/scsi/scsi 來呼叫。

執行 scsi_host_lookup(),如果該傳輸型別支援,則執行 user_scan(),否則執行 scsi_scan_host_selected()

注意

這似乎專門針對 SCSI 並行匯流排。

int scsi_remove_single_device(uint host, uint channel, uint id, uint lun)

響應使用者刪除裝置請求

引數

uint host

使用者提供的十進位制整數

uint channel

使用者提供的十進位制整數

uint id

使用者提供的十進位制整數

uint lun

使用者提供的十進位制整數

描述

透過寫入“scsi remove-single-device”到 /proc/scsi/scsi 來呼叫。執行 scsi_device_lookup()scsi_remove_device()

ssize_t proc_scsi_write(struct file *file, const char __user *buf, size_t length, loff_t *ppos)

處理寫入 /proc/scsi/scsi 的操作

引數

struct file *file

未使用

const char __user *buf

要寫入的緩衝區

size_t length

buf 的長度,最多 PAGE_SIZE

loff_t *ppos

未使用

描述

這提供了一種傳統機制,用於按主機、通道、ID 和 Lun 新增或刪除裝置。要使用,請執行“echo ‘scsi add-single-device 0 1 2 3’ > /proc/scsi/scsi”或“echo ‘scsi remove-single-device 0 1 2 3’ > /proc/scsi/scsi”,其中“0 1 2 3”替換為主機、通道、Id 和 Lun。

注意

這似乎針對並行 SCSI。大多數現代匯流排(USB、SATA、Firewire、光纖通道等)動態分配這些值,以提供一個唯一識別符號,僅此而已。

int proc_scsi_open(struct inode *inode, struct file *file)

粘合函式

引數

struct inode *inode

未使用

struct file *file

傳遞給 single_open()

描述

將 proc_scsi_show 與此檔案關聯

int scsi_init_procfs(void)

在 procfs 中建立 scsi 和 scsi/scsi

引數

void

無引數

void scsi_exit_procfs(void)

從 procfs 中刪除 scsi/scsi 和 scsi

引數

void

無引數

drivers/scsi/scsi_scan.c

掃描主機以確定連線了哪些(如果有)裝置。一般的掃描/探測演算法如下,根據裝置特定標誌、編譯選項和全域性變數(啟動或模組載入時間)設定對其進行例外處理。透過 INQUIRY 命令掃描特定 LUN;如果 LUN 連線了裝置,則會為此分配並設定一個 scsi_device。對於給定主機上每個通道的每個 id,首先掃描 LUN 0。跳過根本不響應 LUN 0 掃描的主機。否則,如果 LUN 0 連線了裝置,則為其分配並設定一個 scsi_device。如果目標是 SCSI-3 或更高版本,則發出 REPORT LUN,並掃描 REPORT LUN 返回的所有 LUN;否則,按順序掃描 LUN,直到達到某個最大值,或者看到一個無法連線裝置的 LUN。

void scsi_sanitize_inquiry_string(unsigned char *s, int len)

從 INQUIRY 結果字串中刪除非圖形字元

引數

unsigned char *s

要清理的 INQUIRY 結果字串

int len

字串的長度

描述

SCSI 規範規定,INQUIRY 供應商、產品和版本字串必須完全由圖形 ASCII 字元組成,並在右側用空格填充。由於並非所有裝置都遵守此規則,因此我們將用空格替換非圖形或非 ASCII 字元。例外:NUL 字元被解釋為字串終止符,因此所有後續字元都設定為空格。

int scsi_add_device(struct Scsi_Host *host, uint channel, uint target, u64 lun)

建立新的 SCSI (LU) 例項

引數

struct Scsi_Host *host

裝置所在的 Scsi_Host 例項

uint channel

目標通道號(很少不是 0

uint target

目標 id 號

u64 lun

目標裝置的 LUN

描述

探測特定 LUN 並在找到時新增它。

底層驅動程式可以隨時呼叫它,我們將執行

此呼叫通常在新增 HBA 時在 SCSI 匯流排掃描期間在內部執行(即 scsi_scan_host())。因此,只有在 HBA 在 scsi_scan_host() 完成後意識到新的 SCSI 裝置 (LU) 時,才應呼叫它。如果成功,此呼叫可能會導致 sdev_init() 和 sdev_configure() 回撥到 LLD。

返回

成功時返回 0,失敗時返回負錯誤程式碼

void scsi_scan_target(struct device *parent, unsigned int channel, unsigned int id, u64 lun, enum scsi_scan_mode rescan)

掃描目標 id,可能包括目標上的所有 LUN。

引數

struct device *parent

要掃描的主機

unsigned int channel

要掃描的通道

unsigned int id

要掃描的目標 ID

u64 lun

要掃描的特定 LUN,或 SCAN_WILD_CARD

enum scsi_scan_mode rescan

傳遞給 LUN 掃描例程;SCSI_SCAN_INITIAL 表示不重新掃描,SCSI_SCAN_RESCAN 表示重新掃描現有 LUN,SCSI_SCAN_MANUAL 表示強制掃描,即使設定了“scan=manual”。

描述

掃描 **parent**、**channel** 和 **id** 上的目標 ID。至少掃描 LUN 0,可能掃描目標 ID 上的所有 LUN。

首先嚐試 REPORT LUN 掃描,如果這樣無法掃描目標,則對目標 ID 上的 LUN 進行順序掃描。

void scsi_scan_host(struct Scsi_Host *shost)

掃描給定的介面卡

引數

struct Scsi_Host *shost

要掃描的介面卡

底層驅動程式可以隨時呼叫它,我們將執行

應在 scsi_add_host() 之後呼叫

drivers/scsi/scsi_sysctl.c

設定 sysctl 條目:“/dev/scsi/logging_level”(DEV_SCSI_LOGGING_LEVEL),用於設定/返回 scsi_logging_level。

drivers/scsi/scsi_sysfs.c

SCSI sysfs 介面例程。

void scsi_remove_device(struct scsi_device *sdev)

從 SCSI 總線上登出裝置

引數

struct scsi_device *sdev

要登出的 scsi_device

void scsi_remove_target(struct device *dev)

嘗試刪除目標及其所有裝置

引數

struct device *dev

要刪除的通用 starget 或通用 starget 的父級

注意

這有點競爭。如果使用者請求新增另一個裝置,則可能無法刪除目標。

drivers/scsi/hosts.c

中間層到低層 SCSI 驅動程式介面

void scsi_remove_host(struct Scsi_Host *shost)

刪除 SCSI 主機

引數

struct Scsi_Host *shost

要刪除的 SCSI 主機的指標

int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, struct device *dma_dev)

新增帶有 DMA 裝置的 SCSI 主機

引數

struct Scsi_Host *shost

要新增的 SCSI 主機指標

struct device *dev

scsi 類型別的 struct device

struct device *dma_dev

主機的 DMA 裝置

注意

除非您處於虛擬化主機環境中,否則您很少需要擔心這一點,因此請使用更簡單的 scsi_add_host() 函式。

描述

返回值

成功時為 0 / 錯誤時為 != 0

struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int privsize)

註冊 SCSI 主機介面卡例項。

引數

const struct scsi_host_template *sht

SCSI 主機模板的指標

int privsize

為驅動程式分配的額外位元組

注意

分配新的 Scsi_Host 並執行基本初始化。在呼叫 scsi_add_host 之前,不會將主機發布到 SCSI 中間層。

描述

返回值

指向新的 Scsi_Host 的指標

struct Scsi_Host *scsi_host_lookup(unsigned int hostnum)

按主機號獲取對 Scsi_Host 的引用

引數

unsigned int hostnum

要查詢的主機號

描述

返回值

指向已定位的 Scsi_Host 的指標,如果找不到則為 NULL。

呼叫者必須執行 scsi_host_put() 以刪除 scsi_host_get() 採用的引用。下面的 put_device() 刪除了來自 class_find_device() 的引用。

struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost)

增加 Scsi_Host 引用計數

引數

struct Scsi_Host *shost

指向要增加的 Scsi_Host 的指標。

int scsi_host_busy(struct Scsi_Host *shost)

返回主機忙碌計數器

引數

struct Scsi_Host *shost

指向要增加的 Scsi_Host 的指標。

void scsi_host_put(struct Scsi_Host *shost)

減少 Scsi_Host 引用計數

引數

struct Scsi_Host *shost

指向要減少的 Scsi_Host 的指標。

int scsi_queue_work(struct Scsi_Host *shost, struct work_struct *work)

將工作排隊到 Scsi_Host 工作佇列。

引數

struct Scsi_Host *shost

指向 Scsi_Host 的指標。

struct work_struct *work

要排隊執行的工作。

描述

返回值

1 - 工作已排隊等待執行 0 - 工作已排隊 -EINVAL - 工作佇列不存在

void scsi_flush_work(struct Scsi_Host *shost)

重新整理 Scsi_Host 的工作佇列。

引數

struct Scsi_Host *shost

指向 Scsi_Host 的指標。

void scsi_host_complete_all_commands(struct Scsi_Host *shost, enum scsi_host_status status)

終止所有正在執行的命令

引數

struct Scsi_Host *shost

應終止命令的 SCSI 主機

enum scsi_host_status status

為終止的命令設定的狀態

描述

沒有針對修改未完成命令數的保護。呼叫者有責任確保在呼叫此函式時停止併發 I/O 提交和/或完成。

void scsi_host_busy_iter(struct Scsi_Host *shost, bool (*fn)(struct scsi_cmnd*, void*), void *priv)

迭代所有忙碌命令

引數

struct Scsi_Host *shost

指向 Scsi_Host 的指標。

bool (*fn)(struct scsi_cmnd *, void *)

在每個忙碌命令上呼叫的函式

void *priv

傳遞給 **fn** 的資料指標

描述

如果需要鎖定以防止併發命令完成,則必須由呼叫者提供

drivers/scsi/scsi_common.c

通用支援函式

const char *scsi_device_type(unsigned type)

返回指示裝置型別的 17 字元字串。

引數

unsigned type

要查詢的型別編號

u64 scsilun_to_int(struct scsi_lun *scsilun)

將 scsi_lun 轉換為 int

引數

struct scsi_lun *scsilun

要轉換的 struct scsi_lun。

描述

將 **scsilun** 從 struct scsi_lun 轉換為四位元組的主機位元組序整數,並返回結果。呼叫者在使用此函式之前必須檢查截斷。

底層驅動程式可以隨時呼叫它,我們將執行

有關 LUN 格式的描述,請參閱 SCSI-3 後的 SCSI 架構模型,有關 SCSI-3 請參閱 SCSI 控制器命令。

給定一個 struct scsi_lun:d2 04 0b 03 00 00 00 00,此函式返回整數:0x0b03d204

對於小於 256 的 LUN,此編碼將返回標準整數 LUN,通常使用定址方法 0 的單級 LUN 結構。

void int_to_scsilun(u64 lun, struct scsi_lun *scsilun)

將 int 恢復為 scsi_lun

引數

u64 lun

要恢復的整數

struct scsi_lun *scsilun

要設定的 struct scsi_lun。

描述

恢復 scsilun_to_int 的功能,它將 8 位元組的 LUN 值打包到 int 中。此例程將 int 解包回 LUN 值。

底層驅動程式可以隨時呼叫它,我們將執行

給定一個整數:0x0b03d204,此函式返回一個 struct scsi_lun:d2 04 0b 03 00 00 00 00

bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, struct scsi_sense_hdr *sshdr)

將固定或描述符錯誤資料格式中的主要元素規範化為通用格式。

引數

const u8 *sense_buffer

包含裝置返回的錯誤資料的位元組陣列

int sb_len

sense_buffer 中的有效位元組數

struct scsi_sense_hdr *sshdr

指向將寫入公共元素的結構例項的指標。

底層驅動程式可以隨時呼叫它,我們將執行

來自錯誤資料的“主要元素”是:response_code、sense_key、asc、ascq 和 additional_length(僅適用於描述符格式)。

通常,可以在裝置使用 CHECK_CONDITION 狀態響應 SCSI 命令後呼叫此函式。

描述

返回值

如果找到有效的錯誤資料資訊,則為 true,否則為 false;

const u8 *scsi_sense_desc_find(const u8 *sense_buffer, int sb_len, int desc_type)

在描述符錯誤資料格式中搜索給定的描述符型別。

引數

const u8 * sense_buffer

描述符格式錯誤資料的位元組陣列

int sb_len

sense_buffer 中的有效位元組數

int desc_type

要查詢的描述符型別的值(例如,0 -> 資訊)

底層驅動程式可以隨時呼叫它,我們將執行

僅當錯誤資料採用描述符格式時才有效

描述

返回值

指向找到的(第一個)描述符的開始位置的指標,否則為 NULL

void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq)

在緩衝區中構建錯誤資料

引數

int desc

Sense 格式(非零 == 描述符格式, 0 == 固定格式)

u8 *buf

在何處構建錯誤資料

u8 key

Sense 鍵

u8 asc

附加 sense 程式碼

u8 ascq

附加 sense 程式碼限定符

int scsi_set_sense_information(u8 *buf, int buf_len, u64 info)

在格式化的錯誤資料緩衝區中設定資訊欄位

引數

u8 *buf

在何處構建錯誤資料

int buf_len

緩衝區長度

u64 info

要設定的 64 位資訊值

描述

返回值

成功時為 0,無效錯誤緩衝區長度時為 -EINVAL

int scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd)

在格式化的 sense 資料緩衝區中設定欄位指標 sense key 特定資訊

引數

u8 *buf

在何處構建錯誤資料

int buf_len

緩衝區長度

u16 fp

要設定的欄位指標

u8 bp

要設定的位指標

bool cd

命令/資料位

描述

返回值

成功時為 0,無效錯誤緩衝區長度時為 -EINVAL

傳輸類

傳輸類是 SCSI 下層驅動程式的 service 庫,可在 sysfs 中公開傳輸屬性。

光纖通道傳輸

檔案 drivers/scsi/scsi_transport_fc.c 定義了光纖通道的傳輸屬性。

u32 fc_get_event_number(void)

獲取下一個連續的 FC 事件編號

引數

void

無引數

底層驅動程式可以隨時呼叫它,我們將執行

我們可以內聯這個,但這需要公開 fc_event_seq。目前,暫時使用子例程呼叫。使用 Atomic 避免鎖定/解鎖...

void fc_host_post_fc_event(struct Scsi_Host *shost, u32 event_number, enum fc_host_event_code event_code, u32 data_len, char *data_buf, u64 vendor_id)

在 fc_host 上釋出事件的例程。

引數

struct Scsi_Host *shost

事件發生的主機

u32 event_number

從 get_fc_event_number() 獲取的 fc 事件編號

enum fc_host_event_code event_code

正在釋出的 fc_host 事件

u32 data_len

事件資料量,以位元組為單位

char *data_buf

指向事件資料的指標

u64 vendor_id

供應商 ID 的值

底層驅動程式可以隨時呼叫它,我們將執行

此例程假定入口處沒有持有鎖。

void fc_host_post_event(struct Scsi_Host *shost, u32 event_number, enum fc_host_event_code event_code, u32 event_data)

呼叫以在 fc_host 上釋出 even。

引數

struct Scsi_Host *shost

事件發生的主機

u32 event_number

從 get_fc_event_number() 獲取的 fc 事件編號

enum fc_host_event_code event_code

正在釋出的 fc_host 事件

u32 event_data

正在釋出的事件的 32 位資料

底層驅動程式可以隨時呼叫它,我們將執行

此例程假定入口處沒有持有鎖。

void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number, u32 data_len, char *data_buf, u64 vendor_id)

呼叫以在 fc_host 上釋出廠商唯一事件

引數

struct Scsi_Host *shost

事件發生的主機

u32 event_number

從 get_fc_event_number() 獲取的 fc 事件編號

u32 data_len

廠商唯一資料的數量,以位元組為單位

char * data_buf

指向廠商唯一資料的指標

u64 vendor_id

廠商 ID

底層驅動程式可以隨時呼叫它,我們將執行

此例程假定入口處沒有持有鎖。

struct fc_rport *fc_find_rport_by_wwpn(struct Scsi_Host *shost, u64 wwpn)

查詢給定 wwpn 的 fc_rport 指標

引數

struct Scsi_Host *shost

fc_rport 相關聯的主機

u64 wwpn

fc_rport 裝置的 wwpn

底層驅動程式可以隨時呼叫它,我們將執行

此例程假定入口處沒有持有鎖。

void fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf, u8 event_acknowledge)

處理收到的 FPIN 的例程。

引數

struct Scsi_Host *shost

收到 FPIN 的主機

u32 fpin_len

FPIN 有效負載的長度,以位元組為單位

char *fpin_buf

指向 FPIN 有效負載的指標

u8 event_acknowledge

如果 LLDD 處理此事件,則為 1。

底層驅動程式可以隨時呼叫它,我們將執行

此例程假定入口處沒有持有鎖。

enum scsi_timeout_action fc_eh_timed_out(struct scsi_cmnd *scmd)

FC 傳輸 I/O 超時攔截處理程式

引數

struct scsi_cmnd *scmd

超時的 SCSI 命令

描述

此例程可以防止在 rport 處於阻止狀態時呼叫錯誤處理程式,通常是由於暫時失去連線。 如果允許錯誤處理程式繼續,則中止 i/o、重置目標等請求很可能會失敗,因為無法與裝置通訊以執行所請求的功能。 這些故障可能導致中間層使裝置離線,需要手動干預才能恢復操作。

此例程在 i/o 超時時呼叫,用於驗證底層 rport 的狀態。 如果 rport 被阻止,它將返回 EH_RESET_TIMER,這將繼續重新安排超時。 最終,裝置將返回,或者 devloss_tmo 將觸發,並且當超時觸發時,它將被正常處理。 如果 rport 未被阻止,則繼續正常錯誤處理。

底層驅動程式可以隨時呼叫它,我們將執行

此例程假定入口處沒有持有鎖。

void fc_remove_host(struct Scsi_Host *shost)

呼叫以終止 scsi 主機的任何 fc_transport 相關元素。

引數

struct Scsi_Host *shost

哪個 Scsi_Host

描述

預計此例程將在驅動程式呼叫 scsi_remove_host() 之前立即呼叫。

警告:使用 fc_transport 的驅動程式,如果未能呼叫

scsi_remove_host() 之前執行此例程,將會在 /sys/class/fc_remote_ports 中留下懸掛物件。 訪問任何這些物件都可能導致系統崩潰!!!

底層驅動程式可以隨時呼叫它,我們將執行

此例程假定入口處沒有持有鎖。

struct fc_rport *fc_remote_port_add(struct Scsi_Host *shost, int channel, struct fc_rport_identifiers *ids)

通知 fc 傳輸遠端 FC 埠的存在。

引數

struct Scsi_Host *shost

遠端埠連線到的 scsi 主機。

int channel

連線到的 shost 埠上的通道。

struct fc_rport_identifiers *ids

遠端埠的全球通用名稱、fc 地址和 FC4 埠角色。

描述

LLDD 呼叫此例程以通知傳輸遠端埠的存在。 LLDD 提供埠的唯一識別符號(wwpn、wwn)、其 FC 地址 (port_id) 以及埠的活動 FC4 角色。

對於作為 FCP 目標(又稱 scsi 目標)的埠,FC 傳輸代表 LLDD 維護一致的目標 ID 繫結。 一致的目標 ID 繫結是將目標 ID 分配給遠端埠識別符號,只要 scsi 主機已連線,該繫結就會持續存在。 遠端埠可以消失,然後稍後重新出現,其目標 ID 分配保持不變。 這允許 FC 定址的轉變(如果透過 wwpn 或 wwnn 繫結),而 scsi 子系統沒有任何明顯的變化,scsi 子系統基於 scsi 主機編號和目標 ID 值。 繫結僅在 scsi 主機連線期間有效。 如果主機分離,然後稍後重新連線,則目標 ID 繫結可能會更改。

此例程負責返回遠端埠結構。 此例程將搜尋代表一致目標 ID 對映在內部維護的遠端埠列表。 如果找到,則將重用遠端埠結構。 否則,將分配一個新的遠端埠結構。

每當分配遠端埠時,都會建立一個新的 fc_remote_port 類裝置。

不應從中斷上下文呼叫。

底層驅動程式可以隨時呼叫它,我們將執行

此例程假定入口處沒有持有鎖。

void fc_remote_port_delete(struct fc_rport *rport)

通知 fc 傳輸遠端埠不再存在。

引數

struct fc_rport *rport

不再存在的遠端埠

描述

LLDD 呼叫此例程以通知傳輸遠端埠不再是拓撲的一部分。 注意:雖然埠可能不再是拓撲的一部分,但它可能仍然存在於 fc_host 顯示的遠端埠中。 我們在 2 種情況下執行此操作

  1. 如果埠是 scsi 目標,我們會透過“阻止”它來延遲其刪除。 這允許埠暫時消失,然後重新出現,而不會中斷連線到它的 SCSI 裝置樹。 在“阻止”期間,埠仍將存在。

  2. 如果埠是 scsi 目標並且消失的時間超過我們的預期,我們將刪除該埠並拆除連線到它的 SCSI 裝置樹。 但是,我們希望在最終存在的情況下半持久分配給該埠的目標 ID。 埠結構將保留(儘管資訊最少),以便目標 ID 繫結也保留。

如果遠端埠不是 FCP 目標,它將被完全拆除和釋放,包括 fc_remote_port 類裝置。

如果遠端埠是 FCP 目標,該埠將被置於臨時阻止狀態。 從 LLDD 的角度來看,rport 不再存在。 從 SCSI 中間層的角度來看,SCSI 目標存在,但它上面的所有 sdev 都被阻止進行進一步的 I/O。 然後預期以下情況。

如果遠端埠未在 dev_loss_tmo 超時內返回(透過 LLDD 呼叫 fc_remote_port_add() 發出訊號),則刪除 scsi 目標 - 終止所有未完成的 i/o 並刪除連線到它的 scsi 裝置。 埠結構將被標記為不存在並被部分清除,僅留下足夠的資訊來識別相對於 scsi 目標 ID 繫結的遠端埠(如果它稍後出現)。 只要存在有效的繫結(例如,直到使用者更改繫結型別或解除安裝帶有繫結的 scsi 主機),埠將保持原樣。

如果遠端埠在 dev_loss_tmo 值內返回(並根據目標 ID 繫結型別匹配),則將重用埠結構。 如果它不再是 SCSI 目標,則目標將被拆除。 如果它繼續是 SCSI 目標,則目標將被解除阻止(允許恢復 i/o),並且將啟用掃描以確保檢測到所有 lun。

僅從正常程序上下文呼叫 - 不能從中斷呼叫。

底層驅動程式可以隨時呼叫它,我們將執行

此例程假定入口處沒有持有鎖。

void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)

通知 fc 傳輸遠端埠上的角色可能已更改。

引數

struct fc_rport *rport

已更改的遠端埠。

u32 roles

此埠的新角色。

描述

LLDD 呼叫此例程以通知傳輸遠端埠上的角色可能已更改。 最大的影響是,如果埠現在變為 FCP 目標,則必須為其分配 scsi 目標 ID。 如果埠不再是 FCP 目標,則分配給它的任何 scsi 目標 ID 值都將保留,以防角色更改回包括 FCP 目標。 如果角色發生變化(期望角色將被恢復),則不會呼叫 scsi 中間層的任何更改。 如果不這樣做,將進行正常的錯誤處理。

不應從中斷上下文呼叫。

底層驅動程式可以隨時呼叫它,我們將執行

此例程假定入口處沒有持有鎖。

int fc_block_rport(struct fc_rport *rport)

阻止用於阻止的 fc_rport 的 SCSI eh 執行緒。

引數

struct fc_rport *rport

scsi_eh 嘗試恢復的遠端埠。

描述

可以從 FC LLD scsi_eh 回撥呼叫此例程。 它會阻止 scsi_eh 執行緒,直到 fc_rport 離開 FC_PORTSTATE_BLOCKED 狀態或觸發 fast_io_fail_tmo。 這對於避免 scsi_eh 無法執行阻止的 rport 的恢復操作是必要的,這會導致 SCSI 裝置離線。

返回

如果 fc_rport 離開 FC_PORTSTATE_BLOCKED 狀態,則為 0。

如果觸發了 fast_io_fail_tmo,則為 FAST_IO_FAIL,應將其傳遞迴 scsi_eh。

int fc_block_scsi_eh(struct scsi_cmnd *cmnd)

阻止用於阻止的 fc_rport 的 SCSI eh 執行緒

引數

struct scsi_cmnd *cmnd

scsi_eh 嘗試恢復的 SCSI 命令

描述

可以從 FC LLD scsi_eh 回撥呼叫此例程。 它會阻止 scsi_eh 執行緒,直到 fc_rport 離開 FC_PORTSTATE_BLOCKED 狀態或觸發 fast_io_fail_tmo。 這對於避免 scsi_eh 無法執行阻止的 rport 的恢復操作是必要的,這會導致 SCSI 裝置離線。

返回

如果 fc_rport 離開 FC_PORTSTATE_BLOCKED 狀態,則為 0。

如果觸發了 fast_io_fail_tmo,則為 FAST_IO_FAIL,應將其傳遞迴 scsi_eh。

struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel, struct fc_vport_identifiers *ids)

管理應用程式或 LLDD 請求建立 vport

引數

struct Scsi_Host *shost

虛擬埠連線到的 scsi 主機。

int channel

連線到的 shost 埠上的通道。

struct fc_vport_identifiers *ids

虛擬埠的全球通用名稱、FC4 埠角色等。

底層驅動程式可以隨時呼叫它,我們將執行

此例程假定入口處沒有持有鎖。

int fc_vport_terminate(struct fc_vport *vport)

管理應用程式或 LLDD 請求終止 vport

引數

struct fc_vport *vport

要終止的 fc_vport

描述

呼叫 LLDD vport_delete() 函式,然後從 shost 和物件樹中釋放並刪除 vport。

底層驅動程式可以隨時呼叫它,我們將執行

此例程假定入口處沒有持有鎖。

iSCSI 傳輸類

檔案 drivers/scsi/scsi_transport_iscsi.c 定義了 iSCSI 類的傳輸屬性,該類透過 TCP/IP 連線傳送 SCSI 資料包。

struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)

從控制代碼獲取 ep

引數

u64 handle

端點控制代碼

描述

呼叫方必須執行 iscsi_put_endpoint。

struct iscsi_bus_flash_session *iscsi_create_flashnode_sess(struct Scsi_Host *shost, int index, struct iscsi_transport *transport, int dd_size)

在sysfs中新增 flashnode 會話條目

引數

struct Scsi_Host *shost

指向主機資料的指標

int index

要在sysfs中新增的 flashnode 的索引

struct iscsi_transport *transport

指向傳輸資料的指標

int dd_size

要分配的總大小

描述

為 flashnode 會話屬性新增 sysfs 條目

返回

成功時指向已分配的 flashnode 會話的指標,失敗時為 NULL

struct iscsi_bus_flash_conn *iscsi_create_flashnode_conn(struct Scsi_Host *shost, struct iscsi_bus_flash_session *fnode_sess, struct iscsi_transport *transport, int dd_size)

在sysfs中新增 flashnode 連線條目

引數

struct Scsi_Host *shost

指向主機資料的指標

struct iscsi_bus_flash_session *fnode_sess

指向父 flashnode 會話條目的指標

struct iscsi_transport *transport

指向傳輸資料的指標

int dd_size

要分配的總大小

描述

為 flashnode 連線屬性新增 sysfs 條目

返回

成功時指向已分配的 flashnode 連線的指標,失敗時為 NULL

struct device *iscsi_find_flashnode_sess(struct Scsi_Host *shost, const void *data, device_match_t fn)

查詢 flashnode 會話條目

引數

struct Scsi_Host *shost

指向主機資料的指標

const void *data

指向包含用於比較的值的資料的指標

device_match_t fn

執行實際比較的函式指標

描述

查詢 flashnode 會話物件,使用傳入的函式指標中定義的邏輯比較傳遞的資料

返回

成功時指向找到的 flashnode 會話裝置物件的指標,失敗時為 NULL

struct device *iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess)

查詢 flashnode 連線條目

引數

struct iscsi_bus_flash_session *fnode_sess

指向父 flashnode 會話條目的指標

描述

查詢 flashnode 連線物件,使用傳入的函式指標中定義的邏輯比較傳遞的資料

返回

成功時指向找到的 flashnode 連線裝置物件的指標,失敗時為 NULL

void iscsi_destroy_flashnode_sess(struct iscsi_bus_flash_session *fnode_sess)

銷燬 flashnode 會話條目

引數

struct iscsi_bus_flash_session *fnode_sess

指向要銷燬的 flashnode 會話條目的指標

描述

從 sysfs 中刪除 flashnode 會話條目和所有子 flashnode 連線條目

void iscsi_destroy_all_flashnode(struct Scsi_Host *shost)

銷燬所有 flashnode 會話條目

引數

struct Scsi_Host *shost

指向主機資料的指標

描述

從 sysfs 中銷燬所有 flashnode 會話條目和所有相應的子 flashnode 連線條目

int iscsi_block_scsi_eh(struct scsi_cmnd *cmd)

阻塞 scsi eh 直到會話狀態轉換

引數

struct scsi_cmnd *cmd

傳遞給 scsi eh 處理程式的 scsi 命令

描述

如果會話已關閉,則此函式將等待恢復定時器觸發或會話重新登入。如果恢復定時器觸發,則返回 FAST_IO_FAIL。呼叫者應將此錯誤值傳遞給 scsi eh。

void iscsi_unblock_session(struct iscsi_cls_session *session)

將會話設定為已登入並啟動 IO。

引數

struct iscsi_cls_session *session

iscsi 會話

描述

將會話標記為準備好接受 IO。

void iscsi_force_destroy_session(struct iscsi_cls_session *session)

從核心銷燬會話

引數

struct iscsi_cls_session *session

要銷燬的會話

描述

強制從核心銷燬會話。僅當用戶空間在系統關閉期間不再執行時,才應使用此方法。

struct iscsi_cls_conn *iscsi_alloc_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)

分配 iscsi 類連線

引數

struct iscsi_cls_session *session

iscsi cls 會話

int dd_size

私有驅動程式資料大小

uint32_t cid

連線 ID

int iscsi_add_conn(struct iscsi_cls_conn *conn)

新增 iscsi 類連線

引數

struct iscsi_cls_conn *conn

iscsi cls 連線

描述

這會將 iscsi_cls_conn 公開給 sysfs,因此請確保在呼叫此函式之前初始化 sysfs 屬性的相關資源。

void iscsi_remove_conn(struct iscsi_cls_conn *conn)

從 sysfs 中刪除 iscsi 類連線

引數

struct iscsi_cls_conn *conn

iscsi cls 連線

描述

從 sysfs 中刪除 iscsi_cls_conn,並等待先前在 sysfs 中讀取/寫入 iscsi_cls_conn 的屬性完成。

int iscsi_session_event(struct iscsi_cls_session *session, enum iscsi_uevent_e event)

傳送會話銷燬完成事件

引數

struct iscsi_cls_session *session

iscsi 類會話

enum iscsi_uevent_e event

事件型別

序列連線 SCSI (SAS) 傳輸類

檔案 drivers/scsi/scsi_transport_sas.c 定義了序列連線 SCSI 的傳輸屬性,它是 SATA 的一種變體,旨在用於大型高端系統。

SAS 傳輸類包含用於處理 SAS HBA、驅動程式模型中 SAS 拓撲的近似表示以及各種 sysfs 屬性以向用戶空間公開這些拓撲和管理介面的通用程式碼。

除了基本的 SCSI 核心物件之外,此傳輸類還引入了兩個額外的中間物件:SAS PHY 由 struct sas_phy 表示,定義了 SAS HBA 或擴充套件器上的“傳出”PHY,SAS 遠端 PHY 由 struct sas_rphy 表示,定義了 SAS 擴充套件器或終端裝置上的“傳入”PHY。請注意,這純粹是一個軟體概念,PHY 和遠端 PHY 的底層硬體完全相同。

此程式碼中沒有 SAS 埠的概念,使用者可以根據 port_identifier 屬性檢視哪些 PHY 構成一個寬埠,該屬性對於埠中的所有 PHY 都是相同的。

void sas_remove_children(struct device *dev)

拆除裝置 SAS 資料結構

引數

struct device *dev

屬於 sas 物件的裝置

描述

刪除給定物件的所有 SAS PHY 和遠端 PHY

void sas_remove_host(struct Scsi_Host *shost)

拆除 Scsi_Host 的 SAS 資料結構

引數

struct Scsi_Host *shost

已拆除的 Scsi Host

描述

刪除給定 Scsi_Host 的所有 SAS PHY 和遠端 PHY,並同時刪除 Scsi_Host。

注意

不要再在 Scsi_Host 上呼叫 scsi_remove_host(),因為它已被刪除。

u64 sas_get_address(struct scsi_device *sdev)

返回裝置的 SAS 地址

引數

struct scsi_device *sdev

scsi 裝置

描述

返回 scsi 裝置的 SAS 地址

unsigned int sas_tlr_supported(struct scsi_device *sdev)

檢查 vpd 0x90 中的 TLR 位

引數

struct scsi_device *sdev

scsi 裝置結構

描述

檢查是否支援傳輸層重試。如果存在 vpd 頁 0x90,則支援 TRL。

void sas_disable_tlr(struct scsi_device *sdev)

設定 TLR 標誌

引數

struct scsi_device *sdev

scsi 裝置結構

描述

將 tlr_enabled 標誌設定為 0。

void sas_enable_tlr(struct scsi_device *sdev)

設定 TLR 標誌

引數

struct scsi_device *sdev

scsi 裝置結構

描述

將 tlr_enabled 標誌設定為 1。

bool sas_ata_ncq_prio_supported(struct scsi_device *sdev)

檢查是否支援 ATA NCQ 命令優先順序

引數

struct scsi_device *sdev

SCSI 裝置

描述

檢查 ATA 裝置是否使用 VPD 頁 89h(ATA 資訊)支援 NCQ 優先順序。由於此 VPD 頁僅針對 ATA 裝置實現,因此此函式始終為 SCSI 裝置返回 false。

struct sas_phy *sas_phy_alloc(struct device *parent, int number)

分配並初始化 SAS PHY 結構

引數

struct device *parent

父裝置

int number

Phy 索引

描述

分配一個 SAS PHY 結構。它將新增到裝置樹中,位於 parent 指定的裝置下,該裝置必須是 Scsi_Host 或 sas_rphy。

返回

已分配的 SAS PHY,如果分配失敗,則為 NULL

int sas_phy_add(struct sas_phy *phy)

將 SAS PHY 新增到裝置層次結構

引數

struct sas_phy *phy

要新增的 PHY

描述

將 SAS PHY 釋出到系統的其餘部分。

void sas_phy_free(struct sas_phy *phy)

釋放 SAS PHY

引數

struct sas_phy *phy

要釋放的 SAS PHY

描述

釋放指定的 SAS PHY。

注意

只能對尚未使用 sas_phy_add() 成功新增的 PHY 呼叫此函式。

void sas_phy_delete(struct sas_phy *phy)

刪除 SAS PHY

引數

struct sas_phy *phy

要刪除的 SAS PHY

描述

刪除指定的 SAS PHY。如果 SAS PHY 有關聯的遠端 PHY,則先將其刪除。

int scsi_is_sas_phy(const struct device *dev)

檢查struct device是否代表一個SAS PHY

引數

const struct device *dev

要檢查的裝置

返回

如果裝置代表一個SAS PHY,則返回1,否則返回0

struct sas_port *sas_port_alloc(struct device *parent, int port_id)

分配和初始化一個SAS埠結構體

引數

struct device *parent

父裝置

int port_id

埠號

描述

分配一個 SAS 埠結構。它將被新增到裝置樹中,位於由 **parent** 指定的裝置下方,該裝置必須是 Scsi_Host 或 sas_expander_device。

返回

出錯時返回NULL

struct sas_port *sas_port_alloc_num(struct device *parent)

分配和初始化一個SAS埠結構體

引數

struct device *parent

父裝置

描述

分配一個 SAS 埠結構和一個與之關聯的號碼。 此介面實際上適用於埠號沒有意義的介面卡,因此 SAS 類應該管理它們。 它將被新增到裝置樹中,位於由 **parent** 指定的裝置下方,該裝置必須是 Scsi_Host 或 sas_expander_device。

返回

出錯時返回NULL

int sas_port_add(struct sas_port *port)

將一個SAS埠新增到裝置層次結構中

引數

struct sas_port *port

要新增的埠

描述

向系統的其餘部分發佈一個埠

void sas_port_free(struct sas_port *port)

釋放一個SAS埠

引數

struct sas_port *port

要釋放的SAS埠

描述

釋放指定的SAS埠。

注意

此函式只能在尚未成功使用sas_port_add()新增的埠上呼叫。

void sas_port_delete(struct sas_port *port)

移除 SAS 埠

引數

struct sas_port *port

要移除的 SAS 埠

描述

移除指定的 SAS 埠。如果 SAS 埠有關聯的 phys,則將它們也從埠取消連結。

int scsi_is_sas_port(const struct device *dev)

檢查struct device是否代表一個SAS埠

引數

const struct device *dev

要檢查的裝置

返回

如果裝置代表一個 SAS 埠,則返回 1,否則返回 0

struct sas_phy *sas_port_get_phy(struct sas_port *port)

嘗試獲取對埠成員的引用

引數

struct sas_port *port

要檢查的埠

void sas_port_add_phy(struct sas_port *port, struct sas_phy *phy)

將另一個phy新增到埠以形成一個寬埠

引數

struct sas_port *port

要將phy新增到的埠

struct sas_phy *phy

要新增的phy

描述

當埠最初建立時,它是空的(沒有 phys)。所有埠必須至少有一個 phy 才能執行,並且所有寬埠必須至少有兩個。當前程式碼對埠和寬埠沒有區別,但是唯一可以連線到遠端裝置的物件是一個埠,所以如果埠連線到任何東西,則必須在具有 phys 的所有裝置上形成埠。

void sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy)

從埠或寬埠中移除一個 phy

引數

struct sas_port *port

要從中移除 phy 的埠

struct sas_phy *phy

要移除的 phy

描述

此操作用於再次拆除埠。 在呼叫 sas_port_delete 之前,必須對每個埠或寬埠執行此操作。

struct sas_rphy *sas_end_device_alloc(struct sas_port *parent)

為終端裝置分配一個 rphy

引數

struct sas_port *parent

哪個埠

描述

分配一個 SAS 遠端 PHY 結構,連線到 **parent**。

返回

已分配的 SAS PHY,如果分配失敗,則為 NULL

struct sas_rphy *sas_expander_alloc(struct sas_port *parent, enum sas_device_type type)

為終端裝置分配一個 rphy

引數

struct sas_port *parent

哪個埠

enum sas_device_type type

SAS_EDGE_EXPANDER_DEVICE 或 SAS_FANOUT_EXPANDER_DEVICE

描述

分配一個 SAS 遠端 PHY 結構,連線到 **parent**。

返回

已分配的 SAS PHY,如果分配失敗,則為 NULL

int sas_rphy_add(struct sas_rphy *rphy)

將一個SAS遠端PHY新增到裝置層次結構中

引數

struct sas_rphy *rphy

要新增的遠端 PHY

描述

向系統的其餘部分發佈一個 SAS 遠端 PHY。

void sas_rphy_free(struct sas_rphy *rphy)

釋放一個SAS遠端PHY

引數

struct sas_rphy *rphy

要釋放的SAS遠端PHY

描述

釋放指定的SAS遠端PHY。

注意

此函式只能在尚未成功使用sas_rphy_add()新增的遠端 PHY 上呼叫(或者已經 sas_rphy_remove() 掉了)。

void sas_rphy_delete(struct sas_rphy *rphy)

移除並釋放SAS遠端PHY

引數

struct sas_rphy *rphy

要移除和釋放的SAS遠端PHY

描述

移除指定的SAS遠端PHY並釋放它。

取消連結 SAS 遠端 PHY

引數

struct sas_rphy *rphy

要從其父埠取消連結的 SAS 遠端 phy

描述

移除對 rphy 的埠引用

void sas_rphy_remove(struct sas_rphy *rphy)

移除 SAS 遠端 PHY

引數

struct sas_rphy *rphy

要移除的 SAS 遠端 phy

描述

移除指定的 SAS 遠端 PHY。

int scsi_is_sas_rphy(const struct device *dev)

檢查struct device是否代表一個SAS遠端PHY

引數

const struct device *dev

要檢查的裝置

返回

如果裝置代表一個 SAS 遠端 PHY,則返回 1,否則返回 0

struct scsi_transport_template *sas_attach_transport(struct sas_function_template *ft)

例項化 SAS 傳輸模板

引數

struct sas_function_template *ft

SAS 傳輸類函式模板

void sas_release_transport(struct scsi_transport_template *t)

釋放 SAS 傳輸模板例項

引數

struct scsi_transport_template *t

傳輸模板例項

SATA 傳輸類

SATA 傳輸由 libata 處理,它在此目錄中有自己的文件書。

並行 SCSI (SPI) 傳輸類

檔案 drivers/scsi/scsi_transport_spi.c 定義了傳統(快速/寬/超)SCSI 匯流排的傳輸屬性。

void spi_dv_device(struct scsi_device *sdev)

對裝置進行域驗證

引數

struct scsi_device *sdev

要驗證的 scsi 裝置

在當前執行執行緒中對給定裝置執行域驗證。 由於 DV 操作可能會休眠,因此當前執行緒必須具有使用者上下文。 也不得持有任何可能導致 DV 發出的 I/O 發生死鎖的 SCSI 相關鎖。

void spi_schedule_dv_device(struct scsi_device *sdev)

計劃對裝置進行域驗證

引數

struct scsi_device *sdev

要驗證的裝置

與上面的 spi_dv_device() 相同,只是 DV 將被安排在稍後的工作佇列中進行。 所有記憶體分配都是原子的,因此可以從任何上下文呼叫,包括那些持有 SCSI 鎖的上下文。

void spi_display_xfer_agreement(struct scsi_target *starget)

列印當前目標傳輸協議

引數

struct scsi_target *starget

要顯示協議的目標

描述

每個 SPI 埠都需要為總線上的每個其他埠維護一個傳輸協議。 此函式列印當前協議的單行摘要; 更多詳細資訊可在 sysfs 中獲得。

int spi_populate_tag_msg(unsigned char *msg, struct scsi_cmnd *cmd)

將標記訊息放置在緩衝區中

引數

unsigned char *msg

指向放置標記的區域的指標

struct scsi_cmnd *cmd

指向標記的 scsi 命令的指標

底層驅動程式可以隨時呼叫它,我們將執行

旨在為特定請求建立正確型別的標記訊息。 返回標記訊息的大小。 如果此裝置停用 TCQ,則可能返回 0。

SCSI RDMA (SRP) 傳輸類

檔案 drivers/scsi/scsi_transport_srp.c 定義了透過遠端直接記憶體訪問的 SCSI 的傳輸屬性。

int srp_tmo_valid(int reconnect_delay, int fast_io_fail_tmo, long dev_loss_tmo)

檢查超時組合的有效性

引數

int reconnect_delay

重連延遲,以秒為單位。

int fast_io_fail_tmo

快速 I/O 失敗超時,以秒為單位。

long dev_loss_tmo

裝置丟失超時,以秒為單位。

描述

超時引數的組合必須確保 SCSI 命令在合理的時間內完成。 因此,不允許快速 I/O 故障超時超過 SCSI_DEVICE_BLOCK_MAX_TIMEOUT,如果已停用快速 I/O 故障,也不允許 dev_loss_tmo 超過該限制。 此外,這些引數必須確保多路徑能夠及時檢測到故障路徑。 因此,不允許同時停用所有三個引數。

void srp_start_tl_fail_timers(struct srp_rport *rport)

啟動傳輸層故障計時器

引數

struct srp_rport *rport

SRP 目標埠。

描述

啟動傳輸層快速 I/O 故障和裝置丟失計時器。 不要修改已啟動的計時器。

int srp_reconnect_rport(struct srp_rport *rport)

重新連線到 SRP 目標埠

引數

struct srp_rport *rport

SRP 目標埠。

描述

在呼叫 reconnect() 之前阻止 SCSI 命令排隊,以便 queuecommand() 不會與來自 SCSI EH 之外的 reconnect() 併發呼叫。 這很重要,因為 reconnect() 實現可能會重新分配 queuecommand() 所需的資源。

底層驅動程式可以隨時呼叫它,我們將執行

  • 此函式既不等待未完成的請求完成,也不嘗試中止這些請求。 在重新連線到目標埠之前,reconnect() 函式有責任完成未完成的命令。

  • 呼叫者有責任確保 reconnect() 函式重新分配的資源在此函式進行過程中不會被使用。 一種可能的策略是從 SCSI EH 執行緒的上下文中呼叫此函式。 另一種可能的策略是在每個可由 SCSI EH 呼叫的 SCSI LLD 回撥中鎖定 rport 互斥鎖(scsi_host_template.eh_*() 函式以及 scsi_host_template.queuecommand() 函式)。

enum scsi_timeout_action srp_timed_out(struct scsi_cmnd *scmd)

SCSI 超時 EH 的 SRP 傳輸攔截

引數

struct scsi_cmnd *scmd

SCSI 命令。

描述

如果在 rport 處於阻止狀態時發生超時,請要求 SCSI EH 繼續等待 (SCSI_EH_RESET_TIMER)。 否則,讓 SCSI 核心處理超時 (SCSI_EH_NOT_HANDLED)。

注意

此函式從軟中斷上下文中呼叫,並持有請求佇列鎖。

void srp_rport_get(struct srp_rport *rport)

增加 rport 引用計數

引數

struct srp_rport *rport

SRP 目標埠。

void srp_rport_put(struct srp_rport *rport)

減少 rport 引用計數

引數

struct srp_rport *rport

SRP 目標埠。

struct srp_rport *srp_rport_add(struct Scsi_Host *shost, struct srp_rport_identifiers *ids)

將 SRP 遠端埠新增到裝置層次結構

引數

struct Scsi_Host *shost

遠端埠連線到的 scsi 主機。

struct srp_rport_identifiers *ids

遠端埠的埠 ID。

描述

將埠釋出到系統的其餘部分。

void srp_rport_del(struct srp_rport *rport)

刪除 SRP 遠端埠

引數

struct srp_rport *rport

要刪除的 SRP 遠端埠

描述

刪除指定的 SRP 遠端埠。

void srp_remove_host(struct Scsi_Host *shost)

拆卸 Scsi_Host 的 SRP 資料結構

引數

struct Scsi_Host *shost

已拆除的 Scsi Host

描述

刪除給定 Scsi_Host 的所有 SRP 遠端埠。 必須在 SRP HBA 的 scsi_remove_host 之前呼叫。

void srp_stop_rport_timers(struct srp_rport *rport)

停止傳輸層恢復計時器

引數

struct srp_rport *rport

要停止計時器的 SRP 遠端埠。

描述

必須在 srp_remove_host()scsi_remove_host() 之後呼叫。 呼叫者必須持有對 rport (rport->dev) 和 SCSI host (rport->dev.parent) 的引用。

struct scsi_transport_template *srp_attach_transport(struct srp_function_template *ft)

例項化 SRP 傳輸模板

引數

struct srp_function_template *ft

SRP 傳輸類函式模板

void srp_release_transport(struct scsi_transport_template *t)

釋放 SRP 傳輸模板例項

引數

struct scsi_transport_template *t

傳輸模板例項

SCSI 下層

主機匯流排介面卡傳輸型別

許多現代裝置控制器使用 SCSI 命令集作為協議,透過許多不同型別的物理連線與其裝置進行通訊。

在 SCSI 語言中,能夠承載 SCSI 命令的匯流排稱為“傳輸”,而連線到此類匯流排的控制器稱為“主機匯流排介面卡 (HBA)”。

除錯傳輸

檔案 drivers/scsi/scsi_debug.c 模擬一個主機介面卡,該介面卡連線了可變數量的磁碟(或類似磁碟的裝置),共享一個公共的 RAM 容量。 執行大量檢查以確保我們沒有混淆塊,並且如果發現任何異常情況,核心會發生 panic。

為了更逼真,模擬裝置具有 SAS 磁碟的傳輸屬性。

有關文件,請參閱 http://sg.danny.cz/sg/scsi_debug.html

待辦事項

並行(快速/寬/超寬)SCSI、USB、SATA、SAS、光纖通道、FireWire、ATAPI 裝置、Infiniband、並行埠、netlink...