BTRFS replace - zapisuje něco na původní disk?

BTRFS replace - zapisuje něco na původní disk?
« kdy: 08. 11. 2024, 10:59:20 »
Dobrý den.

Měl jsem btrfs raid1 na dvou discích, fungoval bez problémů. Teď, zpětně viděno, jen z hloupého rozmaru jsem si usmyslel vyměnit v něm disky za větší. Připojil jsem dva nové větší disky (pro informaci - poněkud pochybného původu) a udělal postupně btrfs replace obou stávajících disků na nové. Proběhlo v pořádku, žádné chyby. Následně jsem tedy ještě udělal už na těch nových discích btrfs filesystem resize abych využil to nové místo.
Celou dobu jsem si (naivně) myslel, že je to celkem bezpečná operace, protože mi pořád zůstávají v záloze ty původní dva disky, v případě problémů se k nim mohu vrátit a ztratím max. ty změny od začátku replace. V zápětí se ukázalo že ty nové disky (SSD) jsou opravdu pochybné, po pár hodinách používání prostě začaly "zapomínat" data na nich mizela a v btrfs device stats začaly přibývat corruption_errs.
Myslel jsem si, že možná bude stačit jen odpojit ty nové disky a restartovat, případně manuálně mountnout ty původní disky. Ale nic z toho se nedaří. Při restartu systém ty původní disky nenajde a pokus o ruční mount hlásí wrong fs type, bad option, bad superblock
On btrfs replace příkaz něco zapisuje na ty původní, zdrojové disky? Nebo je dokonce nějak přepisuje/nuluje? Existuje vůbec nějaká cesta zpět?
Díky


Zopper

  • *****
  • 786
    • Zobrazit profil
Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #1 kdy: 08. 11. 2024, 11:19:35 »
Jako úplně první krok teď doporučuji zaběhnout do důvěryhodného obchodu, koupit tam dostatečnou diskovou kapacitu a udělat bitovou kopii původních disků, než si do nich hrábneš ještě víc. A dál se hrabat v té kopii, nezkoušet rozchodit původní fyzické disky.

Z manuálu k btrfs replace:
After completion of the operation, the source device is removed from the filesystem.

Tady to vypadá na trochu víc informací (přepíše se superblok) i s možností obnovy zápisem magických hodnot na konkrétní místo na disku.

Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #2 kdy: 08. 11. 2024, 11:42:42 »
dd z původních disků jinam bylo první co jsem udělal. Ten popis obnovy z odkazu vypadá hodně magicky. Zkusím nejdřív nastudovat a pochopit co vlastně dělá a odkud bere ta záhadná čísla.
Ale díky za odkaz, Google jsem samozřejmě zkoušel, asi jsem se ptal špatně.

Zopper

  • *****
  • 786
    • Zobrazit profil
Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #3 kdy: 08. 11. 2024, 12:12:46 »
Ve zkratce, na tom disku na přesně dané lokaci je informace "tohle je btrfs disk" (to je ta magická hodnota) a v rámci replace příkazu se tahle informace smaže. Pro obnovu je potřeba ji tam zase vrátit (zapsat na konkrétní adresu toho disku). Komplikované je to tím, že superblok, co tu magickou hodnotu obsahuje, se kvůli odolnosti zapisuje duplikovaně na víc záložních pozic v rámci disku, takže to tam dělá 3x.

Ale je to dva roky stará odpověď, nevím, jestli se něco změnilo v superbloku, a nezkoumal jsem, jestli se ty adresy záložních superbloků posunuly.

Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #4 kdy: 08. 11. 2024, 12:25:05 »
Jasně, když člověk ví co má hledat (_BHRfS_M) hned se ta informace hledá snadněji:
https://archive.kernel.org/oldwiki/btrfs.wiki.kernel.org/index.php/On-disk_Format.html#Superblock

O něco jsem se pohnul, teď už hlásí
[ 6224.497322] BTRFS: device fsid 2db8f54a-3a36-4e3c-8e1f-6ef781966d66 devid 0 transid 0 /dev/loop30 scanned by mount (7926)
[ 6224.497921] BTRFS info (device loop30): first mount of filesystem 2db8f54a-3a36-4e3c-8e1f-6ef781966d66
[ 6224.497939] BTRFS info (device loop30): using crc32c (crc32c-intel) checksum algorithm
[ 6224.497944] BTRFS error (device loop30): superblock checksum mismatch
[ 6224.497956] BTRFS error (device loop30): open_ctree failed


Nadějí mě naplňuje že to 2db8f54a-3a36-4e3c-8e1f-6ef781966d66 je opravdu UUID toho původního disku/raid1.


RDa

  • *****
  • 2 739
    • Zobrazit profil
    • E-mail
Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #5 kdy: 08. 11. 2024, 13:13:50 »
A co jsi to koupil za SSD a kde, ze odchazeji? Minimalne jako varovani pro ostatni, co chteji neco superlevne by to poslouzilo. Neni totiz typicke, ze budou odchazet dva nove disky zaroven. Podle popisu bych tipoval ze jde o fejky :D

Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #6 kdy: 08. 11. 2024, 14:09:33 »
Ano, nejspíš jde o fejky (napsáno je na nich Lenovo). Dostaly se ke mně podivnou cestou, ve které pravděpodobně figuroval nějaký čínský shop (ne že bych je tam kupoval), dostal jsem je jako bonus za nějakou protislužbu. Na nic důležitého bych je nepoužil. I tady jsem si to troufnul jen proto že jsem se (chybně) domníval, že jestli fakt chcípnou, tak se prostě jednoduše a snadno vrátím k původnímu páru.
No - chybama se člověk učí...

Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #7 kdy: 08. 11. 2024, 14:29:49 »
Teď jsem si to zkoušel v rychlosti nasimulovat. Byť bez RAID1 jen s jedním blok. zařízením (partišnou), co jsem pak vyměnil za jinou pomocí replace.

Podle všeho to opravdu odstraní jen magic (těch 8 bajtů), jakmile jsem v hex editoru zapsal zpátky řetězec "_BHRfS_M", co byl u mě na offsetu 0x10040 od začátku partišny (což odpovídá přesně tomu stack overflow), tak mi btrfs inspect-internal dump-super <device> hlásí i správný checksum superbloku. Připojení s -o ro,degraded pak jde a normálně si přečtu data.

Když jsem pak pustil btrfs inspect-internal dump-super -a <device>, tak mi vypsal i dekadický byte offset na začátek druhé kopie superbloku, v hexeditoru jsem poskočil dopředu o dalších 0x40, a opravil to také tam.

Normálně (bez -o degraded) se mi to připojovat nechtělo, ale v dmesg mi to napovědělo, že:
BTRFS warning (device nbd0p1): cannot mount because device replace operation is ongoing..


Tak jsem po připojení v degraded režimu zrušil replace (btrfs replace cancel <mountpoint>) a už se to připojuje standardně.

Snad se to povede i u vás. Tam mě jen trochu zaráží, že vám to pořád píše checksum failed.

Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #8 kdy: 08. 11. 2024, 16:15:50 »
Fakt moc oceňuji tu snahu pomoci. U mě je to nějaké složitější. BTRFS tvrdošíjně hlásí chybu superblock checksum a to na všech kopiích superblocku. Jsem si 100% jistý, že jsem na těch původních discích žádnou operaci nedělal, první operací poté co jsem zjistil že nejdou namountovat bylo dd do souboru na jiném disku a vše ostatní pak probíhalo až tam.
Že ale nějakou záchrannou operaci neudělal proaktivně za mými zády nějaký mountovací démon (Kubuntu), to už si tak úplně jistý nejsem...
Uvidím, celé to vlastně od začátku bylo myšleno jako trénink, rozšíření znalostí o BTRFS, to se tedy naplňuje měrou vrchovatou...

Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #9 kdy: 08. 11. 2024, 17:56:53 »
Jen update - as se někam blížím, jen tedy netuším kam. Zkusil jsem, ze zoufalství začít úplně odznovu, s novou bitovou kopií jednoho z těch původních disků (uloženou jako sda.img). Doběhl dd, pustil jsem na sda.img btrfs inspect-internal dump-super a dostal jsem:
Kód: [Vybrat]
btrfs inspect-internal dump-super --force --all  sda.img
superblock: bytenr=65536, device=sda.img
---------------------------------------------------------
csum_type               0 (crc32c)
csum_size               4
csum                    0x1d92253c [DON'T MATCH]
bytenr                  65536
flags                   0x1
                        ( WRITTEN )
magic                   ........ [DON'T MATCH]
fsid                    2db8f54a-3a36-4e3c-8e1f-6ef781966d66
metadata_uuid           00000000-0000-0000-0000-000000000000
label                   srv
generation              1598019
root                    6673317888
sys_array_size          258
chunk_root_generation   1598019
root_level              1
chunk_root              67139272704
chunk_root_level        0
log_root                0
log_root_transid (deprecated)   0
log_root_level          0
total_bytes             246096592896
bytes_used              53234524160
sectorsize              4096
nodesize                16384
leafsize (deprecated)   16384
stripesize              4096
root_dir                6
num_devices             2
compat_flags            0x0
compat_ro_flags         0x0
incompat_flags          0x161
                        ( MIXED_BACKREF |
                          BIG_METADATA |
                          EXTENDED_IREF |
                          SKINNY_METADATA )
cache_generation        1598019
uuid_tree_generation    1598019
dev_item.uuid           f3793453-4d55-46eb-9388-e9e716178818
dev_item.fsid           2db8f54a-3a36-4e3c-8e1f-6ef781966d66 [match]
dev_item.type           0
dev_item.total_bytes    123048296448
dev_item.bytes_used     60196651008
dev_item.io_align       4096
dev_item.io_width       4096
dev_item.sector_size    4096
dev_item.devid          2
dev_item.dev_group      0
dev_item.seek_speed     0
dev_item.bandwidth      0
dev_item.generation     0

superblock: bytenr=67108864, device=sda.img
---------------------------------------------------------
csum_type               0 (crc32c)
csum_size               4
csum                    0xbdf30df2 [DON'T MATCH]
bytenr                  67108864
flags                   0x1
                        ( WRITTEN )
magic                   ........ [DON'T MATCH]
fsid                    2db8f54a-3a36-4e3c-8e1f-6ef781966d66
metadata_uuid           00000000-0000-0000-0000-000000000000
label                   srv
generation              1598019
root                    6673317888
sys_array_size          258
chunk_root_generation   1598019
root_level              1
chunk_root              67139272704
chunk_root_level        0
log_root                0
log_root_transid (deprecated)   0
log_root_level          0
total_bytes             246096592896
bytes_used              53234524160
sectorsize              4096
nodesize                16384
leafsize (deprecated)   16384
stripesize              4096
root_dir                6
num_devices             2
compat_flags            0x0
compat_ro_flags         0x0
incompat_flags          0x161
                        ( MIXED_BACKREF |
                          BIG_METADATA |
                          EXTENDED_IREF |
                          SKINNY_METADATA )
cache_generation        1598019
uuid_tree_generation    1598019
dev_item.uuid           f3793453-4d55-46eb-9388-e9e716178818
dev_item.fsid           2db8f54a-3a36-4e3c-8e1f-6ef781966d66 [match]
dev_item.type           0
dev_item.total_bytes    123048296448
dev_item.bytes_used     60196651008
dev_item.io_align       4096
dev_item.io_width       4096
dev_item.sector_size    4096
dev_item.devid          2
dev_item.dev_group      0
dev_item.seek_speed     0
dev_item.bandwidth      0
dev_item.generation     0

Jak já to čtu, tak tam našel 2 kopie superblocku (na třetí není místo, je to 128G disk), celkem smysluplně oba naplněné, nesouhasí magic - očekávané a csum - nevím ale to může být tím přepsaným magic. Celkem tedy docela nadějné.
Neudělám nic jiného než že přepíšu to magic v obou superblocích:
Kód: [Vybrat]
echo "_BHRfS_M" | dd bs=1 count=8 of=sda.img  seek=$((64*1024+64))
8+0 záznamů přečteno
8+0 záznamů zapsáno
8 bajtů zkopírováno, 0,000129285 s, 61,9 kB/s

echo "_BHRfS_M" | dd bs=1 count=8 of=sda.img  seek=$((64*1024*1024+64))
8+0 záznamů přečteno
8+0 záznamů zapsáno
8 bajtů zkopírováno, 0,000323182 s, 24,8 kB/s

a dám znovu btrfs inspect-internal dump-super ať vidím, co jsem udělal. A co nevidím a svým očim nevěřím:
Kód: [Vybrat]
btrfs inspect-internal dump-super --force --all  sda.img
superblock: bytenr=65536, device=sda.img
---------------------------------------------------------
csum_type               0 (crc32c)
csum_size               4
csum                    0x1d92253c [DON'T MATCH]
bytenr                  65536
flags                   0x1
                        ( WRITTEN )
magic                   _BHRfS_M [match]
fsid                    2db8f54a-3a36-4e3c-8e1f-6ef781966d66
metadata_uuid           00000000-0000-0000-0000-000000000000
label
generation              0
root                    0
sys_array_size          0
chunk_root_generation   0
root_level              0
chunk_root              0
chunk_root_level        0
log_root                0
log_root_transid (deprecated)   0
log_root_level          0
total_bytes             0
bytes_used              0
sectorsize              0
nodesize                0
leafsize (deprecated)   0
stripesize              0
root_dir                0
num_devices             0
compat_flags            0x0
compat_ro_flags         0x0
incompat_flags          0x0
cache_generation        0
uuid_tree_generation    0
dev_item.uuid           00000000-0000-0000-0000-000000000000
dev_item.fsid           00000000-0000-0000-0000-000000000000 [DON'T MATCH]
dev_item.type           0
dev_item.total_bytes    0
dev_item.bytes_used     0
dev_item.io_align       0
dev_item.io_width       0
dev_item.sector_size    0
dev_item.devid          0
dev_item.dev_group      0
dev_item.seek_speed     0
dev_item.bandwidth      0
dev_item.generation     0

ERROR: failed to read the superblock on sda.img at 67108864 read 72/4096 bytes
ERROR: error = 'Success', errno = 0

Tedy magic v prvním superbloku už sedí, zato se z něj ztratila podstatná část dat, od label dále. Druhý superblock zmizel úplně -
Citace
failed to read the superblock on sda.img at 67108864

Co to, sakra, je? dd dostal 8 znaků, tvrdí že zapsal 8 znaků, dokonce tam těch 8 znaků vidím na správném místě... Kam, sakra, zmizel ten zbytek superblocku a proč?

CFM

Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #10 kdy: 08. 11. 2024, 19:33:30 »
V tomto zápisu je něco prohnilého:
Kód: [Vybrat]
echo "_BHRfS_M" | dd bs=1 count=8 of=sda.img  seek=$((64*1024+64)) Rychlý pokus:
Kód: [Vybrat]
dd bs=1 count=100000 if=/dev/zero of=sda.imgVelikost 100000B.
Kód: [Vybrat]
echo "_BHRfS_M" | dd bs=1 count=8 of=sda.img  seek=$((64*1024+64)) Velikost 65608B ...

rmrf

Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #11 kdy: 08. 11. 2024, 20:00:05 »
Kód: [Vybrat]
echo "_BHRfS_M" | dd bs=1 count=8 of=sda.img  seek=$((64*1024+64)) conv=notrunc

Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #12 kdy: 08. 11. 2024, 20:25:19 »
Upřímně, při tom svém testu jsem to ani nezkoušel s dd. Skutečně to vypadá, že jste tam zapsal za magic i něco dalšího.

Mám normálně nainstalovaný program hexedit (https://rigaux.org/hexedit.html) bývá v balíčku skoro ve všech distribucích, ten jsem použil na úpravu toho magicu.
ctrl+g (goto na adresu, buď dekadicky, nebo hex s prefixem 0x), tab přepíná mezi editací hex a text (ascii), ctrl+x - save.

Pokud máte ještě původní data beze změny, tak bych se vrátil a zkusil upravit vyloženě těch 8 bajtů (offset 0x10040) jen na prvním superbloku, to by mělo stačit, aby se to připojilo v degraded režimu.

Jinak ještě k těmhle pokusům s nějaký opravami FS se hodí mít možnost se rychle vrátit a ideálně nezasahovat do původního disku. Není vždy praktické mít víc kopií celého disku v několika image souborech, zvlášť když to má třeba několik TB. Používám na to snapshoty device mapperu (udělá se virtuální zařízení a všechny změny jdou pak do samostatného souboru, který může být i sparse)
Viz:
https://unix.stackexchange.com/questions/67678/gnu-linux-overlay-block-device-stackable-block-device

Druhá možnost pro tohle je pak například používat qemu-nbd a image mít uložené jako qcow2 se snapshoty, což umožní větší flexibilitu, ale to je asi zbytečné rozjíždět, pokud s tím neděláte častěji.

Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #13 kdy: 08. 11. 2024, 20:27:21 »
Kód: [Vybrat]
echo "_BHRfS_M" | dd bs=1 count=8 of=sda.img  seek=$((64*1024+64)) conv=notrunc
conv=notrunc - no jasně, to je to co tomu chybělo! V tom původním návodu https://superuser.com/questions/1281942/recover-data-from-replaced-btrfs-disk to nebylo a mě to netrklo.
Moc díky!

Re:BTRFS replace - zapisuje něco na původní disk?
« Odpověď #14 kdy: 08. 11. 2024, 23:24:13 »
Finálně - původní disky vrácené, skříň zavřená a btrfs scrub spokojený.
Moc díky všem. Když si to projdu znovu od začátku je skvělé vidět kolik lidí se "seběhlo" aby mi pomohlo spravit rozbitý raid. Který jsem si navíc rozbil vlastní blbostí. Tak ještě jednou díky.

Pokud to čte někdo, kdo má podobný problém, tak nezapomeňte na

  • Jestli chcete mít víc než jeden pokus, začněte tím, že si disk(y) někam zkopírujete
  • Příkaz dd na přepsání magic string musí mít param conv=notrunc
  • Až se vám to celé povede a disk se probudí, nezapomeňte na btrfs replace cancel <mountpoint>  ;)