今天参加了OpenSPARC的研讨会,在会上展示ZFS文件系统的特性,现场气氛感觉很不错,自己编写的一些简单的Demo程序将ZFS的数据安全、Samba共享、压缩等特性做了很好的展示,效果自我感觉非常好。
然而展示过程中出现了一个小小的意外,由于一个此前的一个ZFS Pool的挂载点没有删除,导致我的另一个Demo程序报告了错误,存储池创建失败。
# zpool create r1pool raidz c1t0d0s3 c1t0d0s4
mountpoint /r1pool is not empty, the pool has been created, but not mouted.
于是我手工去删除该挂载点/r1pool的时候,由于匆忙,误将/rpool的目录下面内容删除了,当时系统提示了busy的错误,但是为时已晚,最重要的是我的系统安装的是ZFS Root, 根存储池的名字就是rpool,在/rpool/boot/grub下面有最重要的menu.lst文件,也一并被删除了。
当然没有意识到这个问题,演示结束后匆匆关机,到晚上一打开机器,what? 为什么系统无法进入了,只能到 grub> 菜单!
grub>
这可糟糕了,因为这台笔记本上还装有Windows XP,是双系统,这两个系统的启动切换都要依靠menu.lst完成,这个文件一旦被删,何止Solaris无法启动,Windows XP也无法启动了。
于是我尝试了若干手工命令findroot,均告失败
grub> findroot (pool_rpool, 1, a)
File not found
哦,原来/rpool/etc/bootsign, /rpool/boot/grub/bootsign也同样丢失了,实际上findroot命令已经不太可能起作用了,于是改用了传统的root命令,进入了系统。
grub> root (hd0, 1, a)
grub> kernel$ /platform/i86pc/kernel/$ISADIR/unix -B $ZFS-BOOTFS
grub> module$ /platform/i86pc/$ISADIR/boot_archive
grub> boot
Okay,这时进入了Solaris系统,于是我开始手工恢复/rpool下面原有的内容,
# mkdir -p /rpool/boot/grub/bootsign /rpool/etc
# echo "pool_rpool" > /rpool/etc/bootsign
# touch /rpool/boot/grub/bootsign/pool_rpool
然后找了一个menu.lst的样例文件修改后放到了 /rpool/boot/grub/menu.lst
default 0
timeout 10
#---------- ADDED BY BOOTADM - DO NOT EDIT ----------
title Solaris snv_101
findroot (pool_rpool,1,a)
kernel$ /platform/i86pc/kernel/$ISADIR/unix -B $ZFS-BOOTFS
module$ /platform/i86pc/$ISADIR/boot_archive
#---------------------END BOOTADM--------------------
title Windows XP
rootnoverify (hd0,0)
chainloader +1
重启之后,万事大吉了,两个系统都能够通过grub正常启动了。
通过这次事件使我意识到一个比较现实的问题,到底/rpool是要自动挂载还是不自动挂载呢?如果自动挂载,就可能出现像我这样的白痴情况,误操作删了grub启动所需的重要文件;而如果不自动挂载,很多用户可能又不知道如何编辑这个menu.lst。这成了一个两难问题,看起来如果给顶级文件系统打快照snapshot可以避免这种误操作的发生,但是即便有快照,由于系统无法正常进入grub,事实上数据仍然无法恢复(grub界面中无法修改ZFS的相关数据)。
不过经过这次教训,我还是倾向于不要在系统启动时挂载/rpool,而只在必要的时候才挂载。
# zfs set canmount=noauto rpool
这样,系统启动的时候就不会挂载这个顶层文件系统,也就不会出现我这样的误删重要文件的情况。如果需要临时修改 /rpool 下面内容的时候(机会非常小),只需要手工挂载就可以:
# zfs mount rpool
我觉得这样的设置代价相对较小,而对保护系统重要文件的安全是有好处的。
当然如果真的出现了我遇到的问题,就只能按这种方式手工输入grub命令进入系统了,对记忆力和键盘录入是一个小小的考验,Good Lucky!