blk_mq_init_queue函數學習記錄

blk-mq編程,主要要調用兩個函數進行初始化工作,blk_mq_init_queue這是第二個。該函數先是申請了struct request_queue結構,這個請求隊列后面用于賦值給磁盤那個結構體的相應成員。

struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set)
{struct request_queue *uninit_q, *q;//分配struct request_queue并初始化uninit_q = blk_alloc_queue_node(GFP_KERNEL, set->numa_node, NULL);if (!uninit_q)return ERR_PTR(-ENOMEM);/*1:分配每個cpu專屬的軟件隊列并初始化2:分配硬件隊列,并初始化3:建立軟件隊列和硬件隊列的聯系*/q = blk_mq_init_allocated_queue(set, uninit_q);if (IS_ERR(q))blk_cleanup_queue(uninit_q);return q;
}
EXPORT_SYMBOL(blk_mq_init_queue);

blk_mq_init_allocated_queue函數分析

一眼望過去,確實有點復雜,不過,多看幾遍就好了,
這里面,主要就是給struct request_queue *q結構體里面的成員變量賦值的,簡單的變量賦值就不分析了,看看它調用的函數進行分析。

struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, struct request_queue *q)
{/* mark the queue as mq asap */q->mq_ops = set->ops;q->poll_cb = blk_stat_alloc_callback(blk_mq_poll_stats_fn, blk_mq_poll_stats_bkt, BLK_MQ_POLL_STATS_BKTS, q);if (!q->poll_cb)goto err_exit;q->queue_ctx = alloc_percpu(struct blk_mq_ctx);//percpu變量 軟件隊列if (!q->queue_ctx)goto err_exit;/* init q->mq_kobj and sw queues' kobjects */blk_mq_sysfs_init(q); //主要是初始化kobject變量//二級指針 硬件隊列q->queue_hw_ctx = kcalloc_node(nr_cpu_ids, sizeof(*(q->queue_hw_ctx)), GFP_KERNEL, set->numa_node);if (!q->queue_hw_ctx)goto err_percpu;//賦值q->mq_map,這個數組保存了每個CPU對應的硬件隊列編號q->mq_map = set->mq_map;blk_mq_realloc_hw_ctxs(set, q);if (!q->nr_hw_queues)goto err_hctxs;/*定時器初始化,設置超時時間*/INIT_WORK(&q->timeout_work, blk_mq_timeout_work);blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ);q->nr_queues = nr_cpu_ids;q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT;if (!(set->flags & BLK_MQ_F_SG_MERGE))queue_flag_set_unlocked(QUEUE_FLAG_NO_SG_MERGE, q);q->sg_reserved_size = INT_MAX;INIT_DELAYED_WORK(&q->requeue_work, blk_mq_requeue_work);INIT_LIST_HEAD(&q->requeue_list);spin_lock_init(&q->requeue_lock);blk_queue_make_request(q, blk_mq_make_request);if (q->mq_ops->poll)q->poll_fn = blk_mq_poll;/** Do this after blk_queue_make_request() overrides it...*/q->nr_requests = set->queue_depth; //防止被覆蓋/** Default to classic polling*/q->poll_nsec = -1;if (set->ops->complete)blk_queue_softirq_done(q, set->ops->complete);blk_mq_init_cpu_queues(q, set->nr_hw_queues);blk_mq_add_queue_tag_set(set, q);blk_mq_map_swqueue(q);if (!(set->flags & BLK_MQ_F_NO_SCHED)) {int ret;ret = elevator_init_mq(q);if (ret)return ERR_PTR(ret);}return q;
err_hctxs:kfree(q->queue_hw_ctx);
err_percpu:free_percpu(q->queue_ctx);
err_exit:q->mq_ops = NULL;return ERR_PTR(-ENOMEM);
}
EXPORT_SYMBOL(blk_mq_init_allocated_queue);

blk_stat_alloc_callback

這個函數一看也沒什么分析的,主要也是給poll_cb進行賦值,采用了很多的默認函數進行賦值。

struct blk_stat_callback *
blk_stat_alloc_callback(void (*timer_fn)(struct blk_stat_callback *),int (*bucket_fn)(const struct request *), unsigned int buckets, void *data)
{struct blk_stat_callback *cb;cb = kmalloc(sizeof(*cb), GFP_KERNEL);if (!cb)return NULL;cb->stat = kmalloc_array(buckets, sizeof(struct blk_rq_stat), GFP_KERNEL);if (!cb->stat) {kfree(cb);return NULL;}cb->cpu_stat = __alloc_percpu(buckets * sizeof(struct blk_rq_stat), __alignof__(struct blk_rq_stat));if (!cb->cpu_stat) {kfree(cb->stat);kfree(cb);return NULL;}cb->timer_fn = timer_fn;cb->bucket_fn = bucket_fn;cb->data = data;cb->buckets = buckets;timer_setup(&cb->timer, blk_stat_timer_fn, 0);return cb;
}
EXPORT_SYMBOL_GPL(blk_stat_alloc_callback);

blk_mq_sysfs_init

接著到這個函數,也是變量的初始化工作,struct request_queue隊列里面的kobject變量初始化,以及取出在每一個cpu上q->queue_ctx結構體,然后對齊成員kobject變量進行初始化。

void blk_mq_sysfs_init(struct request_queue *q)
{struct blk_mq_ctx *ctx;int cpu;kobject_init(&q->mq_kobj, &blk_mq_ktype);for_each_possible_cpu(cpu) {ctx = per_cpu_ptr(q->queue_ctx, cpu);//返回每個cpu上的q->queue_ctx變量的首地址kobject_init(&ctx->kobj, &blk_mq_ctx_ktype);}
}

blk_mq_realloc_hw_ctxs

這個函數相對來說比較重要。后面再補充。

在這里插入代碼片

blk_queue_make_request

這個函數也是給q的其成員賦值的,先大概熟悉一下,如果有實際的調試分析,需要了解某個參數的值,到時再回來看吧。

void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn)
{/** set defaults*/q->nr_requests = BLKDEV_MAX_RQ; //這個值后面會重新賦值進行覆蓋q->make_request_fn = mfn;blk_queue_dma_alignment(q, 511);blk_queue_congestion_threshold(q);q->nr_batching = BLK_BATCH_REQ;blk_set_default_limits(&q->limits);
}
EXPORT_SYMBOL(blk_queue_make_request);

blk_queue_softirq_done

也是賦值,IO操作完成時,會調用這個回調函數。

void blk_queue_softirq_done(struct request_queue *q, softirq_done_fn *fn)
{q->softirq_done_fn = fn;
}
EXPORT_SYMBOL(blk_queue_softirq_done);

blk_mq_init_cpu_queues

static void blk_mq_init_cpu_queues(struct request_queue *q, unsigned int nr_hw_queues)
{unsigned int i;for_each_possible_cpu(i) { //硬件隊列數/*返回這個變量在編號為i的cpu上的起始地址*/struct blk_mq_ctx *__ctx = per_cpu_ptr(q->queue_ctx, i);struct blk_mq_hw_ctx *hctx;//其成員做一些賦值操作__ctx->cpu = i;spin_lock_init(&__ctx->lock);INIT_LIST_HEAD(&__ctx->rq_list);__ctx->queue = q;/** Set local node, IFF we have more than one hw queue. If* not, we remain on the home node of the device*/hctx = blk_mq_map_queue(q, i); //取出每個cpu上的硬件隊列if (nr_hw_queues > 1 && hctx->numa_node == NUMA_NO_NODE)hctx->numa_node = local_memory_node(cpu_to_node(i));}
}

blk_mq_add_queue_tag_set


blk_mq_map_swqueue


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/166200.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/166200.shtml
英文地址,請注明出處:http://en.pswp.cn/news/166200.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python3到文件的讀取以及輸出

excel表格的讀取和輸入輸出 python中txt的讀取和輸入輸出 txt輸出報錯👇 UnicodeEncodeError: ascii codec cant encode characters in position 154-157: ordinal not in range(128)解決方法

Tomcat 配置

1: 打開 2:選擇版本號,我這邊是 1.7 3:添加 web 4: 添加jar包 5:添加 6:添加 Tomcat

【每日一題】1410. HTML實體解析器-2023.11.23

題目: 1410. HTML 實體解析器 「HTML 實體解析器」 是一種特殊的解析器,它將 HTML 代碼作為輸入,并用字符本身替換掉所有這些特殊的字符實體。 HTML 里這些特殊字符和它們對應的字符實體包括: 雙引號:字符實體為 &…

vim翻頁快捷鍵

Vim翻頁 整頁 Ctrlf向下翻頁,下一頁,相當于Page DownCtrlb向上翻頁,上一頁,相當于Page Up 半頁 Ctrld向下半頁,下一半頁,光標下移Ctrlu向上半頁,上衣半頁,光標上移 按行 Ctrle…

vue2【組件的構成】

目錄 1:什么是組件化開發 2:vue中的組件化開發 3:vue組件的三個組成部分 4:組件中定義方法,監聽器,過濾器,計算屬性節點。 5:template中只允許唯一根節點,style默認…

OpenMLDB SQL 開發調試神器 - OpenMLDB SQL Emulator

今天為大家介紹一款來自 OpenMLDB 社區的優秀獨立工具 - OpenMLDB SQL Simulator(https://github.com/vagetablechicken/OpenMLDBSQLEmulator) ,可以讓你更加高效方便的開發、調試 OpenMLDB SQL。 為了高效的實現時序特征計算,Op…

高質量短效SOCKS5代理IP是什么意思?作為技術你了解嗎

小張是一位網絡安全技術測試員,最近他接到了一個頭疼的任務,那就是評估公司系統的安全性,因此他前來咨詢,在得知SOCKS5代理IP可以幫他之后,他不禁產生疑問,這是什么原理?其實和小張一樣的朋友不…

命令查詢職責分離 (CQRS)

CQRS 的最初需求 多年來,傳統的 CRUD(創建、讀取、更新、刪除)模式一直是系統架構的支柱。在 CRUD 中,讀取和寫入操作通常由相同的數據模型和相同的數據庫模式處理。雖然這種方法簡單直觀,但隨著系統規模的擴大和需求…

第99步 深度學習圖像目標檢測:SSDlite建模

基于WIN10的64位系統演示 一、寫在前面 本期,我們繼續學習深度學習圖像目標檢測系列,SSD(Single Shot MultiBox Detector)模型的后續版本,SSDlite模型。 二、SSDlite簡介 SSDLite 是 SSD 模型的一個變種&#xff0c…

竹云參編《公共數據授權運營平臺技術要求》團體標準正式發布

2023年11月23日,第二屆全球數字貿易博覽會“數據要素治理與市場化論壇”于杭州成功召開,國家數據局黨組書記、局長劉烈宏,浙江省委常委、常務副省長徐文光出席會議并致辭。會上,國家工業信息安全發展研究中心發布并解讀了我國首部…

[Linux] 馮諾依曼體系結構 與 操作系統

文章目錄 1、馮諾依曼體系結構2、操作系統 1、馮諾依曼體系結構 馮諾依曼結構也稱普林斯頓結構,是一種將程序指令存儲器和數據存儲器合并在一起的存儲器結構。程序指令存儲地址和數據存儲地址指向同一個存儲器的不同物理位置,因此程序指令和數據的寬度相…

【鴻蒙應用ArkTS開發系列】- 云開發入門實戰二 實現省市地區三級聯動地址選擇器組件(下)

文章目錄 概述端云調用流程端側集成AGC SDK端側省市地區聯動的地址選擇器組件開發創建省市數據模型創建省市地區視圖UI子組件創建頁面UI視圖Page文件 打包測試總結 概述 我們在前面的課程,對云開發的入門做了介紹,以及使用一個省市地區聯動的地址選擇器…

三次輸錯密碼后,系統是怎么做到不讓我繼續嘗試的?

1故事背景 忘記密碼這件事,相信絕大多數人都遇到過,輸一次錯一次,錯到幾次以上,就不允許你繼續嘗試了。 但當你嘗試重置密碼,又發現新密碼不能和原密碼重復: 圖片 相信此刻心情只能用一張圖形容&#xf…

Mobaxterm 使用lrzsz傳輸文件(rz/sz)

Mobaxterm 使用lrzsz傳輸文件報錯 1. 現象 最近從xshell切換到Mobaxterm其他一切正常,就是使用rz傳輸文件時會出現錯誤,比較苦惱. 會出現以下錯誤 [rootcentos7 rpmbuild]# rz ?CCCCCCCCCCC23be50ive.**B0100000023be502. 解決方法 去官網(https://mobaxterm.mobatek.net…

2021年03月 Scratch(三級)真題解析#中國電子學會#全國青少年軟件編程等級考試

Scratch等級考試(1~4級)全部真題?點這里 一、單選題(共25題,每題2分,共50分) 第1題 在《采礦》游戲中,當角色撿到黃金時財富值加1分,撿到鉆石時財富值加2分,下面哪個程序實現這個功能? A: B: C: D: 答案:D A將變量值固定,BC為雙重判斷

練習七-在Verilog中使用任務task

在Verilog中使用任務task 1,任務目的2,RTL代碼,交換3,測試代碼4,波形顯示 1,任務目的 (1)掌握任務在verilog模塊設計中的應用; (2)學會在電平敏感…

Android Studio記錄一個錯誤:Execution failed for task ‘:app:lintVitalRelease‘.

Android出現Execution failed for task :app:lintVitalRelease.> Lint found fatal errors while assembling a release target. Execution failed for task :app:lintVitalRelease解決方法 Execution failed for task ‘:app:lintVitalRelease’ build project 可以正常執…

〖大前端 - 基礎入門三大核心之JS篇?〗- DOM事件對象及它的屬性

說明:該文屬于 大前端全棧架構白寶書專欄,目前階段免費,如需要項目實戰或者是體系化資源,文末名片加V!作者:不渴望力量的哈士奇(哈哥),十余年工作經驗, 從事過全棧研發、產品經理等工作&#xf…

進程已結束,退出代碼-1073741571 (0xC00000FD)

今天遇到了一個很邪門的問題,沒有報錯,只是提示“進程已結束,退出代碼-1073741571 (0xC00000FD)”。后來查資料說是棧溢出。 出問題的應該是上面這段代碼。 這里我想把一個128*128的矩陣進行剪枝操作。 傳入的128*128的矩陣太大了,兩組for循…

介紹GLFW庫和OpenGL和GLEW庫三者之間的關系

具體來說,OpenGL是一個開放的圖形庫,它規定了每個函數應該如何執行,以及它們的輸出值,但沒有具體實現。它提供了渲染2D和3D圖形的標準或規范。 GLEW,全稱OpenGL Extension Wrangler Library,是一個用于管理…