使用 NanoPi R5S 和西数紫盘 WD43PURZ 组建简易 NAS
前言
大概是刚接触 OpenWrt 的那会儿,我已开始搭建并依赖内网文件共享。并且长久以来我都坚持使用路由器(或软路由)加 U 盘的组合,且一直够用。
当然在最早期是不够用的,因为那时候路由器的性能不足,SMB 这种加密传输的协议速度极低。但随着后来硬件的发展,路由器使用 SMB 已不再成为问题,所以我也就一直没有用到更专业的硬件。
动机
我正在积极开发一个软件项目,它是一个自动化的网络资源抓取/下载的工具。我想将它部署到路由器上,并于最近完成了向 ARM 架构的移植工作。测试部署并轻度试用十多天后,我的共享存储(512GB SD 卡 + 256GB U 盘)已经被占满了,我不得不探索更大空间的存储方案。
有了正经理由,使用 U 盘/SD 卡这类过家家方案的日子也才宣布终结了。
U 盘/SD 卡的缺点
首先是同等价位 U 盘/SD 卡相比机械硬盘容量太小,而寿命又明显偏低。当然不和机械硬盘比较,它们也有比较致命的缺点,尤其影响体验。
我们可以做个实验,启用 Aria2 的预分配空间功能(--file-allocation=prealloc
),并用它下载一个较大的文件到 U 盘/SD 卡中。在下载开始前的很长时间,RPC API 会无响应。例如 Aria2 的前端会获取不到数据,或者非常不稳定。而使用机械硬盘时,这种现象就不明显了。
这一点放在其它程序上也是类似的。当有进程持续向 U 盘/SD 卡写入数据时,它们的速度和响应会变得非常慢,严重影响程序的正常运作。它们不应该承受连续(长时间)的读写工作,其性能会暂时变得不稳定。
例如在撰写本文之前,我已从 U 盘迁移了数据。我注意到当数据被复制出十几 GB 后,即使是大文件的速度也已降低至 10MB/s 以下了。这种不稳定实在是有些夸张了。
虽然,我也可以继续购买所谓的“工业级” SD 卡和固态 U 盘来改进体验,但没有必要了。
硬盘盒的优势
同样是从 USB 口接入,硬盘盒相比 U 盘其实是存在先天优势的。抛开存储设备的性能/寿命不提,从传输协议上硬盘盒已胜过 U 盘。
在 USB 3.0 之前,U 盘这类 USB 存储设备的速度是非常慢的。不仅是存储设备自身的性能不够,协议也存在缺陷(并且影响至今)。要知道 USB 2.0 的理论带宽才 480Mbps(60MB/s),现在的 U 盘超过这个速度是绰绰有余了。可即使把如今的 U 盘插在 USB 2.0 上,它也达不到 2.0 的理论速度。
导致这个现象的原因是传统 USB 存储设备仍在使用 BOT(Bulk-Only Transport)协议,它是一个老旧的协议。BOT 协议在传输数据时,包会按顺序排队等待处理。即使在 USB 3.0 接口上,BOT 也明显拖了后腿。3.0 虽然让马路更宽了,但 BOT 只允许车辆排队走,无法并列更不能插队。大带宽也是浪费。
硬盘盒就不同了,它们普遍使用 UAS 协议(USB Attached SCSI Protocol,简称 UASP)。UASP 改进了 BOT 的缺陷,能够并行处理传输(流式传输,支持无序)。同时部分的协议处理任务会转移到存储设备的主控上,减轻了主机的 CPU 负担(在 ARM 软路由上还是很有意义的)。
目前 U 盘厂商仍使用 BOT 协议,毕竟它兼容性广,成本低(不需要计算能力更强的主控)。不过市面已存在一些“固态” U 盘,据我所知已使用 UASP 且其性能表现不俗。
设备
我的新方案是 ARM 架构软路由 NanoPi R5S 加西数的 4TB 紫盘(型号: WD43PURZ)以及一个 JMS578 主控芯片的硬盘盒(型号:蓝硕 MR35T)。严格来说我只是外置了一个硬盘,而不是增加了一个独立设备。
没关系,需求是一步一步来的,目前我不需要真正专业的 NAS 设备。
费用
紫盘被西数定位用于视频监控,价格低于曾广泛用于台式机的蓝盘。JMS578 也是一颗较为老旧的主控芯片(SATA 转 USB 3.0),但它已够用。
硬盘和硬盘盒的开销很低。有两个原因,一是我当前的环境并非我理想的家,我不想投入太多。二是我没有达到真正意义上的更大需要。我其实有更好的想法,参考我的完美设想。
硬盘盒
蓝硕 MR35T 是一个较为廉价的塑料外壳的硬盘盒,但严丝合缝的卡住硬盘让其不动摇还是做得到的。它的问题是主控芯片的固件版本太低了。
主控固件
如果你细心搜索过评价,可能会发现有时候同一种芯片的不同盒子,其稳定性表现或故障完全不同。这主要就是固件版本的差异导致。低版本的固件通常会有更多的问题,而这些硬盘盒的商家并不在意(或者并不懂)这些。
我并不是建议所有人都刷固件,但如果你遇到了一些不稳定/休眠方面的问题,你可以尝试一下升级固件。
下面是 JMS578 的固件和刷写工具:
待上传。
硬盘盒被我刷坏了一次。我过于自信的用 Hex 编辑器魔改固件内容,结果盒子通电后变成了一个毫无反应的设备。但我又用编程器将它救回(这我太熟悉了),切记刷固件前要备份出厂固件。
西数紫盘
在此前我有看到一些人坚持认为紫盘不能用于数据存储,因为紫盘没有纠错功能。这个说法其实是错误的。普通用户中毕竟少有能获取和阅读专业资料的人,在所谓的“监控盘”的宣传内容面前难免认知出现偏差,是可以理解的。
实际上紫盘不是“少了”纠错功能,而是多了一个功能。这个功能叫做 ATA Stream 指令集。由于监控场景是持续不断的写入数据,一旦硬盘的写入性能不稳定,视频流的输出就会受到严重影响。为了避免这种不稳定,主机通过 ATA Stream 指令告知硬盘读写特定扇区需要的时间,一旦超过这个时间硬盘就可以选择丢弃数据(或允许错误数据写入)。对于保存的监控视频而言可能就是多了一些坏点,放弃了一定的质量保证,但换来了连续、稳定的写入性能。
ATA Stream 指令在超时时,硬盘发生了什么?其中一个很大的可能性就是硬盘在纠错。正常来讲硬盘为了保证数据安全,纠错是经常发生的,有时候会纠错数次,直到彻底放弃某个扇区甚至某个磁道(俗称的坏道)。为什么坏道或者非良好的扇区、磁道延迟会更高呢?排除位置因素,主要原因就是硬盘在这些扇区和磁道写入数据时要不断的纠错和重试。正是因为有纠错功能,所以硬盘可能会产生不稳定的延迟。而 ATA Stream 指令就是阻止硬盘的纠错延迟过高影响后续写入,让硬盘放弃过高延迟的纠错。
ATA Stream 指令在电脑以及其它普通计算设备上是不存在的,它属于 SATA 协议的扩展内容。没有特别实现的标准 SATA 协议是不存在这个指令集的。监控方案因为会特别适配这些“监控盘”,所以它们会添加并使用 ATA Stream 指令。
当我们将紫盘用在一般用途时,它就是个一般的硬盘。有纠错(就是使用 ATA Stream 指令也是有纠错的),且不会启用监控需要的特殊功能。
挂载到 OpenWrt 设备
在尝试挂载前,请通过硬盘盒连接电脑并确保盒子和硬盘双方都无故障,避免做无用功的调试。
我的 R5S 固件是自己定制的,和官方或其它人发布的固件并不同。当我将装有硬盘并通上电源的硬盘盒插入 R5S 时,我注意到硬盘盒的读取指示灯并没有闪烁。通过 dmesg
命令可以查看发生了什么:
[ 375.882577] usb 8-1: new SuperSpeed USB device number 3 using xhci-hcd
最新的相关日志有且只有一条。这表示 R5S 只是正确的识别到相关类型的 USB 设备插入,但没有后续的动作。它甚至没有将此设备虚拟化到文件系统中,说简单点系统不支持此设备。
对于硬盘盒及 SATA 转 USB 3.0 的主控,通常需要系统包含 UASP(USB Attached SCSI Protocol)支持。简单检查是否包含相关驱动:
scsi
root@OpenWrt:~# lsmod | grep scsi
root@OpenWrt:~#
uas
root@OpenWrt:~# lsmod | grep uas
root@OpenWrt:~#
很可惜,它们都不存在。这表示我的 R5S 固件无法支持硬盘盒,我需要自行构建更多的驱动。根据 官方 Wiki 页面的描述,我的固件需包含 kmod-usb-storage-uas
包。如果你的设备固件并没有像我那样定制过内核,可以直接执行 opkg install kmod-usb-storage-uas
命令安装。
在构建新固件的期间,我将硬盘盒插入电脑。由于 PC 系统的内核驱动数量更多,通常它已经内置了。
这是 dmesg
:
[ 813.104486] usb 4-3: new SuperSpeed USB device number 4 using xhci_hcd
[ 813.118194] usb 4-3: New USB device found, idVendor=152d, idProduct=0562, bcdDevice= 2.14
[ 813.118199] usb 4-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 813.118202] usb 4-3: Product: External
[ 813.118205] usb 4-3: Manufacturer: JMicron
[ 813.118207] usb 4-3: SerialNumber: DD56419883891
[ 813.171270] scsi host12: uas
[ 813.171809] scsi 12:0:0:0: Direct-Access JMicron Tech 0214 PQ: 0 ANSI: 6
可以看到日志中不仅包含了检测到新的 USB 设备,还输出了我的硬盘盒主控芯片的基本信息,scsi
驱动也进行了输出。
使用 lsusb
查看连接设备:
Bus 004 Device 009: ID 152d:0562 JMicron Technology Corp. / JMicron USA Technology Corp. JMS567 SATA 6Gb/s bridge
使用 lsblk
查看块设备(也能找到它):
sdb 8:16 0 3.6T 0 disk
├─sdb1 8:17 0 16M 0 part
└─sdb2 8:18 0 3.6T 0 part
可以发现在驱动支持的情况下,Linux 能正确且迅速的识别设备。甚至比我在 Windows 尝试的结果还快还稳定。
现在回到 OpenWrt。在确保已安装 kmod-usb-storage-uas
包后,重新插入硬盘盒。新的 dmesg
:
[ 141.387722] usb 8-1: new SuperSpeed USB device number 2 using xhci-hcd
[ 141.421122] scsi host0: uas
[ 141.422651] scsi 0:0:0:0: Direct-Access JMicron Tech 0214 PQ: 0 ANSI: 6
[ 141.425570] sd 0:0:0:0: [sda] 7814037168 512-byte logical blocks: (4.00 TB/3.64 TiB)
[ 141.426281] sd 0:0:0:0: [sda] 4096-byte physical blocks
[ 141.426935] sd 0:0:0:0: [sda] Write Protect is off
[ 141.427370] sd 0:0:0:0: [sda] Mode Sense: 53 00 00 08
[ 141.428210] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 141.429368] sd 0:0:0:0: [sda] Optimal transfer size 33553920 bytes not a multiple of physical block size (4096 bytes)
[ 145.115500] sda: sda1 sda2
[ 145.118258] sd 0:0:0:0: [sda] Attached SCSI disk
准确无误!接下来就可以安全放心的使用这块硬盘了。
我的完美设想
仅靠一个硬盘盒和一个 4TB 机械硬盘,肯定是达成不了设想中的需求的。在条件满足的情况下,我必然会革新这一套,例如使用容纳多个硬盘的“硬盘柜”(其实就是容纳多个硬盘的硬盘盒)。它应该同时包含固态和机械,并组成 RAID 使用。
更重要的,我的目的是什么?存储只是基础需求而已,它本身并不能带来多大的实用性。并且毫无技术性,我并不会像业余玩家那样建立起这一套而感到兴奋。我的设想是给电视(Android TV)开发专属 APP,存储为它服务。最终达成在电视上浏览和播放内网资源的目的,且效果必定优质。
我的资源抓取工具也会 24 小时工作,将各个网站上的流行内容不间断的下载保存。目前我正在实验这一步,且已经达到十分夸张的结果。本文发表后的第四天,硬盘的 4T 空间(实际可用 3.6T)已经所剩无几了。我不得不中途手动删除一些不需要的资源,并优化程序对资源的筛选策略(如结合豆瓣的评分数据)。
如果未来本博客提及的相关软件项目会开源,我必定也会介绍它们。
一些建议
文件系统
由于挂载到 Linux 上使用,肯定是不建议 ntfs
的。推荐 ext4
,因为它是久经考验的成熟文件系统,适合作为存储盘长期稳定的使用。如果你是个人 Linux 用户我会建议 btrfs
,实际上我的电脑用的就是,但我不建议用在存储盘上。
使用 SMB 而不是 NFS
你可以同时启用这两个的服务端,在内网其它 Linux 设备上挂载 NFS,让浏览多媒体文件的设备连接 SMB。但 SMB 是不可或缺的。NFS 主要用于内网服务器间的存储共享,它缺少很多必要的功能,它并不是为解决用户设备之间的文件共享而诞生的。
结束语
此文内容应该还会继续补充,它还缺失一些经验。我可能漏掉了一些东西,以及一些还未经历的。