userfaultfd內核線程D狀態問題排查

問題現象

運維反應機器上出現了很多D狀態進程,也kill不掉,然后將現場保留下來進行排查。
在這里插入圖片描述

在這里插入圖片描述

排查過程

都是內核線程,先看下內核棧D在哪了,發現D在了userfaultfd的pagefault流程。
在這里插入圖片描述

uffd知識補充

uffd探究
uffd在firecracker與e2b的架構下使用方式如下:
1.firecracker注冊uffd共享給orchestrator,并將guest內存地址空間提交給orchestrator。
2.guest觸發缺頁,vm-exit出來,創建內核線程通知orchestrator有需要處理的pf請求,然后等待處理。
3.orchestrator會調用ioctl從內存快照文件中將數據寫入到對應的內存頁中
在這里插入圖片描述
查看handle_userfault代碼進行分析。

vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason)
{struct vm_area_struct *vma = vmf->vma;struct mm_struct *mm = vma->vm_mm;struct userfaultfd_ctx *ctx;struct userfaultfd_wait_queue uwq;vm_fault_t ret = VM_FAULT_SIGBUS;bool must_wait;unsigned int blocking_state;/** We don't do userfault handling for the final child pid update.** We also don't do userfault handling during* coredumping. hugetlbfs has the special* hugetlb_follow_page_mask() to skip missing pages in the* FOLL_DUMP case, anon memory also checks for FOLL_DUMP with* the no_page_table() helper in follow_page_mask(), but the* shmem_vm_ops->fault method is invoked even during* coredumping and it ends up here.*/if (current->flags & (PF_EXITING|PF_DUMPCORE))goto out;assert_fault_locked(vmf);ctx = vma->vm_userfaultfd_ctx.ctx;if (!ctx)goto out;BUG_ON(ctx->mm != mm);/* Any unrecognized flag is a bug. */VM_BUG_ON(reason & ~__VM_UFFD_FLAGS);/* 0 or > 1 flags set is a bug; we expect exactly 1. */VM_BUG_ON(!reason || (reason & (reason - 1)));if (ctx->features & UFFD_FEATURE_SIGBUS)goto out;if (!(vmf->flags & FAULT_FLAG_USER) && (ctx->flags & UFFD_USER_MODE_ONLY))goto out;/** If it's already released don't get it. This avoids to loop* in __get_user_pages if userfaultfd_release waits on the* caller of handle_userfault to release the mmap_lock.*/if (unlikely(READ_ONCE(ctx->released))) {/** Don't return VM_FAULT_SIGBUS in this case, so a non* cooperative manager can close the uffd after the* last UFFDIO_COPY, without risking to trigger an* involuntary SIGBUS if the process was starting the* userfaultfd while the userfaultfd was still armed* (but after the last UFFDIO_COPY). If the uffd* wasn't already closed when the userfault reached* this point, that would normally be solved by* userfaultfd_must_wait returning 'false'.** If we were to return VM_FAULT_SIGBUS here, the non* cooperative manager would be instead forced to* always call UFFDIO_UNREGISTER before it can safely* close the uffd.*/ret = VM_FAULT_NOPAGE;goto out;}/** Check that we can return VM_FAULT_RETRY.** NOTE: it should become possible to return VM_FAULT_RETRY* even if FAULT_FLAG_TRIED is set without leading to gup()* -EBUSY failures, if the userfaultfd is to be extended for* VM_UFFD_WP tracking and we intend to arm the userfault* without first stopping userland access to the memory. For* VM_UFFD_MISSING userfaults this is enough for now.*/if (unlikely(!(vmf->flags & FAULT_FLAG_ALLOW_RETRY))) {/** Validate the invariant that nowait must allow retry* to be sure not to return SIGBUS erroneously on* nowait invocations.*/BUG_ON(vmf->flags & FAULT_FLAG_RETRY_NOWAIT);
#ifdef CONFIG_DEBUG_VMif (printk_ratelimit()) {printk(KERN_WARNING"FAULT_FLAG_ALLOW_RETRY missing %x\n",vmf->flags);dump_stack();}
#endifgoto out;}/** Handle nowait, not much to do other than tell it to retry* and wait.*/ret = VM_FAULT_RETRY;if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT)goto out;/* take the reference before dropping the mmap_lock */userfaultfd_ctx_get(ctx);init_waitqueue_func_entry(&uwq.wq, userfaultfd_wake_function);uwq.wq.private = current;uwq.msg = userfault_msg(vmf->address, vmf->real_address, vmf->flags,reason, ctx->features);uwq.ctx = ctx;uwq.waken = false;blocking_state = userfaultfd_get_blocking_state(vmf->flags);/** Take the vma lock now, in order to safely call* userfaultfd_huge_must_wait() later. Since acquiring the* (sleepable) vma lock can modify the current task state, that* must be before explicitly calling set_current_state().*/if (is_vm_hugetlb_page(vma))hugetlb_vma_lock_read(vma);spin_lock_irq(&ctx->fault_pending_wqh.lock);/** After the __add_wait_queue the uwq is visible to userland* through poll/read().*/__add_wait_queue(&ctx->fault_pending_wqh, &uwq.wq);/** The smp_mb() after __set_current_state prevents the reads* following the spin_unlock to happen before the list_add in* __add_wait_queue.*/set_current_state(blocking_state);spin_unlock_irq(&ctx->fault_pending_wqh.lock);if (!is_vm_hugetlb_page(vma))must_wait = userfaultfd_must_wait(ctx, vmf, reason);elsemust_wait = userfaultfd_huge_must_wait(ctx, vmf, reason);if (is_vm_hugetlb_page(vma))hugetlb_vma_unlock_read(vma);release_fault_lock(vmf);if (likely(must_wait && !READ_ONCE(ctx->released))) {wake_up_poll(&ctx->fd_wqh, EPOLLIN);schedule();}__set_current_state(TASK_RUNNING);/** Here we race with the list_del; list_add in* userfaultfd_ctx_read(), however because we don't ever run* list_del_init() to refile across the two lists, the prev* and next pointers will never point to self. list_add also* would never let any of the two pointers to point to* self. So list_empty_careful won't risk to see both pointers* pointing to self at any time during the list refile. The* only case where list_del_init() is called is the full* removal in the wake function and there we don't re-list_add* and it's fine not to block on the spinlock. The uwq on this* kernel stack can be released after the list_del_init.*/if (!list_empty_careful(&uwq.wq.entry)) {spin_lock_irq(&ctx->fault_pending_wqh.lock);/** No need of list_del_init(), the uwq on the stack* will be freed shortly anyway.*/list_del(&uwq.wq.entry);spin_unlock_irq(&ctx->fault_pending_wqh.lock);}/** ctx may go away after this if the userfault pseudo fd is* already released.*/userfaultfd_ctx_put(ctx);out:return ret;
}

看起來像是不知道什么原因導致調度出去后,一直沒有被喚醒
在這里插入圖片描述
使用crash進一步驗證猜想,隨便找一個bt看下,確實是schedule調度出去之后沒有再被喚醒。
在這里插入圖片描述
先看一下uffd ctx里的這幾個工作隊列情況
在這里插入圖片描述
需要找到ctx地址
vm_fault->vm_area_struct->vm_userfaultfd_ctx,vm_fault結構體是第一個參數傳進來的,
在這里插入圖片描述
handle_userfault這個函數的匯編比較復雜,往上找找,在上層函數把vmf變量定義在了棧里,
在這里插入圖片描述
bt -f查看棧幀,hugetlb_handle_userfault幀里的前幾個地址看起來像是給結構體賦值的參數,嘗試解析一下
在這里插入圖片描述
vm_ops解析出了<hugetlb_vm_ops>,看起來沒啥問題,那解析下ctx
在這里插入圖片描述
fault_pending_wqh隊列的next!=prev,說明有pf請求沒有被處理,所以D住了,其他隊列的next=prev,都是空的。
在這里插入圖片描述
在這里插入圖片描述
waitq看一下pending隊列,結構體的第一個元素,地址就是結構體的地址,可以看到這5個kworker就是對應的pf請求線程,由于沒有被處理,導致D住了,那么接下來就要看一下pf請求為什么沒有被處理。
在這里插入圖片描述
同時也觀察到,引用計數為6,但是5個kworker+firecracker+orchestrator應該是7才對,看一下firecracker和orchestrator的狀態,由于是pf請求沒有被處理,著重排查orchestrator
在這里插入圖片描述
通過mm找到對應的firecracker進程
在這里插入圖片描述
在這里插入圖片描述
找到task_struct中的pid,就是對應的firecracker進程號
在這里插入圖片描述
firecracker進程還在,引用計數那就是少了orchestrator的,可能是close了,也可能是orchestrator進程退了
在這里插入圖片描述
ps一看發現orchestrator服務的啟動時間居然在firecracker之后,
而且查看e2b代碼發現,orchestrator服務close uffd之前會先kill掉firecracker進程,猜測可能是orchestrator重啟了,而且沒有走正常的關閉sandbox的流程,導致這些firecracker進程殘留了,同時也沒法再處理這些firecracker的pagefault請求,導致內核線程進入了D狀態。

與運維確認是我們發布了新版本,orchestrator服務確實重啟過了,問題確認清楚了,解決辦法先完善發布流程,升級重啟前先進行排水。

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

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

相關文章

深入解析:構建高性能異步HTTP客戶端的工程實踐

一、架構設計原理與核心優勢 HTTP/2多路復用技術的本質是通過單一的TCP連接并行處理多個請求/響應流&#xff0c;突破了HTTP/1.1的隊頭阻塞限制。在異步編程模型下&#xff0c;這種特性與事件循環機制完美結合&#xff0c;形成了高性能網絡通信的黃金組合。相較于傳統同步客戶…

根據臺賬批量制作個人表

1. 前期材料準備 1&#xff09;要有 人員總的信息臺賬 2&#xff09;要有 個人明白卡模板 2. 開始操作 1&#xff09;打開 人員總的信息臺賬&#xff0c;選擇所需要的數據模塊&#xff1b; 2&#xff09;點擊插入&#xff0c;選擇數據透視表&#xff0c;按流程操作&…

《AI大模型應知應會100篇》第65篇:基于大模型的文檔問答系統實現

第65篇&#xff1a;基于大模型的文檔問答系統實現 &#x1f4da; 摘要&#xff1a;本文詳解如何構建一個基于大語言模型&#xff08;LLM&#xff09;的文檔問答系統&#xff0c;支持用戶上傳 PDF 或 Word 文檔&#xff0c;并根據其內容進行智能問答。從文檔解析、向量化、存儲到…

RTK哪個品牌好?2025年RTK主流品牌深度解析

在測繪領域&#xff0c;RTK 技術的發展日新月異&#xff0c;選擇一款性能卓越、穩定可靠的 RTK 設備至關重要。2025 年&#xff0c;市場上涌現出眾多優秀品牌&#xff0c;本文將深入解析幾大主流品牌的核心競爭力。 華測導航&#xff08;CHCNAV&#xff09;&#xff1a;技術創…

SpringCloud微服務開發與實戰

本節內容帶你認識什么是微服務的特點&#xff0c;微服務的拆分&#xff0c;會使用Nacos實現服務治理&#xff0c;會使用OpenFeign實現遠程調用&#xff08;通過黑馬商城來帶你了解實際開發中微服務項目&#xff09; 前言&#xff1a;從谷歌搜索指數來看&#xff0c;國內從自201…

pgsql14自動創建表分區

最近有pgsql的分區表功能需求&#xff0c;沒想到都2025年了&#xff0c;pgsql和mysql還是沒有自身支持自動創建分區表的功能 現在pgsql數據庫層面還是只能用老三樣的辦法來處理這個問題&#xff0c;每個方法各有優劣 1. 觸發器 這是最傳統的方法&#xff0c;通過創建一個觸發…

math toolkit for real-time development讀書筆記一三角函數快速計算(1)

一、基礎知識 根據高中知識我們知道&#xff0c;很多函數都可以用泰勒級數展開。正余弦泰勒級數展開如下&#xff1a; 將其進一步抽象為公式可知&#xff1a; 正弦和余弦的泰勒級數具有高度結構化的模式&#xff0c;可拆解為以下核心特征&#xff1a; 1. 符號交替特性 正弦級…

uni-app 中適配 App 平臺

文章目錄 前言? 1. App 使用的 Runtime 架構&#xff1a;**WebView 原生容器&#xff08;plus runtime&#xff09;**&#x1f4cc; 技術棧核心&#xff1a; ? 2. WebView Native 的通信機制詳解&#xff08;JSBridge&#xff09;&#x1f4e4; Web → Native 調用&#xf…

SpringBoot基礎(靜態資源導入)

靜態資源導入 在WebMvcAutoConfiguration自動配置類中 有一個添加資源的方法&#xff1a; public void addResourceHandlers(ResourceHandlerRegistry registry) { //如果靜態資源已經被自定義了&#xff0c;則直接生效if (!this.resourceProperties.isAddMappings()) {logg…

基于OpenCV的人臉識別:LBPH算法

文章目錄 引言一、概述二、代碼實現1. 代碼整體結構2. 導入庫解析3. 訓練數據準備4. 標簽系統5. 待識別圖像加載6. LBPH識別器創建7. 模型訓練8. 預測執行9. 結果輸出 三、 LBPH算法原理解析四、關鍵點解析五、改進方向總結 引言 人臉識別是計算機視覺領域的一個重要應用&…

ElasticSearch重啟之后shard未分配問題的解決

以下是Elasticsearch重啟后分片未分配問題的完整解決方案&#xff0c;結合典型故障場景與最新實踐&#xff1a; 一、快速診斷定位 ?檢查集群狀態 GET /_cluster/health?pretty # status為red/yellow時需關注unassigned_shards字段值 ? 2.查看未分配分片詳情 …

CSS- 3.1 盒子模型-塊級元素、行內元素、行內塊級元素和display屬性

本系列可作為前端學習系列的筆記&#xff0c;代碼的運行環境是在HBuilder中&#xff0c;小編會將代碼復制下來&#xff0c;大家復制下來就可以練習了&#xff0c;方便大家學習。 HTML系列文章 已經收錄在前端專欄&#xff0c;有需要的寶寶們可以點擊前端專欄查看&#xff01; 點…

Git/GitLab日常使用的命令指南來了!

在 GitLab 中拉取并合并代碼的常見流程是通過 Git 命令來完成的。以下是一個標準的 Git 工作流&#xff0c;適用于從遠程倉庫&#xff08;如 GitLab&#xff09;拉取代碼、切換分支、合并更新等操作。 &#x1f310; 一、基礎命令&#xff1a;拉取最新代碼 # 拉取遠程倉庫的所…

HTML 表格與div深度解析區別及常見誤區

一、HTML<div>元素詳解 <div>是HTML中最基本的塊級容器元素&#xff0c;本身沒有語義&#xff0c;主要用于組織和布局頁面內容。以下是其核心用法&#xff1a; 1. 基礎結構與特性 <div><!-內部可包含任意HTML元素 --><h2>標題</h2><p…

mybatisPlus 新增時 其他字段的值和 id 保持一致實現方法

MyBatis-Plus 實現 sp_id_path 與 id 同步的方案 要實現新增時 sp_id_path 自動與 id 保持一致&#xff0c;需要在實體類和插入邏輯中做相應處理。MyBatis-Plus 提供了幾種方式來實現這一需求&#xff1a; 方案一&#xff1a;使用 MyBatis-Plus 的自動填充功能 這是最優雅的…

蘭亭妙微設計:為生命科技賦予人性化的交互語言

在醫療科技日新月異的今天&#xff0c;卓越的硬件性能唯有匹配恰如其分的交互語言&#xff0c;方能真正發揮價值。作為專注于醫療UI/UX設計的專業團隊&#xff0c;蘭亭妙微設計&#xff08;www.lanlanwork.com&#xff09;始終相信&#xff1a;每一處像素的排布&#xff0c;都應…

Tcping詳細使用教程

Tcping詳細使用教程 下載地址 https://download.elifulkerson.com/files/tcping/0.39/在windows環境下安裝tcping 在以上的下載地中找到exe可執行文件&#xff0c;其中tcping.exe適用于32位Windows系統&#xff0c;tcping64.exe適用于64位Windows操作系統。 其實tcping是個…

springCloud/Alibaba常用中間件之Seata分布式事務

文章目錄 SpringCloud Alibaba:依賴版本補充Seata處理分布式事務(AT模式)AT模式介紹核心組件介紹AT的工作流程&#xff1a;兩階段提交&#xff08;**2PC**&#xff09; Seata-AT模式使用Seata(2.0.0)下載、配置和啟動Seata案例實戰前置代碼添加全局注解 GlobalTransactional Sp…

COMSOL隨機參數化表面流體流動模擬

基于粗糙度表面的裂隙流研究對于理解地下水的流動、污染物傳輸以及與之相關的地質災害&#xff08;如滑坡&#xff09;等方面具有重要意義。本研究通過蒙特卡洛方法生成隨機表面形貌&#xff0c;并利用COMSOL Multiphysics對隨機參數化表面的微尺度流體流動進行模擬。 參數化…

初識——QT

QT安裝方法 一、項目創建流程 創建項目 入口&#xff1a;通過Qt Creator的歡迎頁面或菜單欄&#xff08;文件→新建項目&#xff09;創建新項目。 項目類型&#xff1a;選擇「Qt Widgets Application」。 路徑要求&#xff1a;項目路徑需為純英文且不含特殊字符。 構建系統…