2

迁移系统到 SSD

 3 years ago
source link: https://blog.lilydjwg.me/2019/3/31/move-system-to-ssd.214336.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

迁移系统到 SSD

本文来自依云's Blog,转载请注明。

最近一段时间,不知道是磁盘、缓存相关算法的更新,还是我开的服务太多,又或者是新软件占用内存太高,我的系统越来越卡了,尤其是更新系统的时候(备份系统时也特别卡,然后我用限制内存占用的办法解决了)。我当然知道最主要的原因是因为机械硬盘的处理能力就那么多,于是经过一些了解和计划之后,还是决定换 SSD 了。

刚才查看了一下历史数据。从去年七八月份起,平均内存使用量从2G多升高到了3G多。大概是火狐更占内存了吧。我都尽量减少内容进程数量了……也可能是 PHP / MediaWiki 的锅,因为使用 SQLite 存储时,经常发生错误也是这段时间的事情。不过也可以理解为由于磁盘负载重导致的。算了不管了。

当然首先要去买块 SSD 啦。我买的是 LITEON T11 Plus 512,512GB,800块。实际操作系统得到的空间是 477GiB,因为硬盘产业还在沿用1000进制的单位词头。它比我预期的要小不少呢,不过拿在手里感觉比一般同样大小的电路板要重。

拆开我的 T470p,把空闲接口旁边的螺丝下下来,然后 SSD 标签朝外插进去。我也不清楚这个接口叫什么。插进去之后它是翘起来的,难怪要用螺丝固定。然后用下下来的螺丝固定好,再把机器装好,就好了。启动系统,可以看到 /dev/nvme0n1 设备在了~GNOME 磁盘软件不能读取到 SMART 信息,用 smartctl -a /dev/nvme0n1 命令就好了。

设备没问题了,接下来当然是备份系统啦。

备份妥当之后,我就开始格式化 SSD。计划是 EFI 分区 512M,400G 给我的 Arch Linux,然后剩下 76G 左右的空间预留给我的 Win10。

然后这 400G,首先上一层 LUKS 加密,然后格式化为 btrfs 文件系统。其实我想要 btrfs 很久了,快照、去重、压缩都挺棒的。但是听说它的性能比较差,而我已经在受磁盘 I/O 能力不足的苦了,所以到现在有了 SSD,是时候换 btrfs 了!

其实之前 zfs(zfsonlinux)也是候选项,并且已经在工作本上使用过了。然而最近我的 zfs 备份两度出现问题(磁盘掉线之后 zfs 元数据损坏,导致一整个 zfs 文件系统一写就卡住;近期莫名其妙 rsync 跑着跑着就卡在那里不动了,磁盘也没有什么活动),再加上之前遇到的各种大小问题(ARC 被算进内存使用量中;挂载期间一旦磁盘离线就卡死;克隆出来的文件系统无法摆脱原文件系统;不支持 overlayfs;因为是树外模块所以需要专门准备的支持 zfs 的系统来执行安装),以及 TRIM 支持刚刚才加入,我已经停用 zfs 并将其排除考虑范围了。

然后就是规划子卷。参考了 openSUSE 的方案,最终决定分为这么几个子卷:/, /var/cache, /var/tmp, /var/log, /var/lib/lxc/lxc-debian/rootfs, /var/lib/lxc/lxc-centos6/rootfs, /home/lilydjwg, /home/lilydjwg/.cache。主要考虑的是快照。另外我给 /var/log/journal 和 /var/lib/postgres chattr +C 禁用了 CoW。这样也会禁用压缩,不过本来它们基本上就没什么可压缩的。需要排除的有:我的公开第三方源码和各类大文件用的 /ldata 还是放在机械硬盘上、/var/cache/pacman/pkg 缓存不要、/var/lib/pacman.fs 不用单独放连续的文件里了、/home/lilydjwg/.cache 缓存不要、/home/lilydjwg/.debug 这个 perf top 用的目录会有 libc 的硬链接,rsync 时会失败所以就不要了。

最终的同步命令如下:

sudo systemd-run -p MemoryMax=64M --scope \
rsync -aviHAXKhPS --inplace --delete --exclude='*~' --one-file-system \
/ /mnt/root --exclude=/var/cache/pacman/pkg --exclude=/home/lilydjwg/.cache \
--exclude=/var/lib/pacman.fs --exclude=/ldata --exclude=/home/lilydjwg/.debug

同步好之后,重启进入 live 系统再同步一次以保证最新数据也同步好了。然后把部分被排除的目录再同步一下:~/.cache/winetricks 这个以后不一定能够下到、~/.cache/sxiv 都是有效缓存(我有清理)而且生成耗 CPU、/var/lib/pacman 这个是被 --one-file-system 排除掉的。

然后是在 /etc/default/grub 里更新内核命令行 cryptdevice=/dev/disk/by-partlabel/ssd:ssd:allow-discards。这个 allow-discards 会轻微地降低安全性,不过在中国没什么用的。更新 /etc/fstab。

然后还有 /boot 要处理。其实就是把内核和 initrd 复制过去,然后重新安装 grub、生成 grub 配置。位于机械硬盘上的旧文件之后再删掉即可。

重启,使用 fallback 版 initrd 进入系统,开始修复各种问题。

首先是更新默认的 initrd。不过在更新它之前,我要修改一下我自己的 hook。之前这个 hook 里只有 partprobe 我解密之后的机械硬盘分区,因为我在它上边又分了 xfs 和 swap 两个区。现在因为 encrypt hook 解密的是 SSD 上的分区,所以这个机械硬盘上的加密分区的解密也要自己做。其实也很简单,给这个加密分区添加一下文件密钥,然后

cryptsetup open --type=luks --key-file=/etc/keys/hdd.luks /dev/disk/by-partlabel/main main

就可以了。不需要输入两次密码。

/ldata 使用 automount 延迟挂载,所以需要写 ldata.mount 和 ldata.automount 两个文件,然后 enable ldata.automount 那个。不知道写在 /etc/fstab 里是不是也行。然后把机械硬盘里的目录结构调整一下,把原来 /ldata 下的东西上移一级,旧的 / 里的其它东西都放到隐藏的 .oldroot 里去好了。

swap 本来我是保留着的,不过发现这样子我会时不时听到机械硬盘启动了。而且因为机械硬盘启动比较费时,所以系统会卡好一会儿(大概有一两秒)……所以我默认就不开 swap 了,但是 resume hook 还是保留,需要的时候打开 swap 就可以休眠了。这个 resume hook 也是我需要在启动的时候就解密机械硬盘上的加密分区的原因。

加了一个每周运行的 fstrim -v / cron 任务。没有使用 fstrim.timer 是因为它会 trim 所有设备。而我可不希望它去 trim 我挂载的机械硬盘上的 loop 设备,会造成大量碎片的。

还有一些小问题要处理。chattr +i /etc/resolv.conf 以避免 DNS 服务器被不知不觉修改了。我有用 dnsmasq 的所以这个文件不用动。我有一个 MediaWiki 实例的文件是使用 overlayfs 的,它现在挂载提示「failed to verify upper root origin」。后来才发现相关目录上有同步到几个 trusted. 开头的、overlayfs 使用的扩展属性。是它还挂载的时候被同步到的,不知道为什么最后一次同步时没有被清除掉。手动使用 setxattr 删除掉就好了。

rsync 还出了另外几个莫名其妙的问题。我在 /usr/local/sbin 下有个最近新加的文件的执行权限消失了,造成使用它的 systemd 服务失败。另外有个最近被删除的配置文件竟然还在。我不是有指定 --delete 选项吗?火狐缓存的网站图标也都没有了,需要访问之后才会重新出现。~/.cache 下有很多 root 所有的空目录,也许是我哪次忘记 --exclude 它然后又中断才加上?

Wine 有几个文件有几十 KiB 大的 user.wine.sd 扩展属性。太大了以至于 btrfs 里放不下,报「No space left on device」错误。我刚看到时还吓一跳,以为是我的 SSD 满了,仔细一看才发现只是扩展属性写不下而已。

我于是又带 --dry-run 参数同步了一次,确定再没有什么需要的东西被落下。这次 rsync 出现这些问题很是奇怪,不过我没有留日志,加上操作的时候其实是有不少修修改改的,所以就不深究了吧。

修好所有发现的问题,再次重启之后,systemctl status 和 systemctl --user status 没有失败项了~撒花 O(∩_∩)O~

现在我的系统超快的!比如启动时间:

>>> systemd-analyze
Startup finished in 9.257s (firmware) + 1.466s (loader) + 15.110s (kernel) + 6.945s (userspace) = 32.780s
graphical.target reached after 6.945s in userspace

firmware 和 loader 咱管不了。kernel 那儿包含了我输入密码解密,以及解密和探索机械硬盘上的分区,所以花了些时间。userspace 那里你别看花了好几秒,其实大部分时间都是花在联网上了。不依赖网络的服务在差不多一秒的时间内就全部启动好了。

之后我还要更新备份脚本,因为我用了 --one-file-system 而现在它们在不同的子卷上。再写一下每日快照的脚本,就不用一不小心删错文件啥的都要去备份里找了。

关于写入量,smartctl -a /dev/nvme0n1; sleep 300; smartctl -a /dev/nvme0n1 统计了一下,因为我开了 collectd 收集一些系统数据,每分钟大概会写入 60MiB 的数据。算下来,一年要写 20T 左右。这块 SSD 标称的是 280TBW,也就是可以写 280TB 的数据。这么算起来能用十年,所以就这样吧,不用再优化了。顺便说一下,SMART 信息里的「Data Units Written」数据,乘以 512000 之后是字节数。

就这样啦。最后还要说一句:SSD 超快的!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK