2020年6月5日 星期五

Ubuntu 20.04 ZFS on root 安裝筆記

不知不覺中 Ubuntu 20.04 於五月底正式發行了,看到 ZFS on Linux 好像差不多快成熟了,就很想體會一下 ZFS 的 Copy-on-Write 以及強大的 checksum, snapshot, incremental backup 功能。 但是我的 Dell Latitude 5480 筆電必須是 dual-boot Windows 10 & Ubuntu,而 Ubuntu 20.04 的內建 ZFS on root 安裝選項是會把整個硬碟都格式化給 ZFS 使用。所以我只能自己另闢蹊徑想辦法用一些旁門左道的方式,看看有沒有可能整出一個 Ubuntu on ZFS root + dual boot。

當然要 google 一下網路上前人的經驗,比較有參考性的文件連結都收集在下面的【參考文件】。因為之前也想要體驗 Btrfs 的好處,所以我的 SSD 已經安裝了一版 Ubuntu 20.04 在分區 5,格式為 Btrfs 。在這次 ZFS 安裝前,SSD 是採用 GPT 的分區表,容量為 1T,分割如下:

 1 2 3 4 5 -
 FAT32 - BitLocker  NTFS Btrfs Free
 1024M 128M 488G 10GB 200G 324G
 EFI
 System 
 Windows 
 Reserved 
 Win 10
 System
 Windows
 Recovery 
 Ubuntu
 20.04
 -

準備分割區

基本上這次安裝就是利用 Free 的空間,多加入 2 個分割區,一個是給 boot , 主要是為了 UEFI 開機的支援,建議大小為 512M ,剩下的空間就都留給 Ubuntu System 。我的 Latitude 5480 安裝了 32GB 的 RAM,所以我是沒有使用 swap。這次安裝的起點是:我開機進入已經安裝在分區5的 Ubuntu 20.04 on Btrfs,首先就是用 sgdisk 來做增加分割的部分。
sgdisk -n6:0:+512M -t6:BF01 /dev/nvme0n1  # 在分割區5之後,切出512M給分區6,格式碼設為BF01
sgdisk -n7:0:0 -t7:BF01 /dev/nvme0n1  # 把分割區6之後所有的空間給分區7,格式碼設為BF01
檢查分區增加後的結果如下:
rick@E5480:~$ sudo sgdisk -p /dev/nvme0n1
Disk /dev/nvme0n1: 2000409264 sectors, 953.9 GiB
Model: INTEL SSDPEKKW010T7                     
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): C85DF9DB-279D-4D14-83DC-4D49489E105A
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 2000409230
Partitions will be aligned on 2048-sector boundaries
Total free space is 2669 sectors (1.3 MiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         2099199   1024.0 MiB  EF00  EFI system partition
   2         2099200         2361343   128.0 MiB   0C01  Microsoft reserved ...
   3         2361344       955197439   454.3 GiB   0700  Basic data partition
   4      1980418048      2000408575   9.5 GiB     2700  Basic data partition
   5       955197440      1345822719   186.3 GiB   8300  
   6      1345822720      1346871295   512.0 MiB   BF01  
   7      1346871296      1980418047   302.1 GiB   BF01

建立 boot pool

zpool create \
    -o ashift=12 -d \
    -o feature@async_destroy=enabled \
    -o feature@bookmarks=enabled \
    -o feature@embedded_data=enabled \
    -o feature@empty_bpobj=enabled \
    -o feature@enabled_txg=enabled \
    -o feature@extensible_dataset=enabled \
    -o feature@filesystem_limits=enabled \
    -o feature@hole_birth=enabled \
    -o feature@large_blocks=enabled \
    -o feature@lz4_compress=enabled \
    -o feature@spacemap_histogram=enabled \
    -o feature@zpool_checkpoint=enabled \
    -O acltype=posixacl -O canmount=off -O compression=lz4 \
    -O devices=off -O normalization=formD -O relatime=on -O xattr=sa \
    -O mountpoint=/boot -R /mnt \
    bpool /dev/nvme0n1p6
參數重點
➤ ashift=12 是為了要讓新一代 4KB block size 硬碟發揮最好的效能。
➤ canmount=off 表示 bpool 不是主要的掛載點,而是下面接著建立的 filesystem datasets。
➤ muntpoint=/boot 將來這個 bpool 要掛在 /boot
➤ -R /mnt 表示等一下會被掛在另一個指定的地方 /mnt

建立 root pool

zpool create \
    -o ashift=12 \
    -O acltype=posixacl -O canmount=off -O compression=lz4 \
    -O dnodesize=auto -O normalization=formD -O relatime=on \
    -O xattr=sa -O mountpoint=/ -R /mnt \
    rpool /dev/nvme0n1p7

建立 filesystem datasets 當作容器

zfs create -o canmount=off -o mountpoint=none rpool/ROOT
zfs create -o canmount=off -o mountpoint=none rpool/USERDATA
zfs create -o canmount=off -o mountpoint=none bpool/BOOT

建立並掛載真正的 rootfs, boot & home filesystem datasets

zfs create -o canmount=on -o mountpoint=/     rpool/ROOT/ubuntu
zfs create -o canmount=on -o mountpoint=/home rpool/USERDATA/ubuntu
zfs create -o canmount=on -o mountpoint=/boot bpool/BOOT/ubuntu
現在 filesystem datasets 都已經掛在 /mnt 之下,接下來就是將整個系統拷貝進去。

拷貝現有系統

先建立一個現有系統 Btrfs 的唯獨快照
mkdir /media/btrfs
mount /dev/nvmen0p5 /media/btrfs
btrfs subvolume snapshot -r /media/btrfs/@ /media/btrfs/@.latest
btrfs subvolume snapshot -r /media/btrfs/@home /media/btrfs/@home.latest
接下來就是用 rsync 做完整的系統拷貝
rsync -av --info=progress2 --no-inc-recursive --human-readable /media/btrfs/ /mnt
umount /media/btrfs

將系統 chroot 到 /mnt

for d in proc sys dev; do mount --rbind /$d /mnt/$d; done
chroot /mnt
echo "nameserver 8.8.8.8" >> /etc/resolv.conf  # 設定chroot下的DNS

安裝 GURB

mount /boot/efi  # 掛上EFI分區
grub-probe /boot # 確定目前系統可以認得ZFS
update-initramfs -c -k all # 更新initrd
vi /etc/default/grub
# Add init_on_alloc=0 to: GRUB_CMDLINE_LINUX_DEFAULT # Save and quit.
update0grub # 更新boot紀錄
grub-install --target=x86_64-efi --efi-directory=/boot/efi \ --bootloader-id=ubuntu --recheck --no-floppy

修正 filesystem 掛載的順序

mkdir /etc/zfs/zfs-list.cache
touch /etc/zfs/zfs-list.cache/bpool
touch /etc/zfs/zfs-list.cache/rpool
ln -s /usr/lib/zfs-linux/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d
zed -F &
# 用以下命令確認快取的檔案不是空的
cat /etc/zfs/zfs-list.cache/bpool
cat /etc/zfs/zfs-list.cache/rpool
# 確認後停止 zed
fg
Press Ctrl-C.

離開 chroot 然後準備重新開機

mount | grep -v zfs | tac | awk '/\/mnt/ {print $3}' | \
xargs -i{} umount -lf {}
zpool export -a  # 為了確保安全, 卸載 zpool
reboot           # 重新開機
如果一切正常,重開機應該就會看到grub開機選單,選擇 Ubuntu 開機之後就會看到登入畫面。

後記

我這次運氣不錯,一方面也是有仔細參考前人的文件,所以很順利的轉換成 ZFS 系統,沒有把硬碟搞爛掉,造成無法開機。如果遇到開機的問題,一定要有 Ubuntu 的開機碟在身邊,用Live-CD 的環境把 filesystem 再掛載上來,才能進行系統修復。

參考文件

2020年6月1日 星期一

How to make smartcard reader on Dell Latitude 5480 working with Ubuntu

Dell Latitude 5480 has an embedded smartcard reader which should be based on BCM5880 secure processor from Broadcom. BCM5880 supports not only smartcard reader but also fingerprint reader. This article deals only the smartcard reader part. As for fingerprint reader, as of today, Ubuntu 20.04, still cannot have a working driver for that (see ref 1).

rick@E5480:~$ lsusb
Bus 002 Device 003: ID 0bda:8153 Realtek Semiconductor Corp. RTL8153 Gigabit Ethernet Adapter
Bus 002 Device 002: ID 0424:5807 Microchip Technology, Inc. (formerly SMSC) Hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 8087:0a2b Intel Corp. 
Bus 001 Device 014: ID 413c:3016 Dell Computer Corp. Optical 5-Button Wheel Mouse
Bus 001 Device 011: ID 05e3:0610 Genesys Logic, Inc. 4-port hub
Bus 001 Device 010: ID 0bda:4014 Realtek Semiconductor Corp. 
Bus 001 Device 015: ID 05e3:0723 Genesys Logic, Inc. GL827L SD/MMC/MS Flash Card Reader
Bus 001 Device 017: ID 1a2c:0c21 China Resource Semico Co., Ltd 
Bus 001 Device 012: ID 13fd:1340 Initio Corporation Hi-Speed USB to SATA Bridge
Bus 001 Device 009: ID 05e3:0608 Genesys Logic, Inc. Hub
Bus 001 Device 018: ID 058f:9520 Alcor Micro Corp. Watchdata W 1981
Bus 001 Device 005: ID 0424:2807 Microchip Technology, Inc. (formerly SMSC) Hub
Bus 001 Device 004: ID 0c45:6717 Microdia Integrated_Webcam_HD
Bus 001 Device 003: ID 0a5c:5834 Broadcom Corp. 5880
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

The default Ubuntu 20.04 desktop installation does not install the necessary driver for smartcard reader to work. Did a search on google and find ref.2 is kind of close to my problem. But the document is quite old and it is referring to Ubuntu 9.04!! Since my Ubuntu 20.04 is installed on ZFS file system I decided to try that procedure. Before the installation I can do a quick zfs snapshot of my root filesystem and if anything go wrong I can take the chance to practice how to rollback to previous snapshot, I hope...

The installation turns out pretty strait forward. Just one command line and you are all set.
rick@E5480:~$ sudo apt install pcscd libpcsc-perl pcsc-tools libccid 
Per the instruction, pcscd needs to be restarted.
rick@E5480:~$ sudo /etc/init.d/pcscd restart
Restarting pcscd (via systemctl): pcscd.service.
Then use pcsc_scan to make sure smartcard reader is really working. I have card inserted and I can see ATR response from my card, nice ~
rick@E5480:~$ pcsc_scan 
Using reader plug'n play mechanism
Scanning present readers...
0: Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00
1: Broadcom Corp 5880 [Contactless SmartCard] (0123456789ABCD) 01 00
2: Alcor Micro AU9520 02 00
 
Mon Jun  1 14:04:07 2020
 Reader 0: Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00
  Event number: 0
  Card state: Card removed, 
 Reader 1: Broadcom Corp 5880 [Contactless SmartCard] (0123456789ABCD) 01 00
  Event number: 0
  Card state: Card removed, 
 Reader 2: Alcor Micro AU9520 02 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B D8 96 00 81 B1 FE 45 1F 07 43 48 54 47 50 4B 49 4A DD

ATR: 3B D8 96 00 81 B1 FE 45 1F 07 43 48 54 47 50 4B 49 4A DD
+ TS = 3B --> Direct Convention
+ T0 = D8, Y(1): 1101, K: 8 (historical bytes)
  TA(1) = 96 --> Fi=512, Di=32, 16 cycles/ETU
    250000 bits/s at 4 MHz, fMax for Fi = 5 MHz => 312500 bits/s
  TC(1) = 00 --> Extra guard time: 0
  TD(1) = 81 --> Y(i+1) = 1000, Protocol T = 1 
-----
  TD(2) = B1 --> Y(i+1) = 1011, Protocol T = 1 
-----
  TA(3) = FE --> IFSC: 254
  TB(3) = 45 --> Block Waiting Integer: 4 - Character Waiting Integer: 5
  TD(3) = 1F --> Y(i+1) = 0001, Protocol T = 15 - Global interface bytes following 
-----
  TA(4) = 07 --> Clock stop: not supported - Class accepted by the card: (3G) A 5V B 3V C 1.8V 
+ Historical bytes: 43 48 54 47 50 4B 49 4A
  Category indicator byte: 43 (proprietary format)
+ TCK = DD (correct checksum)

Possibly identified card (using /usr/share/pcsc/smartcard_list.txt):
3B D8 96 00 81 B1 FE 45 1F 07 43 48 54 47 50 4B 49 4A DD
	Citizen Digital Certificate, Taiwan (PKI)
	http://moica.nat.gov.tw/

Now I can happily use online ATM and report my tax on Ubuntu (^_^)

[Reference]