在 Arch Linux 上构建 NAS

本文将简述近期笔者在 Arch Linux 上自建 NAS 的过程,兼谈个人对 NAS 的思考和看法。本文主要起记录作用,并不作为配置参考。

系统构成

  • 2x WD Red Pro 4TB HDD (使用主板 RAID 功能构建 RAID 1)
  • 1x Samsung PM981a 256GB NVMe SSD (仅用于缓存)
  • 作为虚拟机运行于 Proxmox VE 7.2 上

笔者的 NAS 并不是一个「标准」的 NAS。经过对个人需求的分析,笔者选择了不同于传统 NAS 的配置——本文将在后面介绍这样选择的考虑。

Arch Linux 的安装过程在此不再赘述。

分区方案

笔者使用主板自带的 RAID 功能,将两块 4TB WD Red Pro 硬盘组建为 RAID 1。对于 Proxmox VE 宿主机来说,这两块硬盘被映射为乐一块硬盘。

随后,笔者设置了 SATA Passthrough,将组建好的 RAID 和 NVMe SSD Passthrough 给 NAS 虚拟机。

在 NAS 虚拟机中,除系统盘外,可见的磁盘为 sda(组建好的 RAID)和 sdb(NVMe SSD)。笔者不对其分区,直接将其格式化为 LUKS Volume。同时,笔者将配置 LUKS Volume 的自动解锁与 FIDO2 密钥解锁。

然后,笔者在 LUKS 解密映射出的 Plaintext Device 上创建 LVM Volume Group,并在 Volume Group 上创建 LVM Cache Volume,以使用 SSD 缓存读写数据。

在 LVM Cache Volume 上,笔者将创建带有若干个 Thin Volume 的 LVM Thin Pool,以便于管理数据的分配。每个 Thin Pool 都将分配特定的用途,例如 Time Machine 备份、同步数据、云存储备份等。

最后,笔者在 LVM Thin Pool 上创建 Btrfs 文件系统,以支持快照、透明压缩、Subvolume 等功能。

以下是上述分区方案的简要示意图:

  • sda (RAID 1 HDD)
    • LUKS (luks-data)
      • LVM Thin Pool (nas-data)
        • 512GB Thin Volume (nas-data_timemachine)
          • Btrfs
        • 1TB Thin Volume (nas-data_sync)
          • Btrfs subvolume (/main)
          • Btrfs subvolume (/snapshots/<snapshot-id>)
        • 1.5TB Thin Volume (nas-data_backups)
          • Btrfs subvolume (/E5): Office E5 OneDrive 备份
          • Btrfs subvolume (/S3): S3 备份
  • sdb (SSD)
    • LUKS (luks-cache)
      • LVM Cache Volume (nas-cache)

磁盘分区与格式化

首先安装必要的软件:

1
pacman -Syu --noconfirm lvm2 libfido2 samba

配置 LUKS

LUKS 是 Linux 通用的全盘加密格式,目前通用且默认的版本为 LUKS2。

首先,创建一个 LUKS 解密秘钥,用于在系统启动时自动解密 LUKS Volume:

1
dd if=/dev/urandom of=/luks.key bs=1 count=64

格式化为 LUKS Volume(笔者这里使用了 --label 选项以设置 Volume Label):

1
2
cryptsetup luksFormat --key-file /luks.key /dev/sda --label LuoTianyiNAS-Data
cryptsetup luksFormat --key-file /luks.key /dev/sdb --label LuoTianyiNAS-Cache

如前文所述,笔者计划配置 FIDO2 密钥解锁。首先将 FIDO2 密钥插入服务器的 USB 接口,并在 Proxmox VE 中设置 USB Passthrough。然后,使用 systemd-cryptenroll 命令将 FIDO2 密钥添加为 LUKS Volume 的解锁密钥:

1
2
systemd-cryptenroll --unlock-key-file /luks.key /dev/sda --fido2-device=auto
systemd-cryptenroll --unlock-key-file /luks.key /dev/sdb --fido2-device=auto

为了在系统启动时自动解密 LUKS Volum,需要编辑 /etc/crypttab 文件,添加以下内容:

1
2
luks-data      LABEL=LuoTianyiNAS-Data                      /etc/luks.key           luks
luks-cache LABEL=LuoTianyiNAS-Cache /etc/luks.key luks,discard

最后,打开 LUKS Volume:

1
2
cryptsetup luksOpen --key-file /luks.key /dev/sda luks-data
cryptsetup luksOpen --key-file /luks.key /dev/sdb luks-cache

在打开 LUKS Volume 后,Plaintext Device 被映射为 /dev/mapper/luks-data/dev/mapper/luks-cache

配置 LVM Cache Volume 上的 LVM Thin Pool

LVM 提供了多种不同的缓存方案,本文使用其中的 LVM Cache Volume 方案。关于各种方案的比较,本文将在后面讨论。

首先创建 LVM Volume Group 和 LVM Cache Volume,并在 LVM Cache Volume 上创建 LVM Thin Pool:

1
2
3
4
5
6
vgcreate nas /dev/mapper/luks-data
lvcreate --type thin-pool -n data -l 100%FREE nas /dev/mapper/luks-data --poolmetadataspare n --chunksize 256

vgextend nas /dev/mapper/luks-cache
lvcreate -n cache -l 100%FREE nas /dev/mapper/luks-cache
lvconvert --type cache --cachevol nas/cache nas/data --chunksize 256

然后,根据预定的分区方案,在 LVM Thin Pool 上创建若干个 LVM Thin Volume:

1
2
3
lvcreate -V 512G -T nas/data -n data_timemachine
lvcreate -V 1T -T nas/data -n data_sync
lvcreate -V 1.5T -T nas/data -n data_backups

格式化 Btrfs 文件系统和创建 Btrfs Subvolume

将 LVM Thin Volume 格式化为 Btrfs 文件系统:

1
2
3
mkfs.btrfs /dev/nas/data_timemachine -L nas-timemachine
mkfs.btrfs /dev/nas/data_sync -L nas-sync
mkfs.btrfs /dev/nas/data_backups -L nas-backups

编辑 /etc/fstab 文件以在系统启动时自动挂载:

1
2
3
LABEL=nas-timemachine /data/TimeMachine  btrfs   rw,relatime,compress=zstd:3,space_cache=v2,nofail  0 0
LABEL=nas-sync /data/Sync btrfs rw,relatime,compress=zstd:3,space_cache=v2,nofail 0 0
LABEL=nas-backups /data/Backups btrfs rw,relatime,compress=zstd:3,space_cache=v2,nofail 0 0

此处有几个值得注意的参数:

  • compress=zstd:3:启用 Zstd 压缩算法,压缩级别为 3
  • space_cache=v2:启用 Btrfs 空间缓存 v2 特性
  • nofail:如果未识别到磁盘,依然继续启动系统,防止启动失败

创建挂载点并挂载:

1
2
3
4
mkdir -p /data/{TimeMachine,Sync,Backups}
mount /dev/nas/data_timemachine -o compress=zstd:3 /data/TimeMachine
mount /dev/nas/data_sync -o compress=zstd:3 /data/Sync
mount /dev/nas/data_backups -o compress=zstd:3 /data/Backups

最后,创建相关的 Btrfs Subvolume:

1
2
3
4
5
6
btrfs subvolume create /data/Sync/main
btrfs subvolume create /data/Sync/snapshots
btrfs subvolume create /data/Backups/@
btrfs subvolume create /data/Backups/E5
btrfs subvolume create /data/Backups/S3
# And other cloud storage services...

配置 SMB 服务

首先安装相关软件:

1
pacman -Syu --noconfirm samba avahi

其中,avahi 为 mDNS 服务,以便其他设备能够发现服务器(例如能在「网上邻居」看到该设备)。

修改 /etc/avahi/avahi-daemon.conf 文件,以更改其他设备发现的设备名和域名:

1
2
3
4
5
[server]
host-name=LuoTianyi-NAS
domain-name=lty.blue
use-ipv4=yes
use-ipv6=no

添加用于 SMB 身份验证的 Linux 用户,并为其设置连接 SMB 时使用的密码:

1
2
useradd -d /dev/null -s /usr/bin/nologin smb
smbpasswd -a smb

然后,编辑 SMB 配置文件 /etc/samba/smb.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[global]
security = user
public = no
guest ok = no
valid users = @smb
load printers = no
use sendfile = yes
ea support = yes
vfs objects = catia fruit streams_xattr
fruit:metadata = stream
fruit:model = MacSamba
fruit:aapl = yes
fruit:veto_appledouble = no
fruit:copyfile = yes
fruit:nfs_aces = no
fruit:posix_rename = yes
fruit:zero_file_id = yes
fruit:delete_empty_adfiles = yes
fruit:wipe_intentionally_left_blank_rfork = yes

[TimeMachine]
path = /data/TimeMachine
comment = Time Machine
browseable = yes
writeable = yes
public = no
valid users = @smb
fruit:time machine = yes

[Sync]
path = /data/Sync
comment = Client Data Sync
browseable = yes
writeable = yes
public = no
valid users = @smb

[Backups]
path = /data/Backups
comment = Automatic NAS Backup
browseable = yes
writeable = no
public = no
valid users = @smb

最后,启动 SMB 服务:

1
2
systemctl enable --now avahi-daemon
systemctl enable --now smb

配置自动化的备份

笔者使用 Rclone 从云存储(OneDrive、S3 等)单向同步数据、备份到 NAS。同时,笔者使用 Systemd Timer 使其定期自动执行。

安装与配置 Rclone

首先安装 Rclone:

1
pacman -Syu --noconfirm rclone

笔者使用一个专门的 Linux 用户(以 rclone 为例)来运行 Rclone,以提高安全性。笔者为该用户分配了一个专门的目录 /etc/rclone 用于存储 Rclone 配置文件,并作为该用户的 Home 目录。

1
2
3
mkdir -p /etc/rclone
useradd -d /etc/rclone -r rclone
chown -R rclone:rclone /etc/rclone /data/Backups

配置 Rclone 的过程不在本文赘述,您可以参见 Rclone 官方文档。您需要切换到 rclone 用户,使用 rclone config 命令来配置 Rclone:

1
sudo -u rclone rclone config

提示
在使用 OneDrive 时,Rclone 的最新版本可能存在 Bug,导致在其他机器上执行 rclone authorize onedrive 的结果无法被识别。因此,您可以使用以下命令启动本地到 NAS 的代理:

1
2
# 将 nas 替换为您的 NAS 主机名
ssh -NL 53682:localhost:53682 nas

创建 Rclone 配置的目录结构

笔者使用如下的目录结构来管理 Rclone 配置文件:

1
2
3
4
5
6
7
8
9
10
11
/etc/rclone/
├── .config/rclone # Rclone 配置目录
├── defaults # 环境变量目录
│ ├── rclone # 全局环境变量文件
│ └── conf
│ └── <name> # 单个备份任务的环境变量文件
├── exclude # Rclone 排除文件目录
│ └── <name>.exclude # 单个备份任务的排除文件
├── pid # 备份任务 Systemd 进程的 PID 文件目录
├── htpasswd # Rclone Web GUI 用户密码文件 (在下文中叙述)
└── web # Rclone Web GUI 静态资源目录 (在下文中叙述)

以配置 Office E5 OneDrive 备份为例(下同),笔者将其简称(也是文件夹名称和 Systemd 实例名称)命名为 e5/etc/rclone/defaults/rclone 文件内容如下,您可以根据自己的需求修改配置:

1
2
3
4
5
6
7
8
# 同时传输文件数,--transfers 参数的值
TRANSFERS=4

# 检查文件的并发数,--checkers 参数的值
CHECKERS=4

# 日志级别,--log-level 参数的值
LOG_LEVEL=INFO

/etc/rclone/defaults/conf/e5 文件内容如下,您可以根据自己的需求修改配置:

1
2
3
4
5
# Rclone 配置的名称
CONF=e5

# 以 /data/Backups/ 为前缀的备份路径
DEST=E5

/etc/rclone/exclude/e5.exclude 文件内容如下,您可以根据自己的需求修改配置:

1
2
# OneDrive 临时文件
~$*

为了在每次开始备份前进行一次 Btrfs 快照,笔者创建了 /etc/rclone/rclone-shapshot 脚本:

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
if [ -z "$DEST" ]; then
echo "Environment variable 'DEST' is not set."
exit 2
fi
SNAPSHOT_DATE=$(date +%Y-%m-%d-%H:%M:%S%z)
SNAPSHOT_UUID=$(uuidgen)
SNAPSHOT_NAME=Snapshot-${SNAPSHOT_DATE}-${SNAPSHOT_UUID}
btrfs subvolume snapshot /data/Backups/${DEST} \
/data/Backups/@/${DEST}/${SNAPSHOT_NAME}

完成以上配置后,使用以下命令来测试备份配置是否能够正常工作:

1
2
3
4
5
6
7
8
9
sudo -u rclone -i
source /etc/rclone/defaults/rclone
source /etc/rclone/defaults/conf/e5
rclone sync -P \
--transfers $TRANSFERS \
--checkers $CHECKERS \
${CONF}: /data/Backups/${DEST} \
--exclude-from /etc/rclone/exclude/${CONF}.exclude
/etc/rclone/rclone-shapshot

创建 Systemd Service 和 Systemd Timer

创建 /etc/systemd/system/rclone-backup@.service 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Unit]
Description=Backup '%i' to local disk via Rclone
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
ConditionPathExists=/etc/rclone/filters/%i.exclude

[Service]
Type=simple
User=rclone
Group=rclone
PIDFile=/etc/rclone/pid/$i.pid
WorkingDirectory=/etc/rclone
EnvironmentFile=/etc/rclone/defaults/rclone
EnvironmentFile=/etc/rclone/defaults/conf/%i
ExecStartPre=/etc/rclone/rclone-shapshot
ExecStart=rclone sync --log-level $LOG_LEVEL --transfers $TRANSFERS --checkers $CHECKERS %i: /data/Backups/${DEST} --exclude-from /etc/rclone/filters/%i.exclude

创建 /etc/systemd/system/rclone-backup@.timer 文件:

1
2
3
4
5
6
7
8
9
[Unit]
Description=Backup '%i' regularly with rclone

[Timer]
OnCalendar=Sat 12:07:12
Persistent=true

[Install]
WantedBy=timers.target

以上文件创建了一个多实例的 Systemd Service 和 Systemd Timer。该 Systemd Service 将在每次执行时,先创建一个 Btrfs 快照,然后使用 Systemd Rclone 同步数据到本地磁盘。而该 Systemd Timer 将定期触发同名的 Systemd Service。而对于多实例的 Systemd Service,能够使多个相似配置的服务复用相同的配置文件。它们使用 service-name@instance-name 的格式来启动,以接受实例名称参数 %i

该 Systemd Timer 将在 每周六的 12:07:12 执行备份任务。您可以根据自己的需求修改 rclone-backup@.timer 中的 OnCalendar 选项。

最后,启动 Systemd Service 和 Systemd Timer:

1
2
3
systemctl enable --now rclone-backup@e5.timer
systemctl enable --now rclone-backup@s3.timer
# More backup tasks...

配置 Rclone Web GUI

Rclone 提供了 Rclone Web GUI,但是并未可用于 NAS 用途的功能。本着「来都来了」的原则,笔者还是进行了配置。

Rclone 会在 Rclone Web GUI 启动时自动下载静态资源,但其存在 bug 导致需要输入两次密码(一次 HTTP Basic 认证,一次表单认证)。因此,笔者使用 Nginx 托管静态资源解决这个问题。

首先安装 Nginx:

1
pacman -Syu --noconfirm nginx

使用如下配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name nas-rclone.lty.blue;
root /etc/rclone/web;

index index.html;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_trusted_certificate /path/to/ca.pem;
access_log /var/log/nginx/rclone-access.log main buffer=512k flush=1m;

location / {
try_files $uri $uri/ @api;
}

location @api {
proxy_pass http://localhost:5572;
}
}

然后,下载 rclone-webui-react 页面上的 currentbuild.zip,解压到 Nginx 配置的 root 目录(/etc/rclone/web)下。

接下来使用 Systemd 配置 Rclone Web GUI 自启动。编辑 /etc/systemd/system/rclone-web.service 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=A full fledged UI for the rclone cloud sync tool
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=simple
User=rclone
Group=rclone
WorkingDirectory=/etc/rclone/web
ExecStart=rclone rcd --rc-web-gui --rc-web-gui-no-open-browser --rc-htpasswd /etc/rclone/htpasswd
Restart=on-failure

[Install]
WantedBy=multi-user.target

接下来您需要创建一个 htpasswd 文件,以存储到 /etc/rclone/htpasswd (与上文 ExecStart 中的路径一致),用户名为 rclone 为例:

1
printf "rclone:$(openssl passwd -apr1)" >> /etc/rclone/htpasswd

最后,启动 Rclone 服务:

1
systemctl enable --now rclone-web

现在,你可以通过 Nginx 配置文件中的域名访问 Rclone Web GUI。若出现问题,您可以使用 systemctl status rclone-webjournalctl -u rclone-web 查看状态或日志。

安装 Cockpit

Cockpit 是 RedHat 开发的基于 Web 的服务器系统管理工具,具有查看 Systemd Service、监控系统资源、监控存储等功能。笔者选择安装 Cockpit 以方便管理 NAS。

首先安装 Cockpit 和 Nginx:

1
pacman -Syu --noconfirm cockpit cockpit-machines cockpit-packagekit cockpit-storaged nginx inetutils

注意
Cockpit 需要 inetutils 包以获取主机名。但是由于缺少 inetutils 包并不影响 Cockpit 工作(Cockpit 会将主机名显示为 localhost),因此 inetutils 未被 Arch Linux 的包管理者列为 Cockpit 的依赖。在 Arch Linux 上,您可能需要手动安装 inetutils 包。

创建 Nginx Site 配置文件,配置 Nginx 反向代理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name nas-cockpit.lty.blue;

index index.html;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_trusted_certificate /path/to/ca.pem;
access_log /var/log/nginx/cockpit-access.log main buffer=512k flush=1m;

location / {
proxy_pass https://127.0.0.1:9090;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Connection "upgrade";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
}

提示
记得将 /path/to/ 替换为证书的路径。

现在,你可以通过 Nginx 配置文件中的域名访问 Cockpit。

演练:如果用于缓存的 SSD Offline 会怎样?

为了防止未来意外的数据丢失,因此进行了一次模拟演练:在 Proxmox VE 中取消了 NVMe SSD Passthrough,以模拟 SSD Offline 的情况。

SSD Offline 后,vg nas 会进入 partial 状态。首先移除 LVM Cache Volume:

1
lvconvert --uncache nas/data

然后,重新上线 LVM Cache Volume 的 Data LV nas/data

1
vgchange -ay nas

此时,可以如同挂在普通 LV 一样挂载 Data LV(实际上 Data LV 已被转换为普通 LV)。建议使用 -o ro 选项以只读方式挂载:

1
mount -o ro /dev/nas/data_timemachine /mnt

完成备份操作(例如使用 dd 命令复制数据)后,下线数据卷:

1
vgchange -an nas

若问题解决,可以使用下面的命令重新组成 LVM Cache Volume。此处笔者重新设置 NVMe SSD Passthrough 后,在 NAS 虚拟机中缓存 SSD 重新可见。

警告
运行下面的命令会导致缓存 SSD 上的数据丢失,但这是预期行为。

1
2
3
vgck nas --updatemetadata
lvcreate -n cache -l 100%FREE nas /dev/mapper/luks-cache
lvconvert --type cache --cachevol nas/cache nas/data --chunksize 256

关于 NAS 的一些思考

为什么不使用成品 NAS?

因为穷。

经过对个人需求的分析之后,个人既没有选择成品 NAS,也没有选择一些通用的 NAS 方案。

没有选择成品 NAS,最大的原因是穷。

没有选择通用的 NAS 方案,也是对自己的需求分析的结果。个人对存储空间的需求很小:4TB 足矣,一个盘装得下。不需要太多盘位。

对于数据安全性,一个知名的说法是 3-2-1 原则:

  • 至少 3 个备份
  • 至少 2 种不同的媒介
  • 至少 1 个备份在远程位置

根据该原则,笔者对存储方案的自我评估如下:

  • 对于个人数据:存储在 OneDrive 和 NAS 上,同时在中国大陆具有一个同步的本地备份(符合 3-2-1 原则
  • 对于网络资源:储存在 OneDrive 和 NAS 上,无本地备份(2-2-0,但是网络资源是可重复获取的,并不需要符合 3-2-1 原则
  • 对于系统备份:
    • 偏好设置的目的是「让系统用的顺手」,本身就会随着系统更新不断调整,即使数据丢失也没什么损失
    • 开发相关的数据「备份」在 GitHub 上
    • 个人数据已经备份在 OneDrive 和 NAS 上

因此,笔者个人认为,笔者的 NAS 方案虽然并不完美契合 3-2-1 原则,但是已经足够满足个人需求。

为什么选用 Arch Linux?

Beacuse I can.

还有就是:

Arch Linux 的蓝色,和天依的蓝色很像呢!

笔者认为,只要能做到「能够对一个系统进行快照、同时快速回滚」,那么 Arch Linux 或 OpenSUSE Tumbleweed 等滚动发行版是最佳选择。

为什么?因为不怕滚挂!

在这一点上,自建的方案(Proxmox VE、ESXi)可以做到,云服务厂商也可以做到。因此,在这些场景,应该 能上 Arch Linux 就上 Arch Linux

为什么不使用 ZFS?

ZFS is not in the mainline kernel.

仅仅这一点就是我不选择 ZFS 的原因。当然这只是个人偏好问题,但也是我思考的出发点——有了这个靶子,笔者便能顺着思路思考

  • 数据一个盘装得下,不需要那么多盘。组 ZFS 没意义。
  • ZFS 对 RAM 需求大,而笔者的 NAS 是运行在虚拟机上的,宿主机也仅有 16GB 内存。

但是又眼馋 ZFS 的高级特性(快照、压缩、数据完整性检查等),恰好 Btrfs 都有,因此选择了 Btrfs。

对于 NAS 的文件系统(和磁盘阵列),笔者一直持有的观点是:对于个人用户,**任何方案都不如 JBOD (JBOD)**。尽管它们声称提供了 _冗余_,但是 冗余不是备份——而对于个人,首要的是 备份而非冗余——大多数人并不需要 99.9999% Uptime 的存储服务。

而它们带来了什么副作用呢?答案是 _复杂性_。是的,RAID 会进行 Checksum、会自动重建;ZFS 也有自动修复,但是在这背后到底发生了什么?这些机制对于用户是 不透明 的。有人说,我完全理解 RAID 或是 ZFS 的算法,但是这一切都不如真正切切、直接 ls 就能看到的 JBOD 简单。

而用户需要的 _备份_,JBOD 可以完美解决。简单的复制粘贴,复杂一点也可以用 rsync 或是 btrfs send | btrfs receive。这些操作是 透明 的,用户可以直接看到数据的变化,理解背后发生的一切,而不是被隐藏在 RAID 或 ZFS 的黑盒子里。

至于文件完整、加密、去重、压缩、快照等功能,笔者更为激进的观点是:这些功能应当作用与 _文件级别_,而非 _文件系统级别_。就像 Android 的 FBE 一样,应当有一个 File-based compression/snapshot/integrity-check 方案。这些方案可以作为 NAS 软件的一部分。而文件系统应当只负责提供基本的文件存储功能,而这些高级功能应当由文件系统之上的应用来实现。

遗憾的是,目前并没有这样的方案——笔者也因此妥协地选用 Btrfs。

为什么有了 Btrfs Subvolume 还要使用 LVM?

因为需要限制 Time Machine 的空间。

至于为什么不用 Quota,Quota 现在在 Arch Wiki 上还是挂着 Unstable 的模板!

LVM 有哪些缓存方案?

LVM 缓存有两种方法:

  • dm-cache: 缓存读写操作,是 LVM 的默认行为,也是笔者的选择
  • dm-writecache: 仅缓存写操作

同时,LVM 提供两种缓存组件:

  • cachepool: 缓存的元数据在一个设备上,缓存本身在另一个设备上
  • cachevol: 缓存的元数据和数据在同一个设备上