dtlchm 发表于 2009-03-27 16:29

ZFS文件系统的学习(二)


                       
               
       
                               
    ZFS概况
      ZFS是Sun开发的基于Solaris平台的最新一代文件系统。Solaris已经于2005年6月正式开源,ZFS作为Solaris的一部分当然也是开源的,这一点是从它正式介绍到OpenSolaris开源社区那天就开始了。2005年10月下旬ZFS正式集成到Solaris Express中,也就是OpenSolaris开源社区中,这标志着全世界的开发者和用户可以开始体验ZFS所带来的全新感受。可以这么说,ZFS对业界所带来的冲击,无论是它的超简单易用性,超大容量,还是简单的设计理念无一不是革命性的。ZFS有很多全新的特性,简单来说可以归纳成以下几点:
      1. 简单易用性
      在设计ZFS时,有一个最基本的原则就是要把系统管理员从繁琐而又很容易出错的日常操作中解放出来,而不是整天纠缠于系统的维护,调整与配置中。比个例
子,我们要创建一个1G的mirror用已有的创建文件系统的方法。系统disk分布情况: 0:c1t5d0 1:c1t6d0
先在各个盘中分出大个大小为1G的slice.
      * 在UFS上创建与删除
      # metadb -a -f c1t5d0s6 c1t6d0s6
      # metainit d10 1 1 c1t5d0s0
      d10: Concat/Stripe is setup
      # metainit d20 1 1 c1t6d0s0
      d20: Concat/Stripe is setup
      # metainit m0 -m d10
      m0: Mirror is setup
      # metattach m0 d20
      m0: submirror d20 is attached
      # newfs /dev/md/dsk/m0
      newfs: construct a new file system /dev/md/rdsk/m0: (y/n)? y
      /dev/md/rdsk/m0:      2097152 sectors in 64 cylinders of 128 tracks, 256 sectors
                1024.0MB in 32 cyl groups (2 c/g, 32.00MB/g, 15040 i/g)
      super-block backups (for fsck -F ufs -o b=#) at:
         32, 65824, 131616, 197408, 263200, 328992, 394784, 460576, 526368, 592160,
         1447456, 1513248, 1579040, 1644832, 1710624, 1776416, 1842208, 1908000,
         1973792, 2039584
      # mount /dev/md/dsk/m0 /mnt
      # df -lhF ufs
      Filesystem             size   usedavail capacityMounted on
      /dev/dsk/c0t1d0s0       11G   4.0G   7.0G    37%    /
      /dev/dsk/c0t1d0s7      223M   1.0M   200M   1%    /export/home
      /dev/md/dsk/m0         965M   1.0M   906M   1%    /mnt
      bash-3.00# umount /mnt
      bash-3.00# metaclear m0
      m0: Mirror is cleared
      bash-3.00# metaclear d10
      d10: Concat/Stripe is cleared
      bash-3.00# metaclear d20
      d20: Concat/Stripe is cleared
      bash-3.00# metadb -f -d c1t6d0s6 c1t5d0s6
    *在ZFS上创建与删除
      # zpool create -f pool mirror c1t6d0 c1t5d0
      # zfs create pool/fs
      # zfs set quota=1G pool/fs
      # zfs set mountpoint=/mnt pool/fs
      # zfs list
      NAME      USEDAVAILREFERMOUNTPOINT
      pool      121K16.5G24.5K/pool
      pool/fs24.5K1024M24.5K/mnt
      # zfs destroy pool/fs
      # zpool destroy pool
      以上这些只是一个简单的比较,而ZFS所拥有的大量非常有用特性和特点我会在以后逐个介绍。
      2. 海量容量
      ZFS是128位的文件系统,而当今的文件系统是64位的,也就是说ZFS是64位文件系统的18*10^18 倍。其中各种dataset的大小限制可以参考wikipidia.
      3. 数据的完整与一致性
      ZFS中所有操作都是基于copy-on-write技
术的,所有操作都是原子操作,非0即1。因为所有操作都是基于事务的,所以没有journal日志,这也就是为什么ZFS不需要fsck(1M)。再者,
ZFS对所有数据都进行checksum处理,不会出现悄无声息的坏数据,这样也就不会由于坏数据而出现系统panic.
ZFS文件系统 - (1) zpool create/destroy
要建立ZFS文件系统,首先要建立一个pool,这个pool是所有在它之上的文件系统所共享的存储空间,当然,每一个文件系统的大小容量等可以分别设
定,这个我们以后再分别详细讲述。那么pool是什么?简单的讲,一个pool本身就是一个zfs文件系统,只是它同时又是所有在它之上的文件系统的父文
件系统,它确定了整个建立于它之上的所有ZFS文件系统的基本属性,例如,它是一个简单pool还是一个mirror,或者raidz池。它具有zfs文
件系统的所以属性,例如在其之上建立文件,目录,创建snapshot,clone等等,同时在它之上还可以进行对pool管理的所有操作。例如,add
或remove设备,扩充或缩小池的大小,以及attach或者detach设备等等。
      zpool create的语法如下
zpool create [-fn] [-R root] [-m mountpoint] pool vdev ...
-f    强制执行创建池操作,甚至正在被其他的文件系统所占用
-n    显示配置信息。注:用该参数,该操作并不真正执行
-R    指定整个pool的根目录。也就是所以在这个pool之上的zfs文件系统的mount目录前缀。默认值:/
-m    mount点
pool    所要建立的pool的名字
vdev    "virtual device".具体说包括三类:disk,file和keywords
            disk:就是位于/dev/dsk下的设备文件
            file:普通的文件
            keywords:包括mirror, raidz, raidz1, raidz2 和 spare

下来我们看几个个例子,
1. 创建一个无冗余的pool。
       # zpool create tank c1t4d0
2. 创建一个两路mirror
# zpool create mypool mirror c1t3d0 c1t4d0

3. 创建一个raidz池
# zpool create -f tank raidz2 c2t5d0 c2t4d0 c2t2d04. 创建一个带hot spare的池
# zpool create tank c2t5d0 spare c2t4d0
5. 创建一个pool并指定根目录和mount点
# zpool create -f -R /zfsdir -m /root tank c2t4d0# zfs listNAME   USEDAVAILREFERMOUNTPOINTtank    91K16.5G24.5K/zfsdir/root
      /zfsdir就是以后所有创建与tank之上的文件系统mount点前缀,包括tank本身。/root是mount点。
6. 查看创建一个pool结果,但不真正执行
# zpool create -n -R /zfsdir -m /root tank c2t5d0would create 'tank' with the following layout:
      tank          c2t5d0

      相对应于create,自然就有destroy。destroy的语法如下
zpool destroy [-f] pool
-f    强行删除
例如
# zpool destroy tank# zpool create tank c2t5d0# zfs mounttank                            /tank# cd /tank# zpool destroy tankcannot unmount '/tank': Device busycould not destroy 'tank': could not unmount datasets# zpool destroy -f tank      通过zfs mount查出tank的mount点,然后进入并占用mount目录,这样当试图删除时系统就会报错。用参数-f,系统将删除tank而忽略警告信息。
ZFS文件系统 - (2) zpool add/remove
      在zpool create/destroy一节中,我们讲了怎样创建和删除一个pool。我们之所以说ZFS简单易用,就是它把系统管理员从复杂而繁琐的管理工作中解放出来,从而将更多的时间花在系统的整体构架上,而不是被日常的管理束缚住手脚和头脑。记得九月份在上海出差参加Sun Tech Days活动,在展台上和很多来自各个行业的软件开发者,系统管理员,系统工程师聊。大家有一个共同的认识就是,现在的volume management + 文件系统的管理方式在做系统扩充和缩小时非常复杂,常常为此提前要做各方面的准备,实施计划,操作流程,回退计划等等。而且,往往这些操作需要宕机做offline工作。我想有过这方面经验的人大概都会有这样的经历。
      那么,现在我们有了新的选择:ZFS。我们叫ZFS为文件系统,其实ZFS是集volume management和文件系统功能于一体。对于用户来说,它的volume management功能是透明的。ZFS提供了两个简单的命令add/remove来解决系统扩充和缩小需要。而且,一切都是online操作,一切在线业务都不需要停机。zfs add/remove语法如下:
      zpool add [-fn] pool vdev ...
      zpool remove pool vdev
    注:当前remove操作只支持对hot spares设备的删除。
    我们做一些实验,实验系统环境如下:
      # format
      Searching for disks...done
      AVAILABLE DISK SELECTIONS:
               0. c1t0d0
                  /pci@8,600000/SUNW,qlc@2/fp@0,0/ssd@w21000004cf836e64,0
               1. c1t2d0
                  /pci@8,600000/SUNW,qlc@2/fp@0,0/ssd@w21000004cf836e65,0
               2. c1t3d0
                  /pci@8,600000/SUNW,qlc@2/fp@0,0/ssd@w21000004cf836e6a,0
               3. c1t4d0
                  /pci@8,600000/SUNW,qlc@2/fp@0,0/ssd@w21000004cf836e60,0
               4. c2t1d0
                  /pci@9,700000/scsi@3/sd@1,0
               5. c2t2d0
                  /pci@9,700000/scsi@3/sd@2,0
               6. c2t4d0
                  /pci@9,700000/scsi@3/sd@4,0
               7. c2t5d0
                  /pci@9,700000/scsi@3/sd@5,0
1. 建立一个pool,然后再增加其空间一倍。
      # zpool create mypool c2t5d0
      # zfs list
      NAME   USEDAVAILREFERMOUNTPOINT
      mypool    85K16.5G24.5K/mypool
      # zpool add mypool c2t4d0
      # zfs list
      NAME   USEDAVAILREFERMOUNTPOINT
      mypool    88K33.0G24.5K/mypool
    我们可以看到,再mypool增加了一个新的disk后空间从16.5G变为33.0G。
      # zpool status -v mypool
          pool: mypool
         state: ONLINE
         scrub: none requested
      config:
                NAME      STATE   READ WRITE CKSUM
                mypool      ONLINE       0   0   0
                  c2t5d0    ONLINE       0   0   0
                  c2t4d0    ONLINE       0   0   0
      errors: No known data errors
    我们可以从上面zpool status的输出清晰的看出mypool的盘结构。
      # zpool destroy mypool
    删除mypool
2. 建立一个2路的mirror,再为其扩充空间。
      # zpool destroy mymirror
      # zpool create mymirror mirror c2t1d0 c2t2d0
      # zfs list
      NAME       USEDAVAILREFERMOUNTPOINT
      mymirror    86K16.5G24.5K/mymirror
      # zpool status mymirror
          pool: mymirror
         state: ONLINE
         scrub: none requested
      config:
                NAME      STATE   READ WRITE CKSUM
                mymirror    ONLINE       0   0   0
                  mirror    ONLINE       0   0   0
                  c2t1d0ONLINE       0   0   0
                  c2t2d0ONLINE       0   0   0
      errors: No known data errors
    两个大小分别为16G的硬盘构成一个2路的mirror,容积仍然为16G。
      # zpool add mymirror mirror c2t4d0c2t5d0
      # zpool status mymirror
          pool: mymirror
         state: ONLINE
         scrub: none requested
      config:
                NAME      STATE   READ WRITE CKSUM
                mymirror    ONLINE       0   0   0
                  mirror    ONLINE       0   0   0
                  c2t1d0ONLINE       0   0   0
                  c2t2d0ONLINE       0   0   0
                  mirror    ONLINE       0   0   0
                  c2t4d0ONLINE       0   0   0
                  c2t5d0ONLINE       0   0   0
      errors: No known data errors
      # zfs list
      NAME       USEDAVAILREFERMOUNTPOINT
      mymirror    88K33.0G24.5K/mymirror
    结果显而易见,mymirror的大小变为33G。
      # zpool destroy mymirror

3.建立一个raidz池,增加hot spares设备,然后删除。
      # zpool create mypool raidz c2t1d0 c2t2d0 c2t4d0 spare c2t5d0
      # zfs list
      NAME   USEDAVAILREFERMOUNTPOINT
      mypool   102K33.1G32.6K/mypool
      # zpool status mypool
          pool: mypool
         state: ONLINE
         scrub: none requested
      config:
                NAME      STATE   READ WRITE CKSUM
                mypool      ONLINE       0   0   0
                  raidz1    ONLINE       0   0   0
                  c2t1d0ONLINE       0   0   0
                  c2t2d0ONLINE       0   0   0
                  c2t4d0ONLINE       0   0   0
                spares
                  c2t5d0    AVAIL
      errors: No known data errors
    对于raidz/raidz1/raidz2来说,整个池的大小等于(N-P) * min(disk size)。N表示disk个数,P为冗余盘的个数,即1或者2。raidz是raidz1的alias。关于数据冗余,我会在以后专门拿出来讨论。hot spares设备不计入池空间。
    # zpool remove mypool c2t5d0
    hot spares设备被删除。
      # zpool status mypool
          pool: mypool
         state: ONLINE
         scrub: none requested
      config:
                NAME      STATE   READ WRITE CKSUM
                mypool      ONLINE       0   0   0
                  raidz1    ONLINE       0   0   0
                  c2t1d0ONLINE       0   0   0
                  c2t2d0ONLINE       0   0   0
                  c2t4d0ONLINE       0   0   0
      errors: No known data errors
      # zfs list
      NAME   USEDAVAILREFERMOUNTPOINT
      mypool   102K33.1G32.6K/mypool
      # zpool destroy mypool
      add/remove是对整个池的大小的修改,但如果我想将一个简单的stripe文件系统变成一个带冗余的mirror,该怎么办?或者想将一个3路mirror变成2路的又该如何?add/remove是没法做到这一点的。这就是我们下一次要探讨的zpool attach/detach。
ZFS文件系统 - (3) zpool attach/detach
      将一个非冗余的文件系统改造成为带冗余的mirror文件系统有很多好处。它可以让数据更安全,容灾性更强。单一物理设备的损坏不至于影响系统数据的完整一致性。当然,在保证数据完整性的前提下,为了尽可能的节约资源,我们也会将一个减少多路的mirror的冗余数目。这些操作就是由zpool attach/detach来完成的。
      zpool attach [-f] pool device new_device
      zpool detach pool device
    注:attach一个新的设备给一个pool设备,这个pool设备不能是raidz池的一部分。
1. 建立一个非冗余简单池,attach一个设备变为两路mirror

      # zpool create mypool c2t5d0
      # zpool status -v mypool
          pool: mypool
         state: ONLINE
         scrub: none requested
      config:
                NAME      STATE   READ WRITE CKSUM
                mypool      ONLINE       0   0   0
                  c2t5d0    ONLINE       0   0   0
      errors: No known data errors
      # zpool attach mypool c2t5d0 c2t4d0
      # zpool status -v mypool
          pool: mypool
         state: ONLINE
         scrub: resilver completed with 0 errors on Thu Dec 21 01:44:03 2006
      config:
                NAME      STATE   READ WRITE CKSUM
                mypool      ONLINE       0   0   0
                  mirror    ONLINE       0   0   0
                  c2t5d0ONLINE       0   0   0
                  c2t4d0ONLINE       0   0   0
      errors: No known data errors
      # zpool list
      NAME                  SIZE    USED   AVAIL    CAPHEALTH   ALTROOT
      mypool               16.8G    128K   16.7G   0%ONLINE   -
2. 将一个3路mirror降为2路
      # zpool create mypool mirror c2t5d0 c2t4d0 c2t2d0
      # zpool status -v mypool
          pool: mypool
         state: ONLINE
         scrub: none requested
      config:
                NAME      STATE   READ WRITE CKSUM
                mypool      ONLINE       0   0   0
                  mirror    ONLINE       0   0   0
                  c2t5d0ONLINE       0   0   0
                  c2t4d0ONLINE       0   0   0
                  c2t2d0ONLINE       0   0   0
      errors: No known data errors
      # zpool detach mypool c2t4d0
      # zpool status -v mypool
          pool: mypool
         state: ONLINE
         scrub: none requested
      config:
                NAME      STATE   READ WRITE CKSUM
                mypool      ONLINE       0   0   0
                  mirror    ONLINE       0   0   0
                  c2t5d0ONLINE       0   0   0
                  c2t2d0ONLINE       0   0   0
      errors: No known data errors
      # zpool list
      NAME                  SIZE    USED   AVAIL    CAPHEALTH   ALTROOT
      mypool               16.8G    128K   16.7G   0%ONLINE   -
3.raidz池不可以进行attach/detach
         # zpool create myraidz raidz c2t5d0 c2t4d0 c2t2d0
      # zpool attach myraidz c2t5d0 c1t4d0
      cannot attach c1t4d0 to c2t5d0: can only attach to mirrors and top-level disks
      # zpool detach myraidz c2t5d0
      cannot detach c2t5d0: only applicable to mirror and replacing vdevs
    attach不能操作raidz设备文件,detach只能对可替换的mirror设备进行操作。
ZFS文件系统 - (4) zpool inport/export
      周一公司放一天假,Merry Christmas!周二一来事情比较杂乱,早上开部门会,匆匆吃过午饭,回来积累的邮件还没有回完,又急急忙忙的去BJS07为年会排演小品。周四,节目筹备委员会对节目进行检查。还有一个组,他们演《武林外传》中的一个片段,他们演的还真不错。对整个剧情把握的还挺到位,而且每一个人的台词都很熟悉。我们的小品是原创的,又都是一群没有演艺任何经验的人,也没有可以比照的表演,所以难免有很多不完善之处。不过,我们的优势也是明显的,我们的小品对大家更具神秘感,未知性和可发挥性更强。还有一个月可以用来排练,相信大家会演的越来越好的。让我们大家一起加油吧!
      罗罗嗦嗦半天,说点正题吧。前面讲了ZFS文件系统的池的建立,池的扩展,hot spare设备的增加和删减。现在我们说说池的import和export。首先说说,为什么要有池的import和export?例如,当我们要升级系统的时候,老的系统已经无法再扩展,内存条槽没有了,CPU也没办法在提速了。那么只好换一套新的硬件,但是我们有着庞大的数据存在硬盘上,如果把这些数据全部转移到新的机器上那时间是不容许的,怎么办呢?又如果我们一个不小心的操作将池删掉了,怎么办?所有的在其上的文件系统都已经不可见了,那么能否将数据重新找回来呢?
      对了,zpool import/export就可以解决以上所有问题。
         zpool export [-f] pool
         zpool import [-d dir] [-D]
         zpool import [-d dir] [-D] [-f] [-o opts] [-R root]pool|id
         zpool import [-d dir] [-D] [-f] [-a]
      没有参数的zpool import将列出当前机器上可以import的所有池,加参数-D将列出所有已经被destroy但是可以找回来的。/dev/dsk目录是import命令的默认操作目录,ZFS会自动搜寻并检测/dev/dsk目录下的所有设备。当然,因为ZFS可以建立在文件之上(这是不被推荐的),也可以建立在volume之上,所以还可以指定要检测的文件夹。这就是-d目录。
      还有一点就是,ZFS文件系统可以在x86平台和sparc平台上平滑迁移。什么意思呢,就是说我们把一个x86系统上的池export出来,然后在sparc系统上在import进来,所有数据文件不需要做任何额外操作立马可用。反之亦然。让我们看几个关于zpool import/export的例子。
例如,将一个文件系统export出去,再import进来,以/zfsroot为目录前缀。
      # zfs list
      NAME            USEDAVAILREFERMOUNTPOINT
      mypool         1.00G65.9G25.5K/mypool
      mypool/fs      24.5K65.9G24.5K/mypool/fs
      mypool/fs@snap       0      -24.5K-
      mypool/vol       22.5K66.9G22.5K-
      mypool/vol@snap      0      -22.5K-
      # zpool export mypool
      # zfs list
      no datasets available
      # zpool import
          pool: mypool
            id: 17890752848509439119
         state: ONLINE
      action: The pool can be imported using its name or numeric identifier.
      config:
                mypool      ONLINE
                  c1t3d0    ONLINE
zpool import显示了当前系统有一个可以import进来的池。
      # zfs list
      no datasets available
      # zpool import -R /zfsroot mypool
      # zfs list
      NAME            USEDAVAILREFERMOUNTPOINT
      mypool         1.00G65.9G25.5K/zfsroot/mypool
      mypool/fs      24.5K65.9G24.5K/zfsroot/mypool/fs
      mypool/fs@snap       0      -24.5K-
      mypool/vol       22.5K66.9G22.5K-
      mypool/vol@snap      0      -22.5K-
      如果要import的池的名字当前系统已经有了,该怎么办?再如果有两个相同名字的池存在,zpool import怎么import进来呢?这就是我们上面看到的参数id和newpool,id是池唯一性的标识符。还有,就是ZFS还可以import进来已经被destroy掉的pool。我们可以看看下面的例子:
      # zpool create pool1 c1t3d0
      # zfs create pool1/fs1
      # zfs create pool1/fs2
      # zfs list
      NAME      USEDAVAILREFERMOUNTPOINT
      pool1       146K33.5G27.5K/pool1
      pool1/fs124.5K33.5G24.5K/pool1/fs1
      pool1/fs224.5K33.5G24.5K/pool1/fs2
      # zpool destroy pool1
      # zpool import
      no pools available to import
zpool import只能看到export出去的池,而pool1是的destroy掉的,所以只有加参数-D才可以显示。
      # zpool import -D
          pool: pool1
            id: 17168252477589329464
         state: ONLINE (DESTROYED)
      action: The pool can be imported using its name or numeric identifier.
                The pool was destroyed, but can be imported using the '-Df' flags.
      config:
                pool1       ONLINE
                  c1t3d0    ONLINE
      # zpool create pool1 c1t4d0
      # zfs list
      NAME    USEDAVAILREFERMOUNTPOINT
      pool1    85K33.5G24.5K/pool1
      # zpool import -Df pool1 pool2
pool1虽然被删除掉了,但是如果在c1t3d0没有建立过新的池,关于已有pool1的所有数据其实还完整的保存与硬盘之上,所以再通过参数-D还是可以在找回来,并且所有数据都完整。由于又有一个pool1存在于当前系统中,所以再import进第一个pool1时只有改名,否则该操作失败。
      # zfs list
      NAME      USEDAVAILREFERMOUNTPOINT
      pool1      85K33.5G24.5K/pool1
      pool2       146K33.5G27.5K/pool2
      pool2/fs124.5K33.5G24.5K/pool2/fs1
      pool2/fs224.5K33.5G24.5K/pool2/fs2
用ZFS rollback还原根系统
ZFS作为根文件系统被集成到solaris中是从b90开始的。到底有什么好处呢?这有个例子。
因为要做ZFS crypto测试,于是以ZFS为根装好系统后,准备bfu到一个ZFS crypto版本。考虑到可能的潜在系统危险,先给整个系统打一个snapshot。
# zfs snapshot -r rootpool@freshinstall
然后bfu,reboot。果然让我碰上了,系统开始不停地在启动阶段panic。看来得试一试用zfs rollback功能恢复,重启后在grub中选择failsafe模式进入。
# zpool import
pool: rootpool
    id: 3421507135120447382
state: ONLINE
status: The pool was last accessed by another system.
action: The pool can be imported using its name or numeric identifier and
      the '-f' flag.
   see: http://www.sun.com/msg/ZFS-8000-EY
config:
      rootpool    ONLINE
          c1t2d0s0ONLINE

显然,ZFS pool是在的,就是有问题导致无法加载和启动。
重新导入rootpool
# mount -o rw,remount /
# zpool import -f rootpool
libshare SMF initialization problem: entity not found
# zfs list
NAME                                     USEDAVAILREFERMOUNTPOINT
rootpool                              9.18G24.3G    36K/rootpool
rootpool@freshinstall                   21.5K      -    36K-
rootpool/ROOT                           5.61G24.3G    18Klegacy
rootpool/ROOT@freshinstall                  0      -    18K-
rootpool/ROOT/zfsroot                   5.61G24.3G4.88G/
rootpool/ROOT/zfsroot@freshinstall       619M      -5.04G-
rootpool/ROOT/zfsroot/var                135M24.3G   133M/var
rootpool/ROOT/zfsroot/var@freshinstall2.33M      -   132M-
rootpool/dump                           1.78G24.3G1.78G-
rootpool/dump@freshinstall                16K      -1.78G-
rootpool/export                           52K24.3G    19K/export
rootpool/export@freshinstall            15K      -    19K-
rootpool/export/home                      18K24.3G    18K/export/home
rootpool/export/home@freshinstall         0      -    18K-
rootpool/swap                           1.78G26.1G    16K-
rootpool/swap@freshinstall                  0      -    16K-
回退到@freshinstall


# zfs rollback -r rootpool@freshinstall
# zfs rollback -r rootpool/ROOT@freshinstall
# zfs rollback -r rootpool/ROOT/zfsroot@freshinstall
# zfs rollback -r rootpool/ROOT/zfsroot/var@freshinstall
# reboot
系统重新启动后,可以正常启动。
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/21041/showart_1882098.html
页: [1]
查看完整版本: ZFS文件系统的学习(二)