欢迎光临
我们一直在努力

深入理解 DM 段:掌握 Linux Device Mapper 映射单元的核心原理与实战

一、深入理解 DM 段:基础概念与体系结构

1.1 什么是 DM 段:从块设备映射谈起

DM 段 (Device Mapper Segment) 是 Linux 内核 Device Mapper 框架中描述地址映射关系的最小逻辑单元。Device Mapper 是 Linux 2.6 内核引入的块设备映射子系统,LVM、dm-crypt、multipath、docker devicemapper 存储驱动等底层均依赖它。

每一条 dm 设备的映射表由若干 DM 段顺序排列构成,每一段描述"逻辑设备的一段连续区间"与"底层物理设备的一段连续区间"之间的对应关系。可以这样理解:把一个虚拟块设备看成一本拼贴书,每一页都来自不同实体书的不同位置,DM 段就是描述"这一页来自哪本书的哪一页"的索引记录。

一个 DM 段的核心字段包括:

  • 起始扇区 (logical start sector):在 dm 设备中的起始偏移。
  • 段长度 (sector count):该段覆盖的扇区数。
  • 目标类型:linear、striped、snapshot、crypt、mirror 等。
  • 目标参数:底层设备路径与起始偏移、条带参数、加密密钥等。
  • 1.2 DM 段在 Device Mapper 中的地位:从段表到 bio 路由

    DM 段是 Device Mapper 实现一切高级语义的基础。无论多么复杂的存储栈,最终都会被拆解为若干 DM 段的线性拼接。从内核角度看,dm 设备的 dm_table 结构体内挂载了一张段表,bio 请求到来时,内核通过二分查找定位到所属 DM 段,再将 bio 重定向到该段对应的底层设备。

    #publish-mermaid-1786592576350-0{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1786592576350-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1786592576350-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1786592576350-0 .error-icon{fill:#552222;}#publish-mermaid-1786592576350-0 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1786592576350-0 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1786592576350-0 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1786592576350-0 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1786592576350-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1786592576350-0 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1786592576350-0 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1786592576350-0 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1786592576350-0 .marker.cross{stroke:#333333;}#publish-mermaid-1786592576350-0 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1786592576350-0 p{margin:0;}#publish-mermaid-1786592576350-0 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1786592576350-0 .cluster-label text{fill:#333;}#publish-mermaid-1786592576350-0 .cluster-label span{color:#333;}#publish-mermaid-1786592576350-0 .cluster-label span p{background-color:transparent;}#publish-mermaid-1786592576350-0 .label text,#publish-mermaid-1786592576350-0 span{fill:#333;color:#333;}#publish-mermaid-1786592576350-0 .node rect,#publish-mermaid-1786592576350-0 .node circle,#publish-mermaid-1786592576350-0 .node ellipse,#publish-mermaid-1786592576350-0 .node polygon,#publish-mermaid-1786592576350-0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1786592576350-0 .rough-node .label text,#publish-mermaid-1786592576350-0 .node .label text,#publish-mermaid-1786592576350-0 .image-shape .label,#publish-mermaid-1786592576350-0 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1786592576350-0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1786592576350-0 .rough-node .label,#publish-mermaid-1786592576350-0 .node .label,#publish-mermaid-1786592576350-0 .image-shape .label,#publish-mermaid-1786592576350-0 .icon-shape .label{text-align:center;}#publish-mermaid-1786592576350-0 .node.clickable{cursor:pointer;}#publish-mermaid-1786592576350-0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1786592576350-0 .arrowheadPath{fill:#333333;}#publish-mermaid-1786592576350-0 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1786592576350-0 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1786592576350-0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1786592576350-0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576350-0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576350-0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1786592576350-0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1786592576350-0 .cluster text{fill:#333;}#publish-mermaid-1786592576350-0 .cluster span{color:#333;}#publish-mermaid-1786592576350-0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1786592576350-0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1786592576350-0 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1786592576350-0 .icon-shape,#publish-mermaid-1786592576350-0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1786592576350-0 .icon-shape p,#publish-mermaid-1786592576350-0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1786592576350-0 .icon-shape .label rect,#publish-mermaid-1786592576350-0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576350-0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1786592576350-0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1786592576350-0 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1786592576350-0 [data-look=\”neo\”].node rect,#publish-mermaid-1786592576350-0 [data-look=\”neo\”].cluster rect,#publish-mermaid-1786592576350-0 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576350-0 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1786592576350-0 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1786592576350-0 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576350-0 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1786592576350-0 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576350-0 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1786592576350-0 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576350-0 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576350-0 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    上层文件系统

    dm 设备 bio 请求

    dm_table 段表查找

    DM 段 1 linear -> sda1

    DM 段 2 striped -> sdb1,sdc1

    DM 段 3 crypt -> sdd1

    底层物理设备 sda1

    底层物理设备 sdb1/sdc1

    底层物理设备 sdd1

    1.3 DM 段的常见目标类型:八种 target 的语义差异

    DM 段的"目标类型"决定了该段如何处理 IO,常见类型如下:

  • linear:最简单的线性映射,逻辑区间一一映射到底层设备的某个区间。
  • striped:条带化映射,将数据按条带轮询写入多个底层设备以提升吞吐。
  • snapshot 与 snapshot-origin:用于 LVM 快照,实现对原始设备某个时间点状态的捕获。
  • crypt:dm-crypt 加密段,对数据进行透明加解密。
  • mirror:镜像段,实现 RAID1 双写。
  • multipath:多路径段,将同一物理设备的多个路径聚合为一个逻辑视图。
  • thin 与 thin-pool:精简配置段,支持按需分配与快照链。
  • cache:缓存段,将快速设备作为慢速设备的缓存层。
  • 不同的目标类型共享同一套 DM 段抽象,这也是 Device Mapper 设计上极具扩展性的原因。

    二、DM 段:工作原理与请求路由机制

    2.1 线性映射段的实现细节:从映射表到 bio 重定向

    线性段是最基础也是最常见的 DM 段。其映射表条目格式为:

    <logical_start> <length> linear <dev> <physical_start>

    例如:

    0 2048 linear /dev/sda1 0
    2048 4096 linear /dev/sdb1 0
    6144 1024 linear /dev/sda1 2048

    上面三行表示:dm 设备的 0-2047 扇区映射到 sda1 的 0-2047;2048-6143 扇区映射到 sdb1 的 0-4095;6144-7167 扇区映射回 sda1 的 2048-3071。可以看到,DM 段并不要求底层设备连续,也不要求与 dm 设备一一对应,这正是 LVM 能够将多个物理卷拼接成线性逻辑卷的根本原因。

    当 bio 到来时,内核执行如下步骤:

  • 根据 bio 的起始扇区在 dm_table 中二分查找命中的 DM 段。
  • 计算该 bio 在该段内的相对偏移。
  • 调用该段 target_type 的 map 函数,由其改写 bio 的 bi_bdev 与 bi_sector。
  • 将 bio 提交给底层块设备驱动。
  • 2.2 条带化段与多设备并发:stripe 路由的数学逻辑

    条带化段将一段逻辑区间按固定条带大小轮询分布到多个底层设备,从而实现并发读写。其映射表条目格式为:

    <logical_start> <length> striped <num_stripes> <chunk_size> <dev1> <physical_start1> <dev2> <physical_start2> …

    条带化段的路由逻辑较为复杂:内核需要根据请求扇区号计算出"第几个条带"以及"条带内偏移",再确定该条带落在哪个底层设备,最后改写 bio 目标。下图展示了条带化段的工作流程。

    #publish-mermaid-1786592576446-1{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1786592576446-1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1786592576446-1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1786592576446-1 .error-icon{fill:#552222;}#publish-mermaid-1786592576446-1 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1786592576446-1 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1786592576446-1 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1786592576446-1 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1786592576446-1 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1786592576446-1 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1786592576446-1 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1786592576446-1 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1786592576446-1 .marker.cross{stroke:#333333;}#publish-mermaid-1786592576446-1 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1786592576446-1 p{margin:0;}#publish-mermaid-1786592576446-1 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1786592576446-1 .cluster-label text{fill:#333;}#publish-mermaid-1786592576446-1 .cluster-label span{color:#333;}#publish-mermaid-1786592576446-1 .cluster-label span p{background-color:transparent;}#publish-mermaid-1786592576446-1 .label text,#publish-mermaid-1786592576446-1 span{fill:#333;color:#333;}#publish-mermaid-1786592576446-1 .node rect,#publish-mermaid-1786592576446-1 .node circle,#publish-mermaid-1786592576446-1 .node ellipse,#publish-mermaid-1786592576446-1 .node polygon,#publish-mermaid-1786592576446-1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1786592576446-1 .rough-node .label text,#publish-mermaid-1786592576446-1 .node .label text,#publish-mermaid-1786592576446-1 .image-shape .label,#publish-mermaid-1786592576446-1 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1786592576446-1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1786592576446-1 .rough-node .label,#publish-mermaid-1786592576446-1 .node .label,#publish-mermaid-1786592576446-1 .image-shape .label,#publish-mermaid-1786592576446-1 .icon-shape .label{text-align:center;}#publish-mermaid-1786592576446-1 .node.clickable{cursor:pointer;}#publish-mermaid-1786592576446-1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1786592576446-1 .arrowheadPath{fill:#333333;}#publish-mermaid-1786592576446-1 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1786592576446-1 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1786592576446-1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1786592576446-1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576446-1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576446-1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1786592576446-1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1786592576446-1 .cluster text{fill:#333;}#publish-mermaid-1786592576446-1 .cluster span{color:#333;}#publish-mermaid-1786592576446-1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1786592576446-1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1786592576446-1 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1786592576446-1 .icon-shape,#publish-mermaid-1786592576446-1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1786592576446-1 .icon-shape p,#publish-mermaid-1786592576446-1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1786592576446-1 .icon-shape .label rect,#publish-mermaid-1786592576446-1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576446-1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1786592576446-1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1786592576446-1 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1786592576446-1 [data-look=\”neo\”].node rect,#publish-mermaid-1786592576446-1 [data-look=\”neo\”].cluster rect,#publish-mermaid-1786592576446-1 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576446-1 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1786592576446-1 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1786592576446-1 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576446-1 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1786592576446-1 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576446-1 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1786592576446-1 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576446-1 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576446-1 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}012

    bio 请求 sector=N

    计算 stripe_index = N / chunk_size

    计算 dev_index = stripe_index mod num_stripes

    计算 dev 内偏移

    dev_index 取值

    改写 bio -> dev1

    改写 bio -> dev2

    改写 bio -> dev3

    提交底层 IO

    提交底层 IO

    提交底层 IO

    条带化段常被 LVM 用于构建 stripe 类型的逻辑卷,其性能优势在大块顺序 IO 场景下尤为明显。

    2.3 DM 段的请求路由总流程:从 VFS 到底层设备

    从 bio 到达 dm 设备,到最终落到底层物理设备,整个流程可以用如下时序刻画。

    #publish-mermaid-1786592576529-2{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1786592576529-2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1786592576529-2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1786592576529-2 .error-icon{fill:#552222;}#publish-mermaid-1786592576529-2 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1786592576529-2 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1786592576529-2 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1786592576529-2 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1786592576529-2 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1786592576529-2 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1786592576529-2 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1786592576529-2 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1786592576529-2 .marker.cross{stroke:#333333;}#publish-mermaid-1786592576529-2 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1786592576529-2 p{margin:0;}#publish-mermaid-1786592576529-2 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1786592576529-2 .cluster-label text{fill:#333;}#publish-mermaid-1786592576529-2 .cluster-label span{color:#333;}#publish-mermaid-1786592576529-2 .cluster-label span p{background-color:transparent;}#publish-mermaid-1786592576529-2 .label text,#publish-mermaid-1786592576529-2 span{fill:#333;color:#333;}#publish-mermaid-1786592576529-2 .node rect,#publish-mermaid-1786592576529-2 .node circle,#publish-mermaid-1786592576529-2 .node ellipse,#publish-mermaid-1786592576529-2 .node polygon,#publish-mermaid-1786592576529-2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1786592576529-2 .rough-node .label text,#publish-mermaid-1786592576529-2 .node .label text,#publish-mermaid-1786592576529-2 .image-shape .label,#publish-mermaid-1786592576529-2 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1786592576529-2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1786592576529-2 .rough-node .label,#publish-mermaid-1786592576529-2 .node .label,#publish-mermaid-1786592576529-2 .image-shape .label,#publish-mermaid-1786592576529-2 .icon-shape .label{text-align:center;}#publish-mermaid-1786592576529-2 .node.clickable{cursor:pointer;}#publish-mermaid-1786592576529-2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1786592576529-2 .arrowheadPath{fill:#333333;}#publish-mermaid-1786592576529-2 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1786592576529-2 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1786592576529-2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1786592576529-2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576529-2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576529-2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1786592576529-2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1786592576529-2 .cluster text{fill:#333;}#publish-mermaid-1786592576529-2 .cluster span{color:#333;}#publish-mermaid-1786592576529-2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1786592576529-2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1786592576529-2 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1786592576529-2 .icon-shape,#publish-mermaid-1786592576529-2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1786592576529-2 .icon-shape p,#publish-mermaid-1786592576529-2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1786592576529-2 .icon-shape .label rect,#publish-mermaid-1786592576529-2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576529-2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1786592576529-2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1786592576529-2 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1786592576529-2 [data-look=\”neo\”].node rect,#publish-mermaid-1786592576529-2 [data-look=\”neo\”].cluster rect,#publish-mermaid-1786592576529-2 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576529-2 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1786592576529-2 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1786592576529-2 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576529-2 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1786592576529-2 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576529-2 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1786592576529-2 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576529-2 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576529-2 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}linearstripedcryptsnapshot

    VFS 层 read/write

    page cache / direct IO

    提交 bio 到 dm 设备

    dm_deferred_io 或直接 map

    dm_table 段表二分查找

    命中 DM 段

    调用 target_type.map

    目标类型

    直接改写 bi_bdev/bi_sector

    计算条带后改写

    加密后改写并克隆 bio

    判断 COW 路径

    submit_bio 到底层设备

    底层驱动处理 IO

    理解这一流程,对后续排错与性能调优至关重要。

    三、DM 段:配置实战与运维排错

    3.1 查看 DM 段映射表:dmsetup 五步法

    Linux 提供了多种方式查看 dm 设备的 DM 段信息,最常用的是 dmsetup 工具。

    操作步骤:

  • 使用 lsblk 找到目标 dm 设备名,例如 dm-0、dm-1,或其符号链接 vg-root。
  • 执行 dmsetup info /dev/mapper/vg-root 查看设备基本信息,包括 UUID、状态、块数。
  • 执行 dmsetup table /dev/mapper/vg-root 输出 DM 段映射表,格式与第 2.1 节一致。
  • 执行 dmsetup deps /dev/mapper/vg-root 查看该 dm 设备依赖的底层块设备。
  • 若需要更可读的输出,可使用 dmsetup ls –tree 查看整个 dm 设备树形拓扑。
  • 示例输出:

    $ dmsetup table /dev/mapper/vg-root
    0 209715200 linear /dev/sda3 2048
    209715200 104857600 linear /dev/sdb1 0

    上面输出表示该逻辑卷由两段构成,分别落在 sda3 与 sdb1 上。

    3.2 创建与管理 DM 段设备:手动构造线性卷

    通过 dmsetup create 可以手动构造一个 dm 设备,完全掌控 DM 段的布局。下面以创建一个由两块磁盘拼成的线性设备为例。

    操作步骤:

  • 准备两块空闲分区 /dev/sdb1 与 /dev/sdc1,确保没有其他设备占用。
  • 编写映射表文件 /etc/dm/mylinear.table,内容如下:
  • 0 1048576 linear /dev/sdb1 0
    1048576 1048576 linear /dev/sdc1 0

  • 执行 dmsetup create mylinear /etc/dm/mylinear.table 创建 dm 设备,设备节点为 /dev/mapper/mylinear。
  • 执行 blockdev –getsize64 /dev/mapper/mylinear 确认设备容量。
  • 对该设备创建文件系统:mkfs.xfs /dev/mapper/mylinear。
  • 挂载并使用:mount /dev/mapper/mylinear /mnt/mylinear。
  • 若要持久化,可执行 dmsetup mknodes 并将映射规则写入自定义 udev 规则,或使用 systemd unit 在启动时执行 dmsetup create。
  • #publish-mermaid-1786592576645-3{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1786592576645-3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1786592576645-3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1786592576645-3 .error-icon{fill:#552222;}#publish-mermaid-1786592576645-3 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1786592576645-3 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1786592576645-3 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1786592576645-3 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1786592576645-3 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1786592576645-3 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1786592576645-3 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1786592576645-3 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1786592576645-3 .marker.cross{stroke:#333333;}#publish-mermaid-1786592576645-3 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1786592576645-3 p{margin:0;}#publish-mermaid-1786592576645-3 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1786592576645-3 .cluster-label text{fill:#333;}#publish-mermaid-1786592576645-3 .cluster-label span{color:#333;}#publish-mermaid-1786592576645-3 .cluster-label span p{background-color:transparent;}#publish-mermaid-1786592576645-3 .label text,#publish-mermaid-1786592576645-3 span{fill:#333;color:#333;}#publish-mermaid-1786592576645-3 .node rect,#publish-mermaid-1786592576645-3 .node circle,#publish-mermaid-1786592576645-3 .node ellipse,#publish-mermaid-1786592576645-3 .node polygon,#publish-mermaid-1786592576645-3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1786592576645-3 .rough-node .label text,#publish-mermaid-1786592576645-3 .node .label text,#publish-mermaid-1786592576645-3 .image-shape .label,#publish-mermaid-1786592576645-3 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1786592576645-3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1786592576645-3 .rough-node .label,#publish-mermaid-1786592576645-3 .node .label,#publish-mermaid-1786592576645-3 .image-shape .label,#publish-mermaid-1786592576645-3 .icon-shape .label{text-align:center;}#publish-mermaid-1786592576645-3 .node.clickable{cursor:pointer;}#publish-mermaid-1786592576645-3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1786592576645-3 .arrowheadPath{fill:#333333;}#publish-mermaid-1786592576645-3 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1786592576645-3 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1786592576645-3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1786592576645-3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576645-3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576645-3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1786592576645-3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1786592576645-3 .cluster text{fill:#333;}#publish-mermaid-1786592576645-3 .cluster span{color:#333;}#publish-mermaid-1786592576645-3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1786592576645-3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1786592576645-3 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1786592576645-3 .icon-shape,#publish-mermaid-1786592576645-3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1786592576645-3 .icon-shape p,#publish-mermaid-1786592576645-3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1786592576645-3 .icon-shape .label rect,#publish-mermaid-1786592576645-3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576645-3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1786592576645-3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1786592576645-3 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1786592576645-3 [data-look=\”neo\”].node rect,#publish-mermaid-1786592576645-3 [data-look=\”neo\”].cluster rect,#publish-mermaid-1786592576645-3 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576645-3 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1786592576645-3 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1786592576645-3 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576645-3 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1786592576645-3 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576645-3 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1786592576645-3 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576645-3 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576645-3 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    准备 sdb1/sdc1

    编写映射表文件

    dmsetup create

    生成 /dev/mapper/mylinear

    mkfs.xfs

    mount

    业务读写

    umount

    dmsetup remove

    3.3 DM 段的监控与排错:常见故障速查路径

    DM 段相关的故障通常表现为 IO 卡顿、设备状态 suspended、映射表与底层设备不一致等。下面给出常用的排查路径。

    操作步骤:

  • 执行 dmsetup info 查看 dm 设备的 State 字段,若为 SUSPENDED 则说明设备被挂起,常见于 lvm 操作中或 dmsetup suspend 未及时 resume。
  • 执行 dmsetup status /dev/mapper/vg-root 查看各 DM 段的运行时状态。对于 striped 段,可看到各底层设备的 IO 计数;对于 thin 段,可看到已分配数据块数与元数据使用率。
  • 通过 cat /sys/block/dm-0/dm/name 与 /sys/block/dm-0/slaves/ 确认 dm 设备名称与其依赖的底层设备。
  • 若怀疑某段性能异常,可使用 iostat -xmd 1 观察 dm-X 与底层 sdX 的对比,判断瓶颈落在哪一段。
  • 出现 device-mapper: reload ioctl failed 类错误时,多半是新映射表与已有 DM 段边界不匹配,应使用 dmsetup table –verbose 核对段长度总和是否等于设备容量。
  • 对于 dm-crypt 段无法解锁的情况,检查 /etc/crypttab 与 keyslot 是否一致,必要时使用 cryptsetup luksDump 与 cryptsetup open –test-passphrase 验证。
  • 常见问题速查:

    #publish-mermaid-1786592576710-4{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1786592576710-4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1786592576710-4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1786592576710-4 .error-icon{fill:#552222;}#publish-mermaid-1786592576710-4 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1786592576710-4 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1786592576710-4 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1786592576710-4 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1786592576710-4 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1786592576710-4 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1786592576710-4 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1786592576710-4 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1786592576710-4 .marker.cross{stroke:#333333;}#publish-mermaid-1786592576710-4 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1786592576710-4 p{margin:0;}#publish-mermaid-1786592576710-4 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1786592576710-4 .cluster-label text{fill:#333;}#publish-mermaid-1786592576710-4 .cluster-label span{color:#333;}#publish-mermaid-1786592576710-4 .cluster-label span p{background-color:transparent;}#publish-mermaid-1786592576710-4 .label text,#publish-mermaid-1786592576710-4 span{fill:#333;color:#333;}#publish-mermaid-1786592576710-4 .node rect,#publish-mermaid-1786592576710-4 .node circle,#publish-mermaid-1786592576710-4 .node ellipse,#publish-mermaid-1786592576710-4 .node polygon,#publish-mermaid-1786592576710-4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1786592576710-4 .rough-node .label text,#publish-mermaid-1786592576710-4 .node .label text,#publish-mermaid-1786592576710-4 .image-shape .label,#publish-mermaid-1786592576710-4 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1786592576710-4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1786592576710-4 .rough-node .label,#publish-mermaid-1786592576710-4 .node .label,#publish-mermaid-1786592576710-4 .image-shape .label,#publish-mermaid-1786592576710-4 .icon-shape .label{text-align:center;}#publish-mermaid-1786592576710-4 .node.clickable{cursor:pointer;}#publish-mermaid-1786592576710-4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1786592576710-4 .arrowheadPath{fill:#333333;}#publish-mermaid-1786592576710-4 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1786592576710-4 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1786592576710-4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1786592576710-4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576710-4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576710-4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1786592576710-4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1786592576710-4 .cluster text{fill:#333;}#publish-mermaid-1786592576710-4 .cluster span{color:#333;}#publish-mermaid-1786592576710-4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1786592576710-4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1786592576710-4 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1786592576710-4 .icon-shape,#publish-mermaid-1786592576710-4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1786592576710-4 .icon-shape p,#publish-mermaid-1786592576710-4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1786592576710-4 .icon-shape .label rect,#publish-mermaid-1786592576710-4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1786592576710-4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1786592576710-4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1786592576710-4 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1786592576710-4 [data-look=\”neo\”].node rect,#publish-mermaid-1786592576710-4 [data-look=\”neo\”].cluster rect,#publish-mermaid-1786592576710-4 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576710-4 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1786592576710-4 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1786592576710-4 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576710-4 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1786592576710-4 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576710-4 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1786592576710-4 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576710-4 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1786592576710-4 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}State=SUSPENDEDreload ioctl failedIO 慢crypt 解锁失败thin 池满

    DM 设备异常

    现象

    dmsetup resume 恢复

    核对段边界与总长度

    iostat 定位瓶颈段

    校验 keyslot/crypttab

    扩容 thin-pool 或回收快照

    恢复正常服务

    掌握 DM 段的查看、构造与排查方法,就掌握了 Linux 块设备虚拟化栈的钥匙。无论是 LVM、容器存储驱动,还是加密卷、多路径,最终都可以回归到对 DM 段映射表的理解与操作,这是排查底层存储问题的根本路径。

    赞(0)
    未经允许不得转载:171主机测评 » 深入理解 DM 段:掌握 Linux Device Mapper 映射单元的核心原理与实战
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址