InfiniBand 中間層鎖定¶
本指南旨在明確 InfiniBand 中間層所做的鎖定假設。 它描述了對位於中間層之下的底層驅動程式和使用中間層的高層協議的要求。
睡眠和中斷上下文¶
除了以下例外情況,struct ib_device 中所有方法的底層驅動程式實現都可以睡眠。例外情況是列表中的任何方法
create_ah
modify_ah
query_ah
destroy_ah
post_send
post_recv
poll_cq
req_notify_cq
這些方法不能睡眠,並且必須可以從任何上下文呼叫。
匯出到高層協議使用者的相應函式
rdma_create_ah
rdma_modify_ah
rdma_query_ah
rdma_destroy_ah
ib_post_send
ib_post_recv
ib_req_notify_cq
因此可以安全地從任何上下文呼叫。
此外,該函式
ib_dispatch_event
底層驅動程式使用該函式透過中間層分發非同步事件,也可以安全地從任何上下文呼叫。
可重入性¶
底層驅動程式匯出的 struct ib_device 中的所有方法必須完全可重入。 需要底層驅動程式執行所有必要的同步以保持一致性,即使同時執行使用同一物件的多個函式呼叫也是如此。
IB 中間層不執行任何函式呼叫的序列化。
由於底層驅動程式是可重入的,因此高層協議使用者不需要執行任何序列化。 但是,可能需要一些序列化才能獲得合理的結果。 例如,使用者可以安全地在多個 CPU 上同時呼叫 ib_poll_cq()。 但是,未定義 ib_poll_cq() 的不同調用之間的工作完成資訊的順序。
回撥¶
底層驅動程式不得從與 ib_device 方法呼叫相同的呼叫鏈中直接執行回撥。 例如,不允許底層驅動程式直接從其 post_send 方法呼叫使用者的完成事件處理程式。 相反,底層驅動程式應推遲此回撥,例如,透過排程一個 tasklet 來執行回撥。
底層驅動程式負責確保不會同時為同一 CQ 呼叫多個完成事件處理程式。 驅動程式必須保證在給定的 CQ 上一次只執行一個 CQ 事件處理程式。 換句話說,不允許出現以下情況
CPU1 CPU2 low-level driver -> consumer CQ event callback: /* ... */ ib_req_notify_cq(cq, ...); low-level driver -> /* ... */ consumer CQ event callback: /* ... */ return from CQ event handler未定義完成事件和非同步事件回撥執行的上下文。 根據底層驅動程式的不同,它可能是程序上下文、軟中斷上下文或中斷上下文。 高層協議使用者不得在回撥中休眠。
熱插拔¶
當底層驅動程式呼叫
ib_register_device()時,它會宣佈裝置已準備好供使用者使用,所有初始化都必須在此呼叫之前完成。 在驅動程式呼叫ib_unregister_device()返回之前,裝置必須保持可用。底層驅動程式必須從程序上下文中呼叫
ib_register_device()和ib_unregister_device()。 它不得持有任何可能導致死鎖的訊號量,如果使用者在這些呼叫中回撥到驅動程式中。高層協議使用者可以在為其呼叫 struct ib_client 的 add 方法後立即開始使用 IB 裝置。 在從 remove 方法返回之前,使用者必須完成所有清理並釋放與裝置相關的所有資源。
允許使用者在其 add 和 remove 方法中睡眠。