linux 下使用 ZFS 初探 – Part1
Sun 的 ZFS 優秀的功能我想網路上看到不少,不過一直沒時間去裝一套 OpenSolaris 系統來測試,不過有一群 developer 實做成為 Filesystem in userspace (FUSE) 下的 zfs 的支援,所以 Linux Kernel 不支援 zfs 還是可以拿來使用。
那要使用哪個 Linux 版本呢,我想手上本身挑自己的 Mandriva cooker 機器,用 Cooker 好處就是每次都可以用最新的程式套件,畢竟是一個發展用的版本所以測新的程式軟體就很方便…
先使用 urpmi 安裝上 zfs-fuse 套件後即可使用,該套件安裝好後使用 rpm -ql 檢視可以看到一些檔案清單:
/etc/bash_completion.d/zfs-fuse
/etc/rc.d/init.d/zfs-fuse
/usr/sbin/zdb
/usr/sbin/zfs
/usr/sbin/zfs-fuse
/usr/sbin/zpool
/usr/sbin/ztest
/usr/share/doc/zfs-fuse
/usr/share/doc/zfs-fuse/BUGS
/usr/share/doc/zfs-fuse/CHANGES
/usr/share/doc/zfs-fuse/HACKING
/usr/share/doc/zfs-fuse/INSTALL
/usr/share/doc/zfs-fuse/LICENSE
/usr/share/doc/zfs-fuse/README
/usr/share/doc/zfs-fuse/STATUS
/usr/share/doc/zfs-fuse/TESTING
/usr/share/doc/zfs-fuse/TODO
/usr/share/man/man1/zdb.1.lzma
/usr/share/man/man1/zfs.1.lzma
/usr/share/man/man1/zpool.1.lzma
先執行啟動 /etc/init.d/zfs-fuse 這個服務才可以開始使用 zfs 的相關支援。而該服務啟動後,可以看到系統一個名稱為 zfs-fuse 的 daemon 正在運作。然後跑一下 zfs 提供的兩個主要大命令,zpool 與 zfs 這兩個程式看一下輸出:
missing command
usage: zpool command args …
where ‘command’ is one of the following:create [-fn] [-o property=value] …
[-O file-system-property=value] …
[-m mountpoint] [-R root]
…
destroy [-f]add [-fn]
…
remove
…list [-H] [-o property[,...]] [pool] …
iostat [-v] [pool] … [interval [count]]
status [-vx] [pool] …online
…
offline [-t]
…
clear
[device]attach [-f]
detach
replace [-f]
[new-device]scrub [-s]
…import [-d dir] [-D]
import [-o mntopts] [-o property=value] …
[-d dir | -c cachefile] [-D] [-f] [-R root] -a [-v]
import [-o mntopts] [-o property=value] …
[-d dir | -c cachefile] [-D] [-f] [-R root]
[newpool]
export [-f]
…
upgrade
upgrade -v
upgrade [-V version] <-a | pool …>history [-il] [
] …
get <”all” | property[,...]>
…
set
下面這是 zfs 命令輸出:
missing command
usage: zfs command args …
where ‘command’ is one of the following:create [-p] [-o property=value] …
create [-ps] [-b blocksize] [-o property=value] … -V
destroy [-rRf]snapshot [-r] [-o property=value] …
rollback [-rRf]
clone [-p] [-o property=value] …
promote
rename
rename -p
rename -r
list [-rH][-d max] [-o property[,...]] [-t type[,...]] [-s property] …
[-S property] … [filesystem|volume|snapshot] …set
…
get [-rHp] [-d max] [-o field[,...]] [-s source[,...]]
<”all” | property[,...]> [filesystem|volume|snapshot] …
inherit [-r]
…
upgrade [-v]
upgrade [-r] [-V version] <-a | filesystem …>
userspace [-hniHp] [-o field[,...]] [-sS field] … [-t type[,...]]groupspace [-hniHpU] [-o field[,...]] [-sS field] … [-t type[,...]]
mount
mount [-vO] [-o opts] <-a | filesystem>
unmount [-f] <-a | filesystem|mountpoint>
share <-a | filesystem>
unshare [-f] <-a | filesystem|mountpoint>send [-R] [-[iI] snapshot]
receive [-vnF]
receive [-vnF] -dallow
allow [-ldug] <”everyone”|user|group>[,...]
[,...]allow [-ld] -e
[,...]
allow -c
[,...]
allow -s @setname
[,...]unallow [-rldug] <”everyone”|user|group>[,...]
[
[,...]]
unallow [-rld] -e [
[,...]]
unallow [-r] -c [
[,...]]
unallow [-r] -s @setname [
[,...]]Each dataset is of the form: pool/[dataset/]*dataset[@name]
For the property list, run: zfs set|get
For the delegated permission list, run: zfs allow|unallow
由於這台機器上沒有其他可用的硬碟分割區空間,所以只好使用 dd 建立幾個大檔案模擬實際上的可用區塊空間。
[root@info /]# mkdir /zfs
[root@info /]# dd if=/dev/zero of=/zfs/zfs-1.dat bs=1024k count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.594376 s, 176 MB/s
[root@info /]# dd if=/dev/zero of=/zfs/zfs-2.dat bs=1024k count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.671803 s, 156 MB/s
分別在建立 /zfs 目錄建立 zfs-1.dat 與 zfs-2.dat 檔案,每個檔案分別為 100MB 的大小。下面繼續使用 zpool 建立 pool 空間:
[root@info /]# zpool create test /zfs/zfs-1.dat /zfs/zfs-2.dat
然後使用 zpool list 看一下建立的結果:
[root@info /]# zpool list
NAME SIZE USED AVAIL CAP HEALTH ALTROOT
test 191M 78K 191M 0% ONLINE -
目前的 pool 空間為 191MB。使用 zpool status 看一下詳細狀態:
[root@info /]# zpool status
pool: test
state: ONLINE
scrub: none requested
config:NAME STATE READ WRITE CKSUM
test ONLINE 0 0 0
/zfs/zfs-1.dat ONLINE 0 0 0
/zfs/zfs-2.dat ONLINE 0 0 0errors: No known data errors
目前初步 pool 已經建立完成,下面就可以使用 zfs 該命令建立實際可用的空間。
[root@info /]# zfs create test/n1
[root@info /]# zfs create test/n2
[root@info /]#
[root@info /]# zfs list
NAME USED AVAIL REFER MOUNTPOINT
test 134K 159M 23K /test
test/n1 21K 159M 21K /test/n1
test/n2 21K 159M 21K /test/n2前面建立的 pool 名稱為 test,所以使用 zfs create 時候需要繼續指定使用 test 這個 pool 名稱,然後依序建立 n1 與 n2 這兩個檔案系統項目。不過目前預設掛載點是在 /test 內的 n1 與 n2,實際使用上不一定都位於 /test 目錄內使用,所以調整一下掛載點的配置:
[root@info /]# zfs set mountpoint=/n1 test/n1
[root@info /]# zfs set mountpoint=/n2 test/n2
[root@info /]#
[root@info /]# zfs list
NAME USED AVAIL REFER MOUNTPOINT
test 152K 159M 23K /test
test/n1 21K 159M 21K /n1
test/n2 21K 159M 21K /n2所以目前指定到 /n1 與 /n2 這兩個掛載點的目錄位置上。使用 df -h 檢視也可以看到已經掛入的資訊:
[root@info /]# df -h | grep test
test 159M 21K 159M 1% /test
test/n1 159M 21K 159M 1% /n1
test/n2 159M 21K 159M 1% /n2
空間來看,其實 n1 與 n2 都是共用 159M 的 pool 空間,所以磁碟空間分配上會非常有效率,這就與 Linux 上面使用 LVM 的架構有所不同。
產生一些檔案佔用 n1 的檔案系統空間:
[root@info /]# for((i=1;i<100;i++)); do cat /etc/termcap >> /n1/file1.dat; done
[root@info /]#
[root@info /]# ls -lh /n1/
total 66M
-rw-r–r– 1 root root 67M Jan 21 05:32 file1.dat
[root@info /]#然後使用 zfs list 檢視結果:
[root@info /]# zfs list
NAME USED AVAIL REFER MOUNTPOINT
test 66.9M 92.1M 24K /test
test/n1 66.6M 92.1M 66.6M /n1
test/n2 21K 92.1M 21K /n2
[root@info /]#
可以看出來 test/n1 的檔案系統空間已經被佔用了。
[root@info /]# df -h | grep test
test 93M 21K 93M 1% /test
test/n1 159M 67M 93M 42% /n1
test/n2 93M 21K 93M 1% /n2
下面測試 zfs 透通壓縮的支援功能:
[root@info /]# zfs set compression=on test/n2
[root@info /]#
[root@info /]# for((i=1;i<100;i++)); do cat /etc/termcap >> /n2/file1.dat; done
[root@info /]#
[root@info /]# ls -lh /n2/file1.dat
-rw-r–r– 1 root root 67M Jan 21 05:37 /n2/file1.dat
[root@info /]#
目前只有針對 test/n2 設定壓縮功能,然後與前面一樣大小內容的檔案提供比較測試,然後再次 zfs list 查看結果:
[root@info /]# zfs list
NAME USED AVAIL REFER MOUNTPOINT
test 110M 48.9M 21K /test
test/n1 66.6M 48.9M 66.6M /n1
test/n2 43.0M 48.9M 43.0M /n2
[root@info /]#
用 df 再次確認一下:
[root@info n1]# df -h | grep test
test 44M 21K 44M 1% /test
test/n1 111M 67M 44M 61% /n1
test/n2 92M 49M 44M 53% /n2
[root@info n1]#
所以可以發現到相同的檔案,但是產生佔用的空間相差至少 20MB 空間。不過為了確認兩個檔案都一樣的內容,使用 md5sum 確認一下更好。
[root@info /]# md5sum /n1/file1.dat /n2/file1.dat
30e4f82d620e3bdc3999ce96f5c93cde /n1/file1.dat
30e4f82d620e3bdc3999ce96f5c93cde /n2/file1.dat
[root@info /]#
下面來玩玩新增 pool 的空間作法,所以還是用 dd 建立大檔並使用 zpool 加入使用。
[root@info /]# dd if=/dev/zero of=/zfs/zfs-3.dat bs=1024k count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.534388 s, 196 MB/s
[root@info /]#
[root@info /]# zpool add test /zfs/zfs-3.dat
[root@info /]#
[root@info /]# zpool list
NAME SIZE USED AVAIL CAP HEALTH ALTROOT
test 286M 115M 171M 40% ONLINE -
[root@info /]#
目前可以看出 pool 的空間已經成長到達 286M,而之前為 159MB。那現在使用 zfs 命令檢視旗下檔案系統的狀態:
[root@info /]# zfs list
NAME USED AVAIL REFER MOUNTPOINT
test 115M 139M 21K /test
test/n1 66.6M 139M 66.6M /n1
test/n2 48.2M 139M 48.2M /n2
[root@info /]#
所以 test 這個 pool 空間變大後,旗下的檔案系統可用空間也直接變大了。使用 df -h 檢視應該更清楚:
[root@info /]# df -h | grep test
test 140M 21K 140M 1% /test
test/n1 206M 67M 140M 33% /n1
test/n2 188M 49M 140M 26% /n2
來測試 clone 功能…
[root@info /]# zfs clone test/n1@20100121 test/n3
[root@info /]#
[root@info /]# zfs set mountpoint=/n3 test/n3
[root@info /]#
[root@info /]# zfs list
NAME USED AVAIL REFER MOUNTPOINT
test 115M 139M 21K /test
test/n1 66.6M 139M 66.6M /n1
test/n2 48.2M 139M 48.2M /n2
test/n3 16K 139M 66.6M /n3
目前的 test1/n1 另外 clone 複製一份成為 test/n3 提供使用,所以 test3/n3 內容會與 test1/n2 完全一樣。其中使用 clone 命令,來源的檔案系統是 test/n1 沒錯,但是後面要多一個 @ 敘述,這邊就指定一個時間紀錄點應對比較好記。
[root@info /]# df -h | grep test
test 140M 21K 140M 1% /test
test/n1 206M 67M 140M 33% /n1
test/n2 188M 49M 140M 26% /n2
test/n3 206M 67M 140M 33% /n3
透過 df 的結果可以確認空間結果都相同,當然 /n3 內也會有原本的檔案項目。
不過呢… 詳細看一次剛剛內容,我驚訝的是上面那個 zfs list 輸出時候顯示 test/n3 佔用空間為 16K,竟然與 test/n1 佔用空間不一樣,莫非厲害到可以紀錄相同檔案的空間?那我修改一下 /n3 該目錄內的檔案,看看結果會如何變化…
[root@info ~]# ls -lh /n1/file1.dat
-rw-r–r– 1 root root 67M Jan 21 05:46 /n1/file1.dat
[root@info ~]#
[root@info ~]# cat /n1/file1.dat >> /n3/file1.dat
[root@info ~]#
[root@info ~]# zfs list
NAME USED AVAIL REFER MOUNTPOINT
test 174M 80.7M 21K /test
test/n1 66.6M 80.7M 66.6M /n1
test/n2 48.2M 80.7M 48.2M /n2
test/n3 66.6M 72.0M 133M /n3
[root@info ~]#
[root@info ~]# df -h | grep test
test 73M 21K 73M 1% /test
test/n1 139M 67M 73M 49% /n1
test/n2 121M 49M 73M 41% /n2
test/n3 206M 133M 73M 65% /n3
[root@info ~]#
[root@info ~]# ls -lh /n3/file1.dat
-rw-r–r– 1 root root 133M Jan 21 06:31 /n3/file1.dat
這時候我發現神奇事情…. /n3/file1.dat 的確變成 133M 的大小,但是檢視 test/n3 本身 zfs 的佔用空間卻只有 66.6M,這表示 zfs 本身已經聰明到紀錄檔案本身實際上還共用哪些區塊空間,真是令人感覺驚豔….. 所以說往後透過 clone 的命令產生的新的檔案系統,其實速度上會非常的快,因為只是標注使用的區塊資訊而非真正去複製一份資料內容。
不過我剛剛是使用 >> 方式附加的,所以只有紀錄附加上資料的資訊,那現在我用 hexedit 命令直接開啟 /n3/file1.dat 檔案編修內容,然後看一下最終結果…..
[root@info n3]# zfs list
NAME USED AVAIL REFER MOUNTPOINT
test 183M 71.4M 21K /test
test/n1 66.6M 71.4M 66.6M /n1
test/n2 48.2M 71.4M 48.2M /n2
test/n3 67.2M 71.4M 133M /n3
可以觀察到 test/n3 本身實際佔用空間變大了,這再次證明 zfs 真的非常優秀…. 對於磁碟空間的分配管理機制有獨到的設計,更能夠充分發揮磁碟空間的使用。而繼續看一下 zfs 的 manpage 其實就已經有提到:
Clones
A clone is a writable volume or file system whose initial contents are the same as another dataset. As with snapshots, creating a clone is nearly instantaneous, and initially consumes no additional space.
原來這是可以讀寫版的 snapshot 功能… 而 snapshot 命令依據 manpage 說明,本身為唯讀的性質。
初探測試 Part1 先到這邊….

最近迴響