Показ дописів із міткою ZFS. Показати всі дописи
Показ дописів із міткою ZFS. Показати всі дописи

вівторок, 12 жовтня 2010 р.

Advanced disk format on FreeBSD

Вот такой вот свой маленький велосипедик получился:
# cat /etc/rc.d/gnop 
#!/bin/sh
#

# PROVIDE: gnop
# REQUIRE: mountcritlocal
# BEFORE:  zfs
# KEYWORD: nojail

. /etc/rc.subr

name="gnop"
rcvar=`set_rcvar`
start_cmd="do_gnop"
stop_cmd=":"

do_gnop()
{
        for d in $gnop_disks
        do
                if [ -e /dev/$d.nop ]
                then
                        echo "gnop: device $d already configured"
                else
                        echo -n "gnop: configuring device $d ..."
                        gnop create -v $gnop_flags $d
                fi
        done
}

load_rc_config $name
run_rc_command "$1"
# fgrep gnop /etc/rc.conf
gnop_enable="YES"
gnop_disks="ada0 ada1 ada2 ada3"
gnop_flags="-S 4096"

вівторок, 21 вересня 2010 р.

Вот тут будет домашняя файлосвалка

# zpool list
NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
zstore  7.25T   776K  7.25T     0%  ONLINE  -
zusb    3.59G  2.41G  1.19G    66%  ONLINE  -
# zpool status zstore
  pool: zstore
 state: ONLINE
 scrub: none requested
config:

        NAME           STATE     READ WRITE CKSUM
        zstore         ONLINE       0     0     0
          raidz1       ONLINE       0     0     0
            gpt/disk1  ONLINE       0     0     0
            gpt/disk2  ONLINE       0     0     0
            gpt/disk3  ONLINE       0     0     0
            gpt/disk4  ONLINE       0     0     0

errors: No known data errors
# sudo camcontrol devlist
<WDC WD20EARS-00MVWB0 51.0AB51>    at scbus0 target 0 lun 0 (ada2,pass2)
<WDC WD20EARS-00MVWB0 51.0AB51>    at scbus1 target 0 lun 0 (ada0,pass0)
<WDC WD20EARS-00MVWB0 51.0AB51>    at scbus2 target 0 lun 0 (ada1,pass1)
<WDC WD20EARS-00MVWB0 51.0AB51>    at scbus3 target 0 lun 0 (ada3,pass6)
< USB DISK 2.0 PMAP>               at scbus4 target 0 lun 0 (pass3,da0,sg0)
<Generic- SD/MMC 1.00>             at scbus5 target 0 lun 0 (pass4,da1,sg1)
<Generic- MS/MS-Pro 1.00>          at scbus5 target 0 lun 1 (pass5,da2,sg2)

вівторок, 17 серпня 2010 р.

htpc & nas & router: OS

Ввиду моих личный предпочтений на железку была установлена FreeBSD, причем на usb flash, причем current, причем amd64, причем на gpt & zfs :)
На самом деле понятно что в current необходимости нет. Я его выбрал из соображений потенциального полигона для покрутить/потестировать и из соображений что в current уже ZFSv15.
В amd64 тоже необходимости нет: не смотря на то, что в материнку можно установить до 4GB оперативной памяти, видеться системой будет только чуть больше трех:
hw.physmem: 3460689920
Я выбрал amd64 из соображений чтобы на ноуте и медиабоксе была одна архитектура - потенциально это позволит в будущем использовать firewire для дебага.
На материнской плате есть только 4 sata разъема, поэтому отдельный системный диск не поставишь. А ставить систему на диски с данными не хотелось. Поэтому было решено использовать usb flash (уж usb портов полно, с большим запасом).
На дисках с данными планируется использовать zfs (в режиме raidz). Это один из пунктов, почему на системной флешке тоже используется zfs: ввиду того, что zfs в данный момент достаточно плохо интегрирован в систему распределения памяти freebsd, не рекомендуется использовать на одном компьютере и zfs, и ufs одновременно. Кроме того использование zfs на системной флешке избавляет от fsck в случае чего, позволяет использовать вкусности типа снэпшотов, сжатия, возможности легко переехать на флешку большего объема.
Установка на zfs ничем особенным от wiki не отличается. Разве что я ставил не с инсталяционного диска, а вставил флешку в ноут, всё разметил и потом сделал
make installkernel installworld distribution DESTDIR=/zusb
Сейчас используется флешка на 4GB. Пока запас еще есть:
# zpool list
NAME   SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
zusb  3.59G  2.17G  1.43G    60%  ONLINE  -
# zfs list -oname,mountpoint,used,compressratio   
NAME                      MOUNTPOINT             USED  RATIO
zusb                      legacy                2.17G  1.34x
zusb/jail                 /jail                  422M  1.03x
zusb/jail/int             /jail/int              422M  1.03x
zusb/jail/int/tmp         /jail/int/tmp           30K  1.00x
zusb/jail/int/usr         /jail/int/usr          349M  1.00x
zusb/jail/int/var         /jail/int/var         52.7M  1.31x
zusb/jail/int/var/db      /jail/int/var/db      52.0M  1.29x
zusb/jail/int/var/db/pkg  /jail/int/var/db/pkg  26.6M  1.57x
zusb/jail/int/var/empty   /jail/int/var/empty     21K  1.00x
zusb/jail/int/var/log     /jail/int/var/log      446K  3.74x
zusb/jail/int/var/mail    /jail/int/var/mail      21K  1.00x
zusb/jail/int/var/run     /jail/int/var/run       31K  1.00x
zusb/jail/int/var/tmp     /jail/int/var/tmp       23K  1.00x
zusb/tmp                  /tmp                   243K  1.00x
zusb/usr                  /usr                  1.46G  1.49x
zusb/usr/home             /usr/home              353K  1.87x
zusb/usr/local            /usr/local             576M  1.04x
zusb/usr/ports            /usr/ports             415M  1.45x
zusb/usr/ports/distfiles  /usr/ports/distfiles   121M  1.00x
zusb/usr/ports/packages   /usr/ports/packages   61.8M  1.00x
zusb/usr/src              /usr/src               234M  3.24x
zusb/var                  /var                  39.3M  1.73x
zusb/var/db               /var/db               35.0M  1.36x
zusb/var/db/pkg           /var/db/pkg           6.95M  2.94x
zusb/var/empty            /var/empty              21K  1.00x
zusb/var/log              /var/log              2.96M  6.57x
zusb/var/mail             /var/mail               59K  1.00x
zusb/var/run              /var/run               587K  1.00x
zusb/var/tmp              /var/tmp               138K  1.00x
Как видно compression тоже дает какой-то эфект.
Светящийся тут jail это неудачная попытка запустить иксы в jail: изначально была идея что так как компьютер планируется использовать одновременно и для внутренних нужд (htpc), и для внешних (router и torrent клиент), то завести два отдельных jail-а: внутренний и внешний, и тем самым обеспечить невозможность засветить внутренние сервиса на внешний ip и ограничить что именно светить наружу. Но в таком виде идея провалилась, поэтому будет реализована в немного видоизмененной.
Это установленная базовая система фактически без оптимизации (только удалены /boot/kernel/*.symbols), Xorg, mplayer, nvidia-driver, openbox и всё, чего оно захотело:
# pkg_info|wc -l
     216
Оборудование в среднем распознается без проблем:
# pciconf -lv
...
ohci0@pci0:0:4:0:       class=0x0c0310 card=0x83e21043 chip=0x0aa510de rev=0xb1 hdr=0x00
    vendor     = 'NVIDIA Corporation'
    class      = serial bus
    subclass   = USB
ehci0@pci0:0:4:1:       class=0x0c0320 card=0x83e21043 chip=0x0aa610de rev=0xb1 hdr=0x00
    vendor     = 'NVIDIA Corporation'
    class      = serial bus
    subclass   = USB
ohci1@pci0:0:6:0:       class=0x0c0310 card=0x83e21043 chip=0x0aa710de rev=0xb1 hdr=0x00
    vendor     = 'NVIDIA Corporation'
    class      = serial bus
    subclass   = USB
ehci1@pci0:0:6:1:       class=0x0c0320 card=0x83e21043 chip=0x0aa910de rev=0xb1 hdr=0x00
    vendor     = 'NVIDIA Corporation'
    class      = serial bus
    subclass   = USB
hdac0@pci0:0:8:0:       class=0x040300 card=0x84271043 chip=0x0ac010de rev=0xb1 hdr=0x00
    vendor     = 'NVIDIA Corporation'
    class      = multimedia
    subclass   = HDA
ahci0@pci0:0:11:0:      class=0x010601 card=0x83e21043 chip=0x0ab810de rev=0xb1 hdr=0x00
    vendor     = 'NVIDIA Corporation'
    device     = 'MCP79 AHCI1 (MCP79)'
    class      = mass storage
    subclass   = SATA
vgapci0@pci0:3:0:0:     class=0x030000 card=0x83e21043 chip=0x087d10de rev=0xb1 hdr=0x00
    vendor     = 'NVIDIA Corporation'
    class      = display
    subclass   = VGA
re0@pci0:4:0:0: class=0x020000 card=0x83a31043 chip=0x816810ec rev=0x03 hdr=0x00
    vendor     = 'Realtek Semiconductor'
    device     = 'Gigabit Ethernet NIC(NDIS 6.0) (RTL8168/8111/8111c)'
    class      = network
    subclass   = ethernet
...
# cat /dev/sndstat 
FreeBSD Audio Driver (newpcm: 64bit 2009061500/amd64)
Installed devices:
pcm0: <hda Realtek ALC887 PCM #0 Analog> (play/rec)
pcm1: <hda Realtek ALC887 PCM #1 Analog> (play/rec)
pcm2: <hda Realtek ALC887 PCM #2 Digital> (play) default
pcm3: <hda NVidia MCP7A HDMI PCM #0 Digital> (play)
Процессор тоже вполне настоящий:
CPU: Intel(R) Atom(TM) CPU  330   @ 1.60GHz (1600.03-MHz K8-class CPU)
  Origin = "GenuineIntel"  Id = 0x106c2  Family = 6  Model = 1c  Stepping = 2
  Features=0xbfe9fbff
  Features2=0x40e31d
  AMD Features=0x20100800
  AMD Features2=0x1
  TSC: P-state invariant
real memory  = 4294967296 (4096 MB)
Physical memory chunk(s):
0x0000000000001000 - 0x0000000000047fff, 290816 bytes (71 pages)
0x0000000000058000 - 0x000000000009afff, 274432 bytes (67 pages)
0x0000000001bbb000 - 0x00000000c9d91fff, 3357372416 bytes (819671 pages)
avail memory = 3338301440 (3183 MB)
Event timer "LAPIC" frequency 0 Hz quality 500
ACPI APIC Table: <020110 APIC1033>
INTR: Adding local APIC 2 as a target
FreeBSD/SMP: Multiprocessor System Detected: 4 CPUs
FreeBSD/SMP: 1 package(s) x 2 core(s) x 2 HTT threads
 cpu0 (BSP): APIC ID:  0
 cpu1 (AP/HT): APIC ID:  1
 cpu2 (AP): APIC ID:  2
 cpu3 (AP/HT): APIC ID:  3
APIC: CPU 0 has ACPI ID 1
APIC: CPU 1 has ACPI ID 3
APIC: CPU 2 has ACPI ID 2
APIC: CPU 3 has ACPI ID 4
Есть кое-какая поддержка power management фичей:
# sysctl dev.cpu.0
dev.cpu.0.%desc: ACPI CPU
dev.cpu.0.%driver: cpu
dev.cpu.0.%location: handle=\_PR_.P001
dev.cpu.0.%pnpinfo: _HID=none _UID=0
dev.cpu.0.%parent: acpi0
dev.cpu.0.temperature: 56.0C
dev.cpu.0.freq: 1600
dev.cpu.0.freq_levels: 1600/-1 1400/-1 1200/-1 1000/-1 800/-1 600/-1 400/-1 200/-1
dev.cpu.0.cx_supported: C1/0 C2/1 C3/85
dev.cpu.0.cx_lowest: C1
dev.cpu.0.cx_usage: 100.00% 0.00% 0.00% last 279us
Процессор поддерживает C3, но включение его вызывает очень сильное падение производительности (дождаться даже установки пекеджа становится проблематично). Всё уменьшение частоты исключительно через acpi throttle. Поэтому, а так же потому, что за всё время наблюдений я не видел чтобы температура процессора доходила хотя бы до 65C, я не включал никаких power management функций.
Видеокарта нормально распозналась X -configure:
Section "Device"
        Identifier  "Card0"
        Driver      "nvidia"
        VendorName  "nVidia Corporation"
        BoardName   "G98 [GeForce 9300M GS]"
EndSection
На подключенный по hdmi телевизор тоже картинка сходу пошла, только не захотел сам выставить максимальное разрешение. Но кручение через nvidia-settings с последующим переносом настроек в xorg.conf всё полечило.
Да, на current драйвер nvidia надо ставить последний с сайта nvidia (у меня это 256.44), а не то, что сейчас в портах. Для быстрой и удобной установки можно просто немного поправить порт: поменять в нём DISTVERSION , после чего make makesum && make install clean .
Звук по hdmi передаваться не захотел. Кто виноват: видеокарта или драйер, я не знаю и пока не разбирался, а просто подключил акустику по оптическому кабелю в spdif. Но вообще звук по hdmi с nvidia под freebsd передается: я сам это проверял на своём ноуте как только вышли драйвера nvidia под freebsd amd64.
Как обычно все аудиовыходы (задние штекеры, фронтальные, spdif, звук на hdma) представлены в виде разных pcm устройств (я выше показывал). Несколько раз видел что людей такое смущает: они удивляются откуда на их компьютере (а особенно если это ноутбук) две звуковых карта, да еще и разных производителей. А вообще благодаря этому можно выбирать куда выводить звук или явно указывая программые нужный /dev/pcm , или выставив для всех hw.snd.default_unit .
Ну и, собственно, самое главное на данный момент: проигрывание hd видео. Для этого нужно собрать mplayer с поддержкой vdpau , прописать ему вот такой конфиг:
# cat .mplayer/config 
vo=vdpau
vc=ffh264vdpau,ffmpeg12vdpau,
ac=hwac3,a52,
и спокойно смотреть видео на прохлаждающемся процессоре:
PID USERNAME    THR PRI NICE   SIZE    RES STATE   C   TIME   WCPU COMMAND
73587 levsha        1  49    0   215M 40660K nanslp  2   0:15  8.98% mplayer
Теперь о планах. Планируется прикрутить IR, перенести аудиоплеер на медиабокс, сделав на ноутбуке управление им хоткеями, поднять torrent client (посматриваю на transmission), спортироать xbmc, возможно поиграться с DLNA.

неділя, 16 травня 2010 р.

zfs only system & geom_eli

Непосредственно с geom_eli грузиться нельзя: ни loader, ни никакой из boot-ов его не умеют и загрузить ядро оттуда не смогут. Поэтому делается схема с /boot на отдельном разделе, без geli.
Вообще для этого можно практически дословно вспользоваться инструкцией http://wiki.freebsd.org/RootOnZFS/UFSBoot , но наличие дополнительного ufs раздела мне не нравится: это fsck после unclean shutdown, отсутствие дешевых снапшотов (к хорошему привыкаешь быстро). Поэтому была взята за основу эта статья, http://wiki.freebsd.org/RootOnZFS/GPTZFSBoot и вместе творчески доработаны до получения конфигурации с двумя zfs pool.
# gpart show ada0
=>       34  976773101  ada0  GPT  (466G)
         34         30        - free -  (15K)
         64        128     1  freebsd-boot  (64K)
        192       1856        - free -  (928K)
       2048   16777216     2  freebsd-swap  (8.0G)
   16779264    2097152     3  freebsd-zfs  (1.0G)
   18876416  957896719     4  freebsd-zfs  (457G)
Тут опять напоминаю владельцам дисков WesternDigital о желательности выравнивания начала разделов по 4K границе (gpart сам этого не делает).
swap в принципе может размещаться на zpool, но при этом не будет возможности получить crash dump ядра.
Понятно что на ada0 надо накатить pmbr и gptzfsboot
На 3-й раздел я повесил gpt label zboot для удобства. Использовать метку на 4-м разделе не получится: он должен быть размечен через geli с -b , а при этом ядро как только увидит geli label на ada0p4 , так сразу и запросит для него пароль, не зависимо от наличия gpt label
# geli list
Geom name: ada0p4.eli
EncryptionAlgorithm: AES-CBC
KeyLength: 128
Crypto: software
UsedKey: 0
Flags: BOOT
Providers:
1. Name: ada0p4.eli
   Mediasize: 490443119616 (457G)
   Sectorsize: 512
   Mode: r1w1e1
Consumers:
1. Name: ada0p4
   Mediasize: 490443120128 (457G)
   Sectorsize: 512
   Mode: r1w1e1
Кстати geli label содержит определенные метаданные, без которых получить данные с раздела не возможно. Поэтому не забывайте о необходимости сохранить их с помощью чего-нибудь типа
# geli backup ada0p4 /boot/geli.meta
Ну а дальше можно создавать два пула:
# zpool status
  pool: zboot
 state: ONLINE
 scrub: none requested
config:

        NAME         STATE     READ WRITE CKSUM
        zboot        ONLINE       0     0     0
          gpt/zboot  ONLINE       0     0     0

errors: No known data errors

  pool: zdata
 state: ONLINE
 scrub: none requested
config:

        NAME          STATE     READ WRITE CKSUM
        zdata         ONLINE       0     0     0
          ada0p4.eli  ONLINE       0     0     0

errors: No known data errors
# zpool get bootfs zboot
NAME   PROPERTY  VALUE   SOURCE
zboot  bootfs    zboot   local
# zpool get bootfs zdata
NAME   PROPERTY  VALUE   SOURCE
zdata  bootfs    -       default
# zfs list -o name,mountpoint zboot
NAME   MOUNTPOINT
zboot  /zboot
# zfs list -o name,mountpoint,exec,compression -r zdata
NAME                       MOUNTPOINT            EXEC  COMPRESS
zdata                      legacy                  on       off
zdata/usr                  /usr                    on       off
zdata/usr/home             /usr/home               on       off
zdata/usr/local            /usr/local              on       off
zdata/usr/local/arch       /usr/local/arch         on      lzjb
zdata/usr/local/jails      /usr/local/jails        on       off
zdata/usr/local/tinderbox  /usr/local/tinderbox    on       off
zdata/usr/ports            /usr/ports              on      lzjb
zdata/usr/ports/distfiles  /usr/ports/distfiles   off       off
zdata/usr/ports/packages   /usr/ports/packages    off       off
zdata/usr/src              /usr/src               off      lzjb
zdata/var                  /var                    on       off
zdata/var/crash            /var/crash             off      lzjb
zdata/var/db               /var/db                off       off
zdata/var/db/pkg           /var/db/pkg             on      lzjb
zdata/var/empty            /var/empty             off       off
zdata/var/log              /var/log               off      lzjb
zdata/var/mail             /var/mail              off      gzip
zdata/var/run              /var/run               off       off
zdata/var/tmp              /var/tmp                on      lzjb
# ls -l /boot
lrwxr-xr-x  1 root  wheel  11 12 кві 18:30 /boot -> /zboot/boot
# fgrep zfs /boot/loader.conf
zfs_load="YES"
vfs.root.mountfrom="zfs:zdata"
vfs.zfs.debug=1
#
# cat /etc/fstab
# Device   Mountpoint      FStype  Options         Dump    Pass#
/dev/gpt/swap   none            swap    sw      0       0       0
tmpfs   /tmp    tmpfs   rw,size=3221225472      0       0
proc    /proc   procfs  rw      0       0
fdescfs /dev/fd fdescfs rw 0 0
linproc /usr/compat/linux/proc  linprocfs       rw,late 0       0
/dev/cd0                /cdrom          cd9660  ro,noauto,-CKOI8-U      0       0
Вот так оно и живет на моем ноутбуке. Уже больше месяца как.

середа, 12 травня 2010 р.

zpool on whoole disk or not?

zfs в своих метках, которые он сохраняет на все диски, входящие в zpool, зачем-то сохраняет имена vdev-ов, из которых он состоит. Зачем он там делает не понятно, ввиду того, что все-равно сохраняются и всегда проверяются еще и GUID-ы дисков. Наверное так делается для усложнения жизни.
На solaris оно вроде как не должно быть ничем страшно ввиду того, что там диски обзываются согласно их расположению. А вот на FreeBSD это чревато проблема в случае, когда съедет нумераци дисков (а она обязательно съедет после ребута с отвалившимся диском)
Оно то вроде и не особо страшно: zfs export && zfs improt и всё снова работает. Но все-равно дополнительные действия (а как поступать в случае zfs only system я вообще не представляю). Поэтому лучше таки так не делать.
Из обдуманых и нарытых в инете советов я дла себя выбрал создание одного большого GPT раздела с gpt меткой: по сравнение с glabel гарантия что не возникнет непоняток из-за вдруг обнаруженных в начале диска zfs меток, и вроде как более переносимо (теоретически, а говорят даже практически существует возможность импортировать в solaris pool, экспортированный из FreeBSD).
Кстати при разметке WD дисков сразу рекомендую не забывать про 4K сектора: gpart для GPT по умолчанию предлагает начинать раздел с 34-го 512B сектора, чего явно делать не стоит.

середа, 5 травня 2010 р.

Пляски с ZFS

Из цитат на #freebsd@RusNet:
zfs = оно то вроде работает, но если/когда она развалится, то что с ней делать не понятно вообще (c) levsha.
fsck не нужен, потому что не поможет (c) kib
"Вот наконец настал тот час", и zfs у меня поломался.
На сервере отвалился один диск (не из того пула, который потом сломался, а из другого). Но это отваливание как-то серьезно переклинило контроллер (да, adaptec говно), и посыпалась куча таймаутов от контроллера.
Полностью выключил сервер, подождал некоторое время и включил. В результате после загрузки получил панику. Попробовал удалить /boot/zfs/zpool.cache . В результате пулы перестали автоматически подключаться (совершенно справедливо) и стали видны по zpool import. При этом нужный пул стал помечен UNAVAILABLE, хотя он состял из одного raidz из 6 дисков, причем и raidz и все 6 дисков отображались как ONLINE.
Для ковыряний попробовал использовать zdb. Он при попытке запуска на пул падал по segmentation fault. Это оказалось плюсом: zdb использует тот же код, что и zfs.ko, но на user level, что, впервых, дает core dump вместо panic, во вторых позовляет использовать обычный gdb.
Ковыряния кода с помощью gdb показали, что где-то в душе вызывается zio_vdev_io_start() с zio->io_vd == NULL . Где и почему это происходит я не нашел. При этом zio_vdev_io_start считает что может справиться с такой ситуацией:
if (vd == NULL) {
if (!(zio->io_flags & ZIO_FLAG_CONFIG_WRITER))
spa_config_enter(spa, SCL_ZIO, zio, RW_READER);

/*
* The mirror_ops handle multiple DVAs in a single BP.
*/
return (vdev_mirror_ops.vdev_op_io_start(zio));
}
Вот только vdev_op_io_start совершенно не приспособлен до такой ситуаци: он в конце концов вызывает вот такую функцию:
boolean_t
vdev_is_dead(vdev_t *vd)
{
return (vd->vdev_state < VDEV_STATE_DEGRADED); }





за что сразу получает по голове (или sigsgev в случае zdb, или panic в случае zfs.ko).
Простенький патч вида
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c (revision 207555)
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c (working copy)
@@ -1845,6 +1845,10 @@
boolean_t
vdev_is_dead(vdev_t *vd)
{
+ if( vd == NULL ){
+ printf("XXX: Attemt to call vdev_is_dead for NULL vd\n");
+ return 1;
+ }
return (vd->vdev_state < VDEV_STATE_DEGRADED); }





панику исправил, вот только к работоспособности это не привело: теперь операции, которые проходили по этому коду, просто бесконечно долго ждали завершения io.
Дальнейшие ковыряния в направлении "а почему же этот пул помечается как UNAVALIABLE и что с этим можно сделать?" дали результатом такое: UNAVAILABLE пул считается тогда, когда zfs решил что некоторые устройства из пула недоступны, но не может определить какие именно. Для того, чтобы было возможно определить такую ситуацию, zfs записывает в каждый uberblock (The uberblock is similar to the superblock in UFS (c) ZFS On-Disk Specification) контрольную сумму идентификаторов всех устройств, входящих в пул. Поизучавши http://hub.opensolaris.org/bin/download/Community+Group+zfs/docs/ondiskformat0822.pdf была накалякана вот такая приблуда:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>

#define UBERBLOCK_MAGIC 0x00bab10c /* oo-ba-bloc! */
#define UBERBLOCK_SHIFT 10 /* up to 1K */

typedef struct dva {
uint64_t dva_word[2];
} dva_t;

typedef struct zio_cksum {
uint64_t zc_word[4];
} zio_cksum_t;

typedef struct blkptr {
dva_t blk_dva[3]; /* 128-bit Data Virtual Address */
uint64_t blk_prop; /* size, compression, type, etc */
uint64_t blk_pad[3]; /* Extra space for the future */
uint64_t blk_birth; /* transaction group at birth */
uint64_t blk_fill; /* fill count */
zio_cksum_t blk_cksum; /* 256-bit checksum */
} blkptr_t;

typedef struct uberblock {
uint64_t ub_magic; /* UBERBLOCK_MAGIC */
uint64_t ub_version; /* SPA_VERSION */
uint64_t ub_txg; /* txg of last sync */
uint64_t ub_guid_sum; /* sum of all vdev guids */
uint64_t ub_timestamp; /* UTC time of last sync */
blkptr_t ub_rootbp; /* MOS objset_phys_t */
} uberblock_t;

int main(int argc, char* argv[]){

uberblock_t* ub = malloc(sizeof ub);
int res;

while( (res = read(0, ub, sizeof *ub) ) > 0 ){
if( ub->ub_magic != 0x00bab10c )
continue;
printf("ub_magic=%jx, ub_version=%ju, ub_txg=%ju, ub_guid_sum=%ju, ub_timestamp=%ju\n",
ub->ub_magic, ub->ub_version, ub->ub_txg, ub->ub_guid_sum, ub->ub_timestamp);

}
if( res < 0 ){ fprintf(stderr, "read(): %d\n", errno); } free(ub); return 0; }





На stdin пограммы были скормлены dd if=(тут перебираем все диски) bs=128k count=1 skip=(тут перебираем 1,3, последний и предпоследний блок на диске) . С блоками так потому, что zfs записывает на каждый диск 4 vdev label: две в начале и две в конце, и каждая vdev label заниает 256KBytes, из которых вторая половина это uberblocks array.
В моём случае было обнаружено что на нулевом диске несколько последних uberblock-ов содержат другую ub_guid_sum. Поэтому этот диск был просто вытянут, после чего zfs спокойно распознала этот пул.
Вот такое вот шаманство этот zfs...