把 FreeBSD 7.1 直接安裝在 2TB 以上的硬碟裡

應該很多人都知道 FreeBSD 裝大於 2TB 的硬碟一直都是一個問題,
一般想要裝 2TB 以上硬碟的人都難免會來到 FreeBSD 官網的這個頁面:
http://www.freebsd.org/projects/bigdisk/index.html
它的主要問題是因為大部分跟硬碟相關的程式有這樣的特徵:

  1. 以 32-bit 整數表示容量相關的資料。
  2. 單位是 sector,一個 sector 是 512 bytes。
  3. 32-bit 只能表示 4T sectors,也就是 2TB。

跟硬碟相關的程式以及它們的特徵大致可以這樣歸納:

  1. 以前的 UFS 檔案系統只能支援到 2TB,2003 年起的 UFS2 則以 64-bit 整數來表示相關資料,使得檔案系統本身可支援到 2TB 以上。
  2. MBR、fdisk、bsdlabel 仍是以 32-bit 整數設計的,因此即使下層的檔案系統支援 2TB 以上的容量也沒有用。
  3. 以 GPT 代替 MBR 的話,可以解決問題,但 FreeBSD 7.1 之前並不支援 boot 在 GPT 分割區的功能。
  4. FreeBSD 目前為止 (7.1-RELEASE) 的 sysinstall 並不支援 GPT,所以安裝系統時無法分割 2TB 以上的硬碟。

再看看這個網頁下方的各種表格後還能發現,
目前 FreeBSD 相關的支援並不十分完善,
且有些功能已經拖了相當多年了。

如果在 Google 上隨便搜尋一下,
一定會發現一堆人會貼出這樣的指令做為教學:

必須注意這樣的教學只適用於你已經事先將系統安裝在某個 2TB 以下的硬碟裡,
也就是事後想加掛 2TB 以上的硬碟時才可以這樣做,
而且照著下的話只會割出一個分割區,
如果是打算直接把系統灌在 2TB 的硬碟上且造出多個 slice,
那麼這種做法完全不可行。

若是更仔細的用 Google 搜尋這個問題的話,
應該會發現這個網頁:
http://m8d.de/news/freebsd-on-gpt.php
它才是真正在教人如何把 FreeBSD 安裝在 2TB 以上的硬碟裡,
這個安裝方法其實類似 Gentoo Linux 從 stage2 開始的安裝方式,
先用 Live CD 開機並 mount 硬碟後,
分割完再自己把檔案弄到分割完的硬碟上去,
這方面 Gentoo 只要抓個壓縮檔來解壓縮就可以了,
FreeBSD 則是要 run 那個 install.sh;
必須注意的是,
一般要 boot 在 GPT 上是需要 EFI BIOS 來支援的,
而這個教學主要是因為大部分的機器沒有 EFI BIOS,
所以是以沒有 EFI BIOS 的狀況為前提來教人如何安裝和設定。

在 FreeBSD 7.1 以後就提供了 dvd image 的下載,
所以其實也不需要去管教學裡面的 disc1 disc2 什麼的,
上網下載 iso 檔什麼的步驟也可以省略,
直接 dvd image 抓下來燒進 DVD+R 或 DVD-R 的空片裡就什麼都有了,
教學裡面也有提醒到,
有很多 tools 都被藏在 dist 這個目錄下 (其實就是一個完整的 FreeBSD 該有的東西都會在那下面),
預設的 path 裡實際上是少很多東西的,
如果沒注意這點應該安裝過程中打一堆指令都會說 Command not found,
用 DVD 開的話可能要去 /cdrom/dist 裡找。

在分割硬碟時我們使用的是 gpart 而不是直接操作 gpt,
gpart 是 GEOM framework 裡的 tool,
透過它可以支援 multiple partitioning schemes,
在 FreeBSD 7 開始比較建議使用 gpart 而不是 gpt。

一開始是要把整顆硬碟的 partitioning scheme 指定為 GPT,
現在大家都用 SATAII RAID 了所以裝置代號一般會是 da0 (不需要打路徑):

再來打 gpart show 就可以看到目前整顆硬碟是什麼分割區都沒割的,
至於 sector 34 之前不能使用是正常現象,
那前面的空間是要放 PMBR (sector 0)、primary GPT header (sector 1) 和 primary GPT table (sector 2~33) 用的。

使用 GPT 來開機需要一個 8KB 的小小 boot 分割區才行,
所以會在 sector 34 的位置先造出一個 8KB (16 sectors) 的分割區:

這樣就會產生一個叫做 da0p1 的分割區,
而下次再做 gpart add 則會生出叫 da0p2 的分割區,
以此類推;
因為 gpart add 的 -b -s -t 三個參數是必填的,
所以建議每次分割時都要用 gpart show 確認一下起始的 sector,
指令的下法跟上面類似:
gpart add -b <start sector> -s <size> -t <type> da0,
size 是用 sector 來計算的,
所以算完 KBytes 數以後記得把它乘以 2,
type 的話應該只會用到 freebsd-swap 跟 freebsd-ufs 兩種,
其它的 types 去 man 一下 gpart 應該就會看得到;
割完以後大致上會像是這樣:

該割的分割區都割完之後,
就要設定開機相關的東西,
首先是把 bootcode 寫入:

接著是製作 FreeBSD loader 需要用到的 bootcode 並寫入 boot 分割區:

最後只要很開心的 newfs 就可以了:

開機用的 da0p1 和當成 swap 用的分割區 da0p3 不用去動它,
接下來就可以把這些分割區根據預先規劃的新系統 layout 來 mount 到 /mnt 下面去。

接下來就是把系統複製到 mount 上去的分割區裡,
這個除了照那個網頁的教學跑光碟裡的 install.sh 之外,
你也可以事先找一顆小硬碟用 sysinstall 裝好以後把整個系統給 tar 起來,
然後在這裡設好網路後用 sftp 或 NFS 把它傳進來直接解壓縮,
這些做法其實都是可以的 (後者比較類似 Gentoo Linux 的 stage2 裝法);
總之裝完以後一定要記得去 /mnt/etc 下把 fstab 寫好:

boot 用的 da0p1 不用 mount 所以不必寫,
接下來重開機以後就可以開始搞 kernel 和 world 然後裝 ports 了。


Update: 2010-05-13
有人說那個來源網站掛了不知道怎麼玩,
所以這邊追加一點資訊。

首先用光碟進到 fixme shell 來敲上面那堆指令的步驟很簡單,
就拿光碟開機跳出選單以後選完鍵盤語系再選 FIXME 就到 shell 下了。

再來就是安裝系統 (假設上面的 da0p2 ~ da0p6 那些都切好也暫時 mount 在 /mnt 下的目錄裡了),
以 8.0-RELEASE 的 DVD 來說會在 /dist/8.0-RELEASE 下有一群目錄,
每個目錄底下大都有個叫 install.sh 的檔案。
在執行這些 install.sh 之前要設定一個環境變數,
比方說事先 newfs 好的 /、/usr、/var、/home 等分割區已經掛在 /mnt 下了,
那就輸入 export DESTDIR=/mnt,
再來就 cd 進你想要裝的目錄然後執行 ./install.sh 就好了,
基本上 base 跟 kernels 是必裝項目。

安裝 kernel 的方法是 ./install.sh generic,
然後 cd /mnt/boot/kernel 再 cp -a ../GENERIC/* . 把 kernel 和 kernel modules 都複製過去 (因為 boot loader 是自動抓 /boot/kernel/kernel)。
src 的話為了之後 cvsup 方便建議是直接全裝了,
所以直接 ./install.sh all 就可以,
不然會打到手酸死又沒什麼好處。
除了這兩項需要在 install.sh 後面接參數外,
其它的單獨 run install.sh 不接參數就可以了。


Update: 2010-05-14
有人說這幾步在 8.0-RELEASE 會炸掉:

所以來 update 一下。
基本上 7.1-RELEASE 的 /boot/gptboot 是 7551 bytes,
而這個範例的來源網頁是割 8KB 給 freebsd-boot 分割區,
所以它補了 641 個 0 在後面湊成 8192 bytes,
那個 641 並不是無差別照著打就好的。

基本上現在只要一行指令就能搞定這些事了:

-i 1 是指 index 1 of da0,
就是 da0p1 的意思。
如果想用 GPT 分割完直接上 ZFS 來開機的話,
就把上面的 gptboot 改成 gptzfsboot 就可以了,
不過 gptzfsboot 有 27KB 左右,
只割 8KB 是不夠的。
關於怎樣 boot 在 ZFS 上的部分可以參閱:
http://wiki.freebsd.org/RootOnZFS/GPTZFSBoot/RAIDZ1
這個網頁是以 RAIDZ1 為例說明的。

但是要上 ZFS 的話我必須再附帶提醒一點,
8.0-RELEASE 到 8.0-STABLE 的 ZFS storage pool 版本是從 v13 升到 v14,
所以開機會提示你打 zpool upgrade -a 升級。
打下去升級是沒關係,
但是請記得寫入新的 gptzfsboot 再重開 (installkernel 後會得到新的 gptzfsboot 檔):

不然保證你開機抓不到 kernel 直接陷入悲劇 (v13 loader v.s. v14 pool)。
說悲劇其實也沒那麼糟糕,
用各種方法從其它地方弄到新版的 gptzfsboot 再寫入就好了。