FreeBSD 中文社区 2025 第二季度问卷调查
FreeBSD 中文社区(CFC)
VitePress 镜像站QQ 群 787969044视频教程Ⅰ视频教程Ⅱ
  • FreeBSD 从入门到追忆
  • 中文期刊
  • 状态报告
  • 发行说明
  • 手册
  • 网络文章集锦
  • 笔记本支持报告
  • Port 开发者手册
  • 架构手册
  • 开发者手册
  • 中文 man 手册
  • 文章
  • 书籍
  • FreeBSD 中文期刊
  • 编辑日志
  • 2025-123 下游项目
    • FreeBSD 发布工程:新主管上任
    • GhostBSD:从易用到挣扎与重生
    • BSD Now 与将来
    • 字符设备驱动教程(第三部分)
    • 学会走路——连接 GPIO 系统
    • FreeBSD 中对 SYN 段的处理
    • FreeBSD 2024 年秋季峰会
  • 2024-1112 虚拟化
    • 字符设备驱动程序教程(第二部分)
    • 面向 Linux 和 Windows 用户的 bhyve
    • Xen 与 FreeBSD
    • Wifibox:一种嵌入式虚拟化无线路由器
    • 嵌入式 FreeBSD:Fabric——起步阶段
    • DGP:一种新的数据包控制方法
    • 会议报告:我在都柏林的 EuroBSDCon 体验
  • 2024-0910 内核开发
    • 字符设备驱动程序教程
    • VPP 移植到了 FreeBSD:基础用法
    • 利用 Kyua 的 Jail 功能提升 FreeBSD 测试套件的并行效率
    • FreeBSD 上的 Valgrind
    • 嵌入式 FreeBSD:探索 bhyve
    • TCP/IP 历险记:FreeBSD TCP 协议栈中的 Pacing
    • 实用软件:实现无纸化(Paperless)
  • 2024-0708 存储与文件系统
    • FreeBSD 中的 NVMe-oF
    • FreeBSD iSCSI 入门
    • 使用 ZFS 原生加密保护数据
    • 嵌入式 FreeBSD:打造自己的镜像
    • TCP LRO 简介
    • 基于 Samba 的时间机器备份
  • 2024-0506 配置管理对决
    • 基本系统中的 mfsBSD
    • rdist
    • Hashicorp Vault
    • 在 GitHub 上向 FreeBSD 提交 PR
    • 悼念 Mike Karels
    • 2024 年 5-6 月来信
    • 嵌入式 FreeBSD 面包板
    • TCP/IP 历险记:TCP BBLog
    • 实用软件:开发定制 Ansible 模块
  • 2024-0304 开发工作流与集成
    • FreeBSD 内核开发工作流程
    • FreeBSD 与 KDE 持续集成(CI)
    • 更现代的内核调试工具
    • 从零开始的 ZFS 镜像及 makefs -t zfs
    • 提升 Git 使用体验
  • 2024-0102 网络(十周年)
    • FreeBSD 中的 RACK 栈和替代 TCP 栈
    • FreeBSD 14 中有关 TCP 的更新
    • if_ovpn 还是 OpenVPN
    • SR-IOV 已成为 FreeBSD 的重要功能
    • FreeBSD 接口 API(IfAPI)
    • BATMAN:更优的可移动热点网络方式
    • 配置自己的 VPN——基于 FreeBSD、Wireguard、IPv6 和广告拦截
    • 实用软件:使用 Zabbix 监控主机
  • 2023-1112 FreeBSD 14.0
    • LinuxBoot:从 Linux 启动 FreeBSD
    • FreeBSD 容器镜像
    • 现在用 Webhook 触发我
    • 新的 Ports 提交者:oel Bodenmann (jbo@freebsd.org)
  • 2023-0910 Port 与软件包
    • 回忆录:与 Warner Losh(@imp)的访谈
    • 在你自己的仓库中定制 Poudriere 源
    • Wazuh 和 MITRE Caldera 在 FreeBSD Jail 中的使用
    • PEP 517
    • CCCamp 2023 旅行报告
  • 2023-0708 容器与云
    • 在 Firecracker 上的 FreeBSD
    • 使用 pot 和 nomad 管理 Jail
    • 会议报告:C 与 BSD 正如拉丁语与我们——一位神学家的旅程
    • 抒怀之旅:与 Doug Rabson 的访谈
    • 基于 Jail 的广告拦截教程
    • 我们收到的来信
  • 2023-0506 FreeBSD 三十周年纪念特刊
    • CheriBSD 近十多年的历程
    • AArch64:成为 FreeBSD 新的一级架构
    • 岁月如梭:我个人的时间线
    • 安装 FreeBSD 1.0:回顾 30 年前
    • ZFS 是如何进入 FreeBSD 的呢?
    • 我不是来自约克郡的,我保证!
    • 回忆录:采访 David Greenman Lawrence
    • FreeBSD 和早期的 Unix 社区
    • 早期的 FreeBSD 移植
    • FreeBSD 30 周年:成功的秘诀
    • FreeBSD 在日本:回忆之旅与今日之实
  • 2023-0304 嵌入式
    • CheriBSD port 和软件包
    • 让我们来试试 ChatGPT
    • GPU 直通
  • 2023-0102 构建 FreEBSD Web 服务器
    • ZFS 的原子 I/O 与 PostgreSQL
    • 虚拟实验室——BSD 编程研讨会
    • ZFS 简介
    • 会议报告:落基山庆祝女性计算机科学家
    • 进行中的工作/征求反馈:数据包批处理
    • 基金会与 FreeBSD 桌面
  • 2022-1112 可观测性和衡量标准
    • 在 FreeBSD 的 DDB 内核调试器中编写自定义命令
    • DTrace:老式跟踪系统的新扩展
    • 基于证书的 Icinga 监控
    • 活动监控脚本(activitymonitor.sh)
    • 实用 IPv6(第四部分)
    • EuroBSDCon 会议报道
    • 实用 Port:Prometheus 的安装与配置
    • 书评:《用火解决问题:管理老化的计算机系统(并为现代系统保驾护航)》Kill It with Fire: Manage Aging Computer Systems (and Future Proof Modern Ones)
  • 2022-0910 安全性
    • CARP 简介
    • 重构内核加密服务框架
    • PAM 小窍门
    • SSH 小窍门
    • 实用 IPv6(第三部分)
    • 书评:Understanding Software Dynamics(深入理解软件性能——一种动态视角)—— Richard L. Sites 著
    • 访谈:保障 FreeBSD 安全性
    • MCH 2022 会议报告
  • 2022-0708 科研、系统与 FreeBSD
    • 在 FreeBSD 上构建 Loom 框架
    • 教授本科生 Unix 课程
    • FreeBSD 入门研讨会
    • 实用 IPv6(第二部分)
    • 在 2022 年及以后推广 FreeBSD
    • 进行中的工作/征求反馈:Socket 缓冲区
    • FreeBSD 开发者峰会报告
    • 支持 Electromagnetic Field 2022
  • 2022-0506 灾难恢复
    • 使用 FreeBSD 构建高弹性的私有云
    • LLDB 14 —— FreeBSD 新调试器
    • 实用 IPv6(第一部分)
    • 利用 netdump(4) 进行事后内核调试
    • 进行中的工作/征求反馈:FreeBSD 启动性能
    • 实用 Port:在 OpenZFS 上设置 NFSv4 文件服务器
  • 2022-0304 ARM64 是一级架构
    • FreeBSD/ARM64 上的数据科学
    • Pinebook Pro 上的 FreeBSD
    • 嵌入式控制器的 ACPI 支持
    • 进行中的工作/征求反馈:Lumina 桌面征集开发人员
    • 实用 Port:如何设置 Apple 时间机器
  • 2022-0102 软件与系统管理
    • 为 FreeBSD Ports 做贡献
    • 使用 Git 贡献到 FreeBSD Ports
    • CBSD:第一部分——生产环境
    • 将 OpenBSD 的 pf syncookie 代码移植到 FreeBSD 的 pf
    • 进行中的工作/征求反馈:mkjail
    • 《编程智慧:编程鬼才的经验和思考》(The Kollected Kode Vicious)书评
    • 会议报告:EuroBSDCon 2021 我的第一次 EuroBSDCon:一位新组织者的视角
  • 2021-1112 存储
    • 开放通道 SSD
    • 构建 FreeBSD 社区
    • 与完美操作系统同行 27 年
    • 进行中的工作/征求反馈:OccamBSD
    • 通过 iSCSI 导入 ZFS ZIL——不要在工作中这样做——就像我做的那样
  • 2021-0910 FreeBSD 开发
    • FreeBSD 代码审查与 git-arc
    • 如何为 FreeBSD 实现简单的 USB 驱动程序
    • 内核开发技巧
    • 程序员编程杂谈
  • 2021-0708 桌面/无线网
    • 通往 FreeBSD 桌面的直线路径
    • FreeBSD 13 中的人机接口设备 (HID) 支持
    • Panfrost 驱动程序
    • 用 Git 更新 FreeBSD
    • FreeBSD 的新面孔
    • 想给你的桌面加点佐料?
  • 2021-0506 安全
    • 七种提升新安装 FreeBSD 安全性的方法
    • copyinout 框架
    • 使用 TLS 改善 NFS 安全性
    • Capsicum 案例研究:Got
    • 对 Jail 进行安全扫描
  • 2021-0304 FreeBSD 13.0
    • 展望未来
    • FreeBSD 13.0 工具链
    • FreeBSD 13.0 中有新加载器吗?
    • TCP Cubic 准备起飞
    • OpenZFS 中的 Zstandard 压缩
    • 会议报告:FreeBSD 供应商峰会
    • Git 不够吗?
  • 2021-0102 案例研究
    • Tarsnap 的 FreeBSD 集群
    • BALLY WULFF
    • Netflix Open Connect
    • FreeBSD 的新面孔
    • 写作学者的 FreeBSD
    • 在世界之巅
  • 2020-1112 工作流/持续集成(CI)
    • FreeBSD Git 快速入门
    • 使用 syzkaller 进行内核 Fuzzing
    • Mastering Vim Quickly 书评
    • 线上会议实用技巧
    • 在控制台上进行网络监控
  • 2020-0910 贡献与入门
    • 采访:Warner Losh,第 2 部分
    • 代码审查
    • 撰写良好的提交消息
    • 如何在不是程序员的情况下做出贡献——成为 FreeBSD 译者
    • 如何成为文档提交者
    • 谷歌编程之夏
    • 为 FreeBSD 期刊撰写文章
    • 你为什么使用 FreeBSD
    • FreeBSD 的新面孔
  • 2020-0708 基准测试/调优
    • FreeBSD Friday
    • 采访:Warner Losh,第 1 部分
    • 构建和运行开源社区
    • 在 FreeBSD 上轻松搭建我的世界(Minecraft)服务器
    • FreeBSD 的新面孔
  • 2020-0506 网络性能
    • 内核中的 TLS 卸载
    • 访谈:Michael W Lucas
    • FreeBSD 桌面发行版
    • 使用 Poudriere 进行 Port 批量管理
    • FreeBSD 的新面孔
由 GitBook 提供支持
LogoLogo

FreeBSD 中文社区(CFC) 2025

在本页
在GitHub上编辑
导出为 PDF
  1. 2021-1112 存储

开放通道 SSD

上一页会议报告:EuroBSDCon 2021 我的第一次 EuroBSDCon:一位新组织者的视角下一页构建 FreeBSD 社区

最后更新于22天前

NAND 闪存固态硬盘广泛用作主要存储设备,因其低功耗和高性能。然而,固态硬盘存在不可预测的 IO 延迟、日志重叠问题以及资源利用不足等问题。

  • 原文链接:

  • 作者:ARKA SHARMA、AMIT KUMAR、ASHUTOSH SHARMA

随着固态硬盘的普及,对更可预测的 IO 延迟的需求也在增长。传统的固态硬盘通常向主机暴露一个块接口,但常常无法满足这一需求。原因在于 NAND 闪存的工作方式。通常,在固态硬盘内部,闪存被划分为由多个芯片组成的单元。每个芯片包含若干个 die,每个 die 可以独立执行闪存命令(读/写/擦除)。这些 die 内部包含多个 plane,多个 plane 可以一次性执行相同的闪存命令,从而提高效率。每个 plane 内包含多个块,块是擦除单位,而块内包含的页则是读写单位。

这些芯片可以组织成多个通道,能够独立地在 NAND 和闪存控制器之间进行数据传输。众所周知,NAND 中的页无法被直接覆盖,因此必须先擦除一个块,然后才能将新数据写入该块的页。块的擦除次数是有限的,这个次数也叫做 PE(编程/擦除)次数,不同类型的 NAND 的 PE 次数各不相同。例如,SLC NAND 的 PE 次数大约为 100,000,MLC 的 PE 次数在 1,000 到 3,000 之间,而 TLC 的 PE 次数范围则是 100 到 300。通常,固态硬盘内部会运行一个闪存转换层(FTL),它实现了一个日志结构方案,通过使前一个内容失效来为主机提供就地更新的抽象。FTL 还实现了一个映射方案来支持这一过程。

与任何日志结构实现一样,随着时间的推移,写操作会导致碎片化,从而需要进行垃圾回收(GC)以擦除无效数据并创建空闲块。在固态硬盘的情况下,这意味着需要将有效页从一个块(GC 源)移动到另一个块(GC 目标),然后擦除源块并将其标记为空闲。整个任务对主机是透明的,但主机会遭遇固态硬盘性能下降,同时,GC 操作还会影响闪存介质的使用寿命,因为它将有效数据写入 GC 目标块。已有若干研究和解决方案来减轻这一问题,如引入 TRIM/UNMAP 机制,旨在通过以某种方式使主机的数据无效,从而最小化 GC 操作中需要移动的页数。多流固态硬盘是一种尝试将数据按生命周期相似的方式存储在同一个擦除块中的技术,从而减少碎片化,这也在一定程度上缓解了 GC 的压力。工作负载分类是另一种减少碎片化的方式。开放通道固态硬盘(OCSSD)则通过将部分 FTL 的职责转移给主机来提高预测性和更好的资源利用。通常,固态硬盘的职责可以分为以下几个类别:数据放置、I/O 调度、介质管理、逻辑到物理(L2P)地址转换和错误恢复。

OC 固态硬盘可以将全部(完全主机管理的开放通道固态硬盘(1.2))或部分(主机驱动的开放通道固态硬盘(2.0))职责转移给主机。我们的工作受 LightNVM 启发,LightNVM 是 Linux 实现的开放通道固态硬盘,Linux 特有的部分已被修改以适应 FreeBSD 的生态系统。正如在 LightNVM 中观察到的,共享职责模型能够更好地平衡各方,而不会过度增加主机的负担。我们探索了一种 OC 固态硬盘模型,其中数据放置、L2P 管理、I/O 调度和部分 NAND 管理由主机完成。错误检测和恢复等任务仍然在设备端进行。OC 固态硬盘向主机暴露一个通用的抽象几何结构,包括介质(NAND)的几何信息、磨损均衡阈值、读/写/擦除时序以及写入约束(最小/最佳写入大小)。

几何信息通常通过通道数、芯片、块和页数来描述底层 NAND 媒体中的并行性。主机可以通过命令查询块的状态,并获得以下信息:LBA 起始地址、块内当前写入偏移量以及块的状态(已满、空闲、开放、坏块)。驱动器提供关于块健康状况的实时反馈,从而提醒主机在需要时将数据从这些块中移走。

目前,基本的读写用例已经通过 FIO 测试,但由于带宽不可用,垃圾回收(GC)这一必须具备的功能尚未开发。所有开发工作都在 QEMU 上进行,因此当前也没有性能基准数据。在我们收到有关 Linux 5.15 中移除 LightNVM 的更新之前,我们计划将这一解决方案实现为 GEOM 类,并结合一些特定的方案,例如使用带有 NVRAM/NVDIMM/PCM 缓存的自定义设备,并与开放通道固态硬盘配合使用。但现在,我们已决定放弃这些想法。未来,我们期待参与 FreeBSD 中与 NVMe ZNS 相关的工作。

我们将工作分为两个部分:我们称之为 pblk 的 FTL 部分和我们称之为 lightnvm 的驱动程序,命名方式与 Linux 中的 LightNVM 保持一致。我们遵循 nvd 模型编写了 lightnvm 驱动程序。lightnvm 驱动程序创建了一个 DEVFS 条目“lightnvm/control”,可以通过该条目由各种工具(如 nvmecli)管理 OC 固态硬盘设备。我们在 nvmecli 中添加了对 OC 固态硬盘设备的支持。底层 NVMe 驱动程序(sys/dev/nvme)初始化设备并通知 lightnvm 驱动程序。lightnvm 驱动程序将设备注册到 lightnvm 子系统,lightnvm 系统启动初始化过程,并通过 NVMe Geometry 管理命令(http://lightnvm.io/docs/OCSSD-2_0-20180129.pdf)从设备查询底层介质的几何信息。设备几何信息填充完成后,lightnvm 子系统将设备及其几何信息和其他 NAND 属性注册。

当用户通过 nvmecli 发起创建 OC 固态硬盘目标时,lightnvm 驱动程序从 OC 固态硬盘中划分出请求的空间,并为该目标创建一个与 geom 子系统交互的“磁盘”实例。I/O 请求通过策略例程进行拦截,并转发到 pblk 子系统进行进一步处理。I/O 操作完成后,nvme 会通知 lightnvm,lightnvm 将通知 pblk,并最终传递到 geom 层。

我们将 pblk 层中的 FTL 算法保持与 LightNVM 大致相同。我们将映射单元定义为 4K(也称为扇区),这意味着每个大小为 4K 的逻辑页将映射到物理页的 4K 部分,而物理页通常大于 4K。我们使用 nvmecli 来划分并创建目标。在创建目标时,我们可以选择目标类型,从而选择底层的 FTL(如果有多个 FTL 的话)。

如前所述,NAND 被划分为芯片/Die/Plane/块。在 LightNVM 的背景下,并保持与 OC 固态硬盘规范一致的术语,我们将通道称为组,将芯片称为 PU(并行单元),将块称为 Chunk。OC 固态硬盘规范还定义了物理页地址(PPA),它通过组、PU、Chunk 和 Chunk 内的页号来定位 NAND 中的物理页。符合 OC 固态硬盘规范的设备通过 OC 固态硬盘规范中定义的 "geometry" 命令暴露 NAND 几何信息,并对底层 NAND 媒体的一些特殊性进行了抽象。这允许用户选择目标的一部分并选择起始和结束的并行单元。这样也使得底层 FTL 能够定义“行”(lines),即跨不同并行单元的块数组,从而可以将数据条带化,以利用底层 NAND 的并行性。可以通过两种方式实现这一点:如果目标包含连接到不同 NAND 通道的 PU,那么固态硬盘控制器可以同时将数据发送到 NAND 或从 NAND 接收数据。如果目标的 PU 连接到相同的通道,那么数据流就不能并行进行。然而,待数据流完成并且闪存命令在 PU 内部执行,通道就可以被用于将数据传输到/从其他 PU。在目标只包含一个 PU 的情况下,正如预期的那样,我们不能实现并行性。

在写入数据时,我们通常会将数据写入缓存,并将成功状态返回给 geom。我们有一个写线程将缓存中的数据写入 NAND。缓存的大小计算为必须容纳在某个页之前要写入的页数,这些页必须写入缓存,以便能够从该页读取数据。假设底层 NAND 有一个限制,即在一个页之前必须写入 16 个物理页,假设我们想从第 10 页读取数据。为了可靠地从该块中读取数据,必须写入直到第 26 页。如果我们考虑条带化操作,将需要更多时间来填充这些页,因为行中的所有块都将有相同的限制。此外,我们还必须确保缓存中可以容纳一次向量写入命令中可以写入的块中最大扇区数。这是因为块可能发生编程失败,并且为了替换块并重试写入命令,我们需要将这些数据保留在缓存中。缓存必须能够容纳这些数据,乘以目标中 PU 的数量。因此,为了避免数据丢失,我们需要确保这些页可以适配到缓存中。L2P 映射数据保存在三个地方:在主机内存中,映射整个目标;在行的末尾,仅映射该行中写入的页;以及在物理页的备用区域,包含逻辑页的数据。如前所述,由于带宽不可用,垃圾回收(GC)尚未实现。

如上所述,我们有一个写线程,它从缓存中读取数据并将其写入 NAND 设备。由于我们将设备的映射单元定义为 4K 大小,因此我们按条目划分缓存和环形缓冲区,每个条目对应 4K 的用户数据。我们在环形缓冲区中存储一些计数器,这些计数器充当指针,指导写线程选择正确的环形缓冲区条目,将数据刷新到 NAND 设备,确认刷新成功,并更新 L2P 映射,使逻辑页映射到物理页,而不是缓存条目。这些计数器存储缓存信息,例如:缓存的大小(按环形缓冲区条目计算,4K)、缓存中可写/空闲的条目数量、尚未提交到 NAND 设备的条目数量、尚未从设备接收确认的条目、已经从设备收到确认的条目,以及需要从缓存地址更新到设备 PPA 的物理映射的条目。因此,现在借助这些计数器,写线程将计算需要刷新到设备的环形缓冲区条目。接着,它将检查需要刷新的条目数是否大于最小写入页数据(即最佳写入大小)。假设最佳写入大小为 8 个扇区(8 * 4K)。如果条目数少于 8,则线程将退出并在下次运行时重试。但如果条目数大于或等于 8(最佳写入大小),则它将从缓存中读取这些条目。在形成向量化写入命令以将数据写入物理页时,我们为每个页创建一个元数据区域,并在其中写入关联页的 LBA。这样做是为了在发生断电时能够恢复映射。在当前的实现中,我们只有一个活动的写入端,这意味着我们将一直写入同一行,直到该行写满或发生编程失败。在这种情况下,我们将分配一个新行并继续写入。当内存页面中有 8 个(最佳写入大小)扇区(数据 + 元数据)可用时,我们将数据写入设备,并更新设备的写指针(WP),同时 NAND 页内部的 LBA 信息将在备用区域更新。如果设备的写请求失败,我们将把这些失败的 I/O 添加到重新提交队列中。重新提交队列的消费者仍然是写线程。这时,写线程将只读取环形缓冲区(缓存)中的失败条目。因此,如果条目数少于 8(最佳写入大小),我们将添加填充(虚拟页),并将写请求重新提交给设备。

对于读请求,我们接收到需要读取的扇区数量、起始扇区和数据缓冲区,这些信息封装在一个 bio 结构中。假设有一个读取 8 个扇区的请求。首先,我们读取第一个扇区的 L2P 映射。如果第一个请求扇区的逻辑地址映射到缓存中,即数据位于缓存/环形缓冲区中,那么我们计算数据存储在缓存中的连续扇区数量。假设所有 8 个扇区的逻辑地址都映射到缓存,那么我们只需要将这 8 个扇区的数据从缓存复制到读取的 bio 结构的页中,并调用 bio_done 将数据返回给上层(geom)。

在另一种情况下,如果第一个请求扇区映射到设备,我们计算数据存储在设备中的连续扇区数量,并为这些连续扇区创建一个子 bio,使用适当的 PPA 向设备发送读取请求。假设所有 8 个扇区的逻辑地址都映射到 NAND 设备,那么我们将创建一个包含 8 个页的子 bio,并将这 8 个扇区的读取请求发送到设备。与此同时,父(读取)bio 会等待,直到收到设备的读取完成确认。之后,GEOM 发送的读取 bio 将使用子 bio 中读取的数据更新其缓冲区,并调用 bio_done 将数据发送回 geom。

现在还有另一种混合情况,其中部分数据位于设备上,剩余数据位于缓存中。假设前两个扇区位于设备上,第三和第四扇区位于缓存中,其余四个扇区再次位于设备上。那么,第一步与之前相同,即我们发现第一个扇区的映射在设备上,连续扇区的数量为 2。我们创建一个包含两个页的子 bio,向设备发送读取请求。接下来,我们会发现第三个扇区的逻辑地址映射在缓存中,再次得到连续扇区数量为 2。因此,我们读取两个合适的环形缓冲区条目,并将它们的数据复制到读取(父)bio 的页中。接下来,我们发现第五个扇区的映射在设备上,连续扇区数量为 4。这时,我们创建另一个子 bio 从设备读取剩余的四个扇区。父(读取)bio 必须等待,直到收到设备对两个子 BIO 的确认。最终,读取 I/O 将从两个子 BIO 和缓存中获取数据,然后我们调用 bio_done 完成读取请求。


ARKA SHARMA 具有在各种存储组件(如驱动程序、FTL 和 option ROM)上的工作经验。在 2019 年进入 FreeBSD 之前,他曾在 WDM mini-port 和 UEFI 驱动程序方面工作。

AMIT KUMAR 是一名系统软件开发人员,目前从事基于 FreeBSD 的存储产品工作。他自 2019 年起成为 FreeBSD 用户。在业余时间,他喜欢探索 FreeBSD I/O 堆栈。

ASHUTOSH SHARMA 目前在 Isilon 担任软件工程师。他的主要兴趣领域是存储子系统。在过去,他曾在 Linux md-raid 上工作。

Open Channel 固态硬盘