[troubleshoot][archlinux][bcache] 修改linux文件系统 / 分区方案 / 做混合硬盘 / 系统转生大!手!术!(调整底层架构,不!重!装!)

目标:

  我要做的事情是:修改文件系统,硬盘分区方案,但是不重装系统,整个操作不被应用层感知。

背景:

我的笔记本 ThinkPad T450。8G内存 + 16GB SSD + 1TB HDD。预装windows7。

在预装系统里16GB的SSD好像是被win7用作睡眠之类的功能。电脑拿到手之后的第一件事我就是想办法把linux装进去。我当初的方案是:

  1. 备份win7。比较是预装的,也算是正版。我把1TB硬盘C盘中的文件压缩拷贝出来了。然后又把硬盘开始1G
B dd了出来。这样有一点可以装回去,给其他人用,当我有一天换了新本之后。

  2. 重装了win7。因为win7安装的时候,会认出16GB的SSD,并且自动的装东西进去。所以要重装(忘记了具体怎么做的了)为了让16GB分离出来。只将win7装到HDD的前50GB里边。再分一个200多GB用做D盘。

  3. 把archlinux装进了SSD。并且从SSD引导。这样,启动不同的系统,只有选择不同的启动盘就可以了,而无需安装双引导。SSD挂载根目录。/home目录挂到HDD剩下的700多GB的分区里。

  4. 由于SSD比较小,我把/var/下面的pacman cache设置到了/home下。此外又这是了基于文件的swap,改文件也位于/home下。

  5. 这样的话,基本就可用了。而且我还洋洋自得了很久。感觉高效的利用了SSD。

  就这样一直使用了1年2个月一直到今天。重要,根目录还是增长到了80% 导致系统运行变得很慢。SSD的性能在快满的时候,会变得很慢(我仿佛记得)。而且更重要的是,swap是机械的,交换的时候真的很明显。

  综上,终于有了结论,我的方案失败了。。。

新方案:

  方案最终于的核心内容就是,如何把只有16GB的SSD用起来? 

  市面上有一种硬盘叫混合硬盘。它的原理是,在机械硬盘前有一个小小的固态硬盘,用来缓存。据说性能与固态硬盘无异。可是,咦!为什么要提这个呢? 因为在linux下,我们可以自制。是的。

  大概这几种吧:FlashCache,dm-cache,lvm-cahce,bcache。

  flashcache是facebook搞的,性能很好,但是没有进内核,需要编内核。lvm-cache是红帽搞的,听说性能不太好?而且archwiki里也没用。另一个不知道。bcache,入了内核,就它了!链接不一一提供了,请自寻。

  然后是文件系统的问题:ext4,xfs,btrfs,zfs。

  其实我想用btrfs,但是还是高实验性啊,不稳定啊,还是涮了。zfs要单装内核模块。ext4比较好,但是xfs被redhat7默认了。所以我就选xfs了。

  最后,用LVM。方便高级为何不要?

开始:

1. U盘启动。

  进U盘系统,就是arch的安装盘啊。

2. 把所有目录按原结构挂载至 /mnt/ROOT_FS/ 目录下。

  对啊,把原系统挂起来,准备备份,准备重做。

3. 台式机与启动U盘分别安装rsync工具。

  rsync比较高级吧,其实我只用了它的scp功能,应该用些更高级的。

4. 启动台式机的ssh,打开防火墙。

  咻咻咻咻咻咻咻咻咻

5. 使用rsync命令将ROOT_FS拷贝至台式机硬盘。

  烤哇烤烤哇烤烤哇烤

6. 等待6个小时。。。 看电视剧,睡觉,吃东西,出去约会。。。

  等啊等等啊等等啊等

7. 考完了,一共380GB。。。开始弄吧。。。

  烤哇烤烤哇烤烤哇烤

8. 分区

  补充两份资料:

https://bcache.evilpiepirate.org/

https://evilpiepirate.org/git/linux-bcache.git/tree/Documentation/bcache.txt

https://wiki.archlinux.org/index.php/LVM

  关于对齐:https://wiki.archlinux.org/index.php/Partitioning#Partition_alignment

  现在工具已经可以自动检测是否对齐了,例如parted

8.1 给SSD分区

  parted mklabel gpt

  parted mkpart primary linux-swap(new) 1 50%

  parted mkpart primary 50% 100%

8.2 UEFI

  https://wiki.archlinux.org/index.php/EFI_System_Partition

  EFI启动需要一个FAT32的EFI分区。不能under LVM。用了让UEFI firmware启动这里边的bootloader application。

8.2.1 创建EFI分区ESP(EFI System Partition)

  A。使用GPT分区表

  B。推荐分区大小512MiB。  

  C。必须格式化为FAT32

  D。设置标记esp

8.2.2 如何修改EFI启动项

  有两种方式,一种是在OS里使用efibootmgr。这是一个linux命令。但是有时候也许有一些限制之类的,或者其他的莫名其妙的原因,在OS命令里不一定搞得定。这时候就可以用efi shell再试一试。有一些主板集成了efi shell。有些没有。没有集成的,就需要自行把efi shell安装到ESP中,然后中EFI loader中启动了。  

  

>mklabel gpt
>mkpart primary fat32 1 512
>mkpart primary 512 100%
>set 1 esp on

8.2.3 UEFI相关的知识

  介绍:http://www.rodsbooks.com/efi-bootloaders/principles.html

  安装:http://www.rodsbooks.com/efi-bootloaders/installation.html

8.2 装bcache-tools

   在AUR下载pkg文件 https://aur.archlinux.org/packages/bcache-tools/

  使用makepkg命名做包。

8.3 做bcache

  ESP要做在bcache外面。

  1. 做backing device

# make-bcache -B /dev/sda2

  2. 做caching device

# make-bcache -C /dev/sdb2

  3. 注册

# bcache-super-show /dev/sdb2|grep cset.uuid|cut -f3 > /sys/block/bcache0/bcache/attach
# ll /sys/fs/bcache

  其他:

  重启了之后只有 udev rule。才能保证重启被认到。

8.4 LVM

  1. 使用lvmdiskscan查看所有可以的设备。

  2. 将bcache0制作成pv

# pvcreate /dev/bcache0
# pvdisplay

  3. 创建vg

# vgcreate vg0 /dev/bcache0
# vgdispaly

  4. 创建lv

# lvcreate -L 50G vg0 -n lvroot
# lvcreate -l 100%FREE vg0 -n lvhome
# lvdispaly

9. 将新分区按目录树结构重新挂载

# mount /dev/mapper/vg0-lvroot /mnt/ROOT_FS/
# mount /dev/mapper/vg0-lvhome /mnt/ROOT_FS/home/
# mount /dev/sda1 /mnt/ROOT_FS/boot

10. 使用rsync 将整机转生回新的文件系统。

  变变变变变变变变变

11. 拷贝完成前,学习一下bootloader

  0. 8.2.2中提到的efi shell 

  如果想装,可以从这安装https://wiki.archlinux.org/index.php/Unified_Extensible_Firmware_Interface#Obtaining_UEFI_Shell

  1. 之前用的是systemd-boot: https://wiki.archlinux.org/index.php/Systemd-boot

  systemd自带一个工具 bootctl。很简单,基于前文已经设置好的东西。只需要使用 bootctl install 命令就可以完成boot loader的安装。它会在/boot目录下放置两个文件

  /boot/EFI/systemd/systemd-bootx64.efi   

  /bootEFI/Boot/BOOTX64.EFI

  修改正确相应的配置文件之后,就可以用了:

  /boot/loader/loader.conf

  /boot/loader/entries/arch.conf

  

  2. 准备试一下,EFISTUB:https://wiki.archlinux.org/index.php/EFISTUB

    这个也比较简单。

    第一招: 直接修改UEFI页面选项,把启动参数内核位置等,写到UEFI选项中,UEFI直接启内核:

# efibootmgr -d /dev/sdX -p Y -c -L "Arch Linux" -l /vmlinuz-linux -u "root=/dev/sdBZ rw initrd=/initramfs-linux.img"

    记得 verify一下,省的搞错了

# efibootmgr -v

    第二招:完成第0小节。从UEFI选项进到 UEFI SHELL里。在UEFI SHELL里使用命令行,直接把内核启起来。

> fs0:
> /vmlinuz-linux root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 rw initrd=/initramfs-linux.img

12. 按照11中的内容,考完开搞!

12.1. 在启动CD中识别bcache设备。

  因为拷贝过程很长。第二天又要上班。所以考完之后,我就关机了。第二天开机之后。自然认不出bcache分区,也就认不出lvm,也就认不出文件系统了。需要使用以下步骤,是CD认出他们来。

  现象:

  lsblk,ls /sys/fs, ls /sys/block 均查看不到bcache相关的信息。

  lsmod |grep bcache 发现bcache模块没有加载。

  可以通过 modinfo bcache 查看到相关模块的信息。

  1.  加载 bcache 模块, /sys/fs/bcache 文件夹出现。

# modprobe bcache
# lsmod |grep bcache
# ls /sys/fs/bcache

  2. 注册bcache设备到系统, /sys/fs/bcache/ 下出现注册设备。backing device和caching Device都需要注册。可以通过blkid命令在众多block device中找到他们。

# echo /dev/sda2 > /sys/fs/bcache/register
# echo /dev/sdb2 > /sys/fs/bcache/register
# ls /sys/fs/bcache/
690915e5-a03a-4eef-8fa0-cee935aabea5  register  register_quiet

  3. attach caching device 到 backing device。按理说应该如前文般attach,文档中也如实说。但实际情况已经自动attach了,故略。

  4.  至此,bcache设备已经识别,lvm,文件系统等都可以被识别了。

12.2. 改 /etc/fstab 

  1. 按设计挂载好所有的device,/,/home,/boot,swap等。

  2. 使用genfstab命令生成 fstab 文件。

# genfstab ROOT_FS > ROOT_FS/etc/fstab

12.3. 改boot loader, 删掉grub2, 留下systemd-boot

  补充知识:

    https://wiki.archlinux.org/index.php/Mkinitcpio

  1. chroot, 并删掉grub

# arch-chroot ROOT_FS
# pacman -Rsun grub
# bootctl update

  2. 修改/boot/loader/ 下的config为正确的设置。

  3. 修改 /etc/mkinitcpio.conf 让initramfs认识ROOT文件系统。包括认识bache,认识lvm。

  a. 让系统认识bcache。需要安装包bcache-tools ;需要在HOOKS中加入bache(顺序相关)。需要注意的是,不需要修改MODULES。

/home/tong [tong@T7] [18:53]
> cat /etc/mkinitcpio.conf |grep HOOKS
# HOOKS
# This is the most important setting in this file.  The HOOKS control the
# order in which HOOKS are added.  Run 'mkinitcpio -H <hook name>' for
#    HOOKS="base"
#    HOOKS="base udev autodetect block filesystems"
#    HOOKS="base udev block filesystems"
#    HOOKS="base udev block mdadm encrypt filesystems"
#    HOOKS="base udev block lvm2 filesystems"
HOOKS="base udev autodetect modconf block bcache filesystems keyboard fsck"

/home/tong [tong@T7] [18:53]
> 

  b. 让系统认识lvm。需要安装包sd-lvm2; 需要在HOOKS中加入 systemd,sd-lvm2;

/home/tong [tong@T7] [18:53]
> cat /etc/mkinitcpio.conf |grep HOOKS
# HOOKS
# This is the most important setting in this file.  The HOOKS control the
# order in which HOOKS are added.  Run 'mkinitcpio -H <hook name>' for
#    HOOKS="base"
#    HOOKS="base udev autodetect block filesystems"
#    HOOKS="base udev block filesystems"
#    HOOKS="base udev block mdadm encrypt filesystems"
#    HOOKS="base udev block lvm2 filesystems"
HOOKS="base systemd udev autodetect modconf block bcache sd-lvm2 filesystems keyboard fsck"

/home/tong [tong@T7] [18:53]
> 

  c. 重新生成

# mkinitcpio -p linux

12.4 reboot

13. 重生! :)  

 14. 由于失误出现了的问题:

14.1 rsync 用的不对,SUID都缺少了。。。(SUID是啥玩意??? 参考链接

sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set

  只能给强行加上SUID

# chmod 4755 /usr/bin/sudo

  但这已经说明,由于拷贝的问题,一定遗留了好多隐患。可以试着滚一下所有包,当定然不能解决全部问题吧,我想。。。。

# pacman -Qqn |pacman -S -

  我想,我失败了。。。。好无语。。。

  需要系统的补充学习,rsync。

15.  其他补充学习与实验

15.1 EFI STUB, 前文以提到。参见11节。

  1. 进入 EFI shell后,使用如下命令,可以启动。

  a. 安装EFI shell 到EFI MENU

/sys/block/bcache0/bcache [tong@T7] [19:23]
> yaourt -S uefi-shell-git

  b. 下载太慢了。。。 去BOOT CD里考了一个出来,一共两个文件。

/home/tong [tong@T7] [22:53]
> ll /boot/EFI/shellx64_v2.efi /boot/loader/entries/uefi-shell-v2-x86_64.conf
-rwxr-xr-x 1 root root 884K Dec  5 22:39 /boot/EFI/shellx64_v2.efi
-rwxr-xr-x 1 root root   56 Dec  5 22:40 /boot/loader/entries/uefi-shell-v2-x86_64.conf

/home/tong [tong@T7] [22:53]
> 

  c. 进入EFI shell,使用如下命令启动内核。

> map
> ls FS1:
> vmlinuz-linux root=/dev/mapper/vg0-lvroot rw initrd=initramfs-linux.img

  2. STUB from efibootmgr

home/tong [tong@T7] [23:09]
> sudo efibootmgr -d /dev/sda -p 1 -c -L "STUB" -l /vmlinuz-linux -u "root=/dev/mapper/vg0-lvroot initrd=/initramfs-linux.img"
BootCurrent: 000C
Timeout: 0 seconds
BootOrder: 0014,0013,0009,000A,000C,0007,0008,000B,000D,0012
Boot0000  Setup
Boot0001  Boot Menu
Boot0002  Diagnostic Splash Screen
Boot0003  Lenovo Diagnostics
Boot0004  Startup Interrupt Menu
Boot0005  Rescue and Recovery
Boot0006  MEBx Hot Key
Boot0007* USB CD
Boot0008* USB FDD
Boot0009* ATA HDD0
Boot000A* ATA HDD1
Boot000B* ATA HDD2
Boot000C* USB HDD
Boot000D* PCI LAN
Boot000E* IDER BOOT CDROM
Boot000F* IDER BOOT Floppy
Boot0010* ATA HDD
Boot0011* ATAPI CD
Boot0012* PCI LAN
Boot0013* Linux Boot Manager
Boot0014* STUB

/home/tong [tong@T7] [23:09]
> 

  使用如下命令,可以对指定的启动项进行启用或禁用

/home/tong [tong@T7] [19:41]
> sudo efibootmgr -b 0013 -A
BootCurrent: 0015
Timeout: 0 seconds
BootOrder: 0013,0015,000C,0009,0007,000A,0008,000B,000D,0012
... ...
Boot0013  STUB
Boot0015* Linux Boot Manager

/home/tong [tong@T7] [19:41]
> sudo efibootmgr -b 0013 -a
BootCurrent: 0015
Timeout: 0 seconds
BootOrder: 0013,0015,000C,0009,0007,000A,0008,000B,000D,0012
... ...
Boot0013* STUB
Boot0015* Linux Boot Manager

/home/tong [tong@T7] [19:41]
> 

15.2

  EFI boot loader的设置调整。主要是使用两个工具,前文以提到,efibootmgr,efi shell

15.3

  并没有文档中明确指出mkinitcpio.conf中的systemd,可以代替udev。但是我的直觉,它是可以代替的。所以,去掉了并且测试成功。但是这并不代表没有隐患,个人感觉基本不可能有什么隐患,因为系统启动之后,基本上就和initramfs没有关系了。

/home/tong [tong@T7] [19:01]
> cat /etc/mkinitcpio.conf|grep HOOKS
# HOOKS
# This is the most important setting in this file.  The HOOKS control the
# order in which HOOKS are added.  Run 'mkinitcpio -H <hook name>' for
#    HOOKS="base"
#    HOOKS="base udev autodetect block filesystems"
#    HOOKS="base udev block filesystems"
#    HOOKS="base udev block mdadm encrypt filesystems"
#    HOOKS="base udev block lvm2 filesystems"
HOOKS="base systemd autodetect modconf block bcache sd-lvm2 filesystems keyboard fsck"

/home/tong [tong@T7] [19:02]
> 

  并且,userland启动速度又22秒,变成13秒(同时我还禁掉了一个service,所以这个数据只做记录而没有可比性)。

home/tong [tong@T7] [19:06]
> systemd-analyze 
Startup finished in 4.865s (firmware) + 3.349s (loader) + 859ms (kernel) + 1.531s (initrd) + 13.356s (userspace) = 23.961s

/home/tong [tong@T7] [19:06]
> 

16. 最后的设置

  忙活一大顿,如果不做这一步,真的是白忙活了。 就是writeback,心情不好。。。不解释了。。。

[root@T7 ~]# cat /sys/block/bcache0/bcache/cache_mode 
[writethrough] writeback writearound none
[root@T7 ~]# echo writeback > /sys/block/bcache0/bcache/cache_mode 
[root@T7 ~]# cat /sys/block/bcache0/bcache/cache_mode 
writethrough [writeback] writearound none
[root@T7 ~]# 

   还有readahead,由于本人水平比较low,真的不知道这个值应该怎么给。。。默认是0。保守起见,没有并没有修改该值。

readahead
  Size of readahead that should be performed.  Defaults to 0.  If set to e.g.
  1M, it will round cache miss reads up to that size, but without overlapping
  existing cache entries.
[root@T7 ~]# cat /sys/block/bcache0/bcache/readahead 
0
[root@T7 ~]# 

   试着改了下,好像也没啥用。。。 而且配置不能固化,重启就没了。

  

原文地址:https://www.cnblogs.com/hugetong/p/6127707.html