{"id":414,"title":"Kurtar\u0131lamaz\" Denen RAID'i S\u0131f\u0131rdan Geri Kurmak","content":"<h1>Metadata's\u0131z RAID ve Yedek Kurtarma: Mimari ve Uygulama Notlar\u0131<\/h1>\n<p>Bu yaz\u0131, index\/journal\/dosya sistemi hi&ccedil;birinin kalmad\u0131\u011f\u0131 bir Veeam kurtarma vakas\u0131nda yazd\u0131\u011f\u0131m iki arac\u0131n teknik i&ccedil; yap\u0131s\u0131n\u0131 ele al\u0131yor. Ama&ccedil; hikaye anlatmak de\u011fil; kararlar\u0131n <em>neden<\/em> &ouml;yle al\u0131nd\u0131\u011f\u0131n\u0131 ve uygulaman\u0131n nas\u0131l kuruldu\u011funu g&ouml;stermek.<\/p>\n<h2>Problem Tan\u0131m\u0131<\/h2>\n<p>Girdi durumu:<\/p>\n<ul>\n<li>RAID metadata's\u0131 kay\u0131p, &uuml;st&uuml;ne yanl\u0131\u015f parametrelerle (muhtemelen yanl\u0131\u015f stripe size \/ disk s\u0131ras\u0131 ile) bir \"rebuild\" denemesi yap\u0131lm\u0131\u015f &mdash; yani &uuml;st &uuml;ste iki bozulma katman\u0131 var.<\/li>\n<li>Dizideki bir k\u0131s\u0131m disk Windows'ta h\u0131zl\u0131 formatlanm\u0131\u015f, ard\u0131ndan &uuml;zerine yeni veri yaz\u0131lm\u0131\u015f.<\/li>\n<li>Hedef veri bir Veeam backup repository'si (.vbk\/.vib zinciri), ama repository'nin kendi index\/metadata katman\u0131 da kay\u0131p.<\/li>\n<\/ul>\n<p>\u0130ki ayr\u0131 problem s\u0131n\u0131f\u0131 var burada ve birbirine kenetli: <strong>(1) blind RAID reconstruction<\/strong> &mdash; hi&ccedil;bir &uuml;st seviye metadata olmadan disk dizisinin geometrisini tespit etmek, <strong>(2) metadata's\u0131z i&ccedil;erik carving<\/strong> &mdash; dosya sistemi ya da backup index'i olmadan, ham bloklardan orijinal yedek yap\u0131s\u0131n\u0131 geri kurmak.<\/p>\n<h2>K\u0131s\u0131m 1: RAID Geometri Tespiti<\/h2>\n<h3>Neden mevcut ara&ccedil;lar yetmedi<\/h3>\n<p>PC-3000 ve benzerlerinin RAID reconstruction mod&uuml;lleri temelde \u015funu yapar: disk ba\u015f\u0131na belirli offsetlerde dosya sistemi imzalar\u0131 arar (NTFS <code>$MFT<\/code> kay\u0131tlar\u0131n\u0131n periyodikli\u011fi, FAT tablo tekrarlar\u0131 vb.), farkl\u0131 stripe size \/ disk s\u0131ras\u0131 \/ rotasyon kombinasyonlar\u0131n\u0131 dener, hangi kombinasyonda bu imzalar \"tutarl\u0131\" bir \u015fekilde diziliyor diye bakar. Bu, istatistiksel bir arama uzay\u0131 problemi &mdash; N disk i&ccedil;in disk s\u0131ras\u0131 perm&uuml;tasyonu &times; olas\u0131 stripe size seti &times; rotasyon y&ouml;n&uuml; kombinasyonlar\u0131n\u0131 taray\u0131p bir \"confidence score\" ile en iyi aday\u0131 se&ccedil;iyor.<\/p>\n<p>Bu y&ouml;ntemin temel varsay\u0131m\u0131: <strong>disk &uuml;zerindeki veri deseni bozulmam\u0131\u015f<\/strong>. Benim vakamda bu varsay\u0131m ge&ccedil;ersizdi &mdash; baz\u0131 diskler formatlan\u0131p &uuml;zerine yaz\u0131lm\u0131\u015ft\u0131, yani &uuml;zerlerindeki \"desen\" zaten farkl\u0131 bir dosya sistemi kurulumuna aitti. Algoritma orada tutarl\u0131 bir sonu&ccedil; bulam\u0131yor, &ccedil;&uuml;nk&uuml; arad\u0131\u011f\u0131 imzalar ger&ccedil;ekten yok.<\/p>\n<h3>Yakla\u015f\u0131m: Desen aramak yerine iz okumak<\/h3>\n<p>Kendi arac\u0131mda stratejiyi tersine &ccedil;evirdim: dosya sistemi i&ccedil;eri\u011fine bak\u0131p geometriyi <em>tahmin etmek<\/em> yerine, RAID controller'lar\u0131n disk &uuml;zerinde b\u0131rakt\u0131\u011f\u0131 <strong>kendi metadata art\u0131klar\u0131n\u0131<\/strong> do\u011frudan okumak.<\/p>\n<p>Pratikte bu \u015fu katmanlardan olu\u015fuyor:<\/p>\n<p><strong>a) WWN tabanl\u0131 disk kimliklendirme<\/strong><\/p>\n<p>Her fiziksel diskten WWN (World Wide Name) okunuyor ve bu, dizideki mant\u0131ksal disk pozisyonuyla e\u015fle\u015ftiriliyor. RAID controller'lar\u0131n &ccedil;o\u011fu (LSI\/Avago, Adaptec, Intel RST) config bloklar\u0131nda disk kimliklerini saklar; bu bloklar formatla silinmemi\u015fse (genelde disk sonunda ayr\u0131 bir reserved alanda dururlar) buradan disk s\u0131ras\u0131 do\u011frudan okunabiliyor. Go taraf\u0131nda bu, <code>\/dev\/sdX<\/code> &uuml;zerinde <code>ioctl<\/code> ile SCSI INQUIRY komutu (page 0x83) &ccedil;a\u011f\u0131rarak WWN &ccedil;ekmek \u015feklinde uyguland\u0131 &mdash; &uuml;&ccedil;&uuml;nc&uuml; parti ba\u011f\u0131ml\u0131l\u0131k yok, do\u011frudan syscall seviyesinde.<\/p>\n<p><strong>b) Config art\u0131klar\u0131ndan stripe\/parity geometrisi<\/strong><\/p>\n<p>Disklerin controller-reserved alanlar\u0131nda (genelde disk sonunda, birka&ccedil; MB'l\u0131k bir b&ouml;lge) eski RAID config yap\u0131lar\u0131 kal\u0131nt\u0131 halinde duruyordu. Buradan stripe size ve parity rotasyon y&ouml;n&uuml; do\u011frudan parse edildi &mdash; tahmin de\u011fil, kay\u0131t okuma. Format i\u015flemi genelde bu alanlara dokunmuyor &ccedil;&uuml;nk&uuml; i\u015fletim sistemi bu sekt&ouml;rleri \"kullan\u0131labilir alan\" olarak g&ouml;rm&uuml;yor.<\/p>\n<p><strong>c) COW katman\u0131 &mdash; sanal montaj<\/strong><\/p>\n<p>Bu, mimarinin can al\u0131c\u0131 noktas\u0131. Elimde formatlan\u0131p &uuml;zerine yaz\u0131lm\u0131\u015f diskler oldu\u011fu i&ccedil;in, herhangi bir yanl\u0131\u015f geometri denemesi ger&ccedil;ek diske yaz\u0131l\u0131rsa geri d&ouml;n&uuml;\u015f&uuml; olmayan bir hasar riski var. Bu y&uuml;zden RAID'i hi&ccedil;bir zaman fiziksel diske yazmadan kurdum:<\/p>\n<ul>\n<li>Her fiziksel disk salt-okunur (<code>O_RDONLY<\/code>) a&ccedil;\u0131l\u0131yor.<\/li>\n<li>&Uuml;zerine bir sparse overlay dosyas\u0131 (fiziksel disk ba\u015f\u0131na bir \"diff\" dosyas\u0131) tan\u0131mlan\u0131yor; okunan her sekt&ouml;r &ouml;nce overlay'de var m\u0131 diye kontrol ediliyor, yoksa fiziksel diskten okunup overlay'e gerekti\u011finde yaz\u0131l\u0131yor (yaln\u0131zca RAID kurulum s&uuml;recinin kendi &uuml;retti\u011fi meta-yaz\u0131lar overlay'e gidiyor, kullan\u0131c\u0131 verisine asla dokunulmuyor).<\/li>\n<li>Bu sanal katman, bir NBD (Network Block Device) server olarak expose ediliyor. Go'da bu, NBD protokol&uuml;n&uuml; (basit bir TCP &uuml;zerinden request\/reply &mdash; <code>NBD_CMD_READ<\/code>, <code>NBD_CMD_WRITE<\/code>, <code>NBD_CMD_DISC<\/code>) do\u011frudan implemente ederek yap\u0131ld\u0131; harici bir ba\u011f\u0131ml\u0131l\u0131k gerekmedi.<\/li>\n<li>Linux taraf\u0131nda <code>nbd-client<\/code> ile bu sanal cihaz <code>\/dev\/nbdX<\/code> olarak mount edilip &uuml;zerinde normal bir blok cihaz\u0131 gibi &ccedil;al\u0131\u015f\u0131labiliyor &mdash; <code>mdadm --assemble<\/code>, loop mount, hatta do\u011frudan dosya sistemi recovery ara&ccedil;lar\u0131 bu sanal cihaza kar\u015f\u0131 &ccedil;al\u0131\u015ft\u0131r\u0131labiliyor.<\/li>\n<\/ul>\n<p>Bunun getirdi\u011fi pratik fayda: onlarca farkl\u0131 stripe size \/ disk s\u0131ras\u0131 \/ rotasyon kombinasyonunu, her denemede ger&ccedil;ek diske hi&ccedil; dokunmadan test edebildim. Yanl\u0131\u015f bir kombinasyon sadece \"bo\u015f\" ya da tutars\u0131z bir dosya sistemi g&ouml;r&uuml;nt&uuml;s&uuml; veriyordu, hasar vermiyordu.<\/p>\n<p><strong>d) Formatlanm\u0131\u015f disklerin toparlanmas\u0131<\/strong><\/p>\n<p>Format (&ouml;zellikle h\u0131zl\u0131 format) diski s\u0131f\u0131rlamaz; yaln\u0131zca dosya sistemi metadata yap\u0131lar\u0131n\u0131 (MFT, boot sector, cluster bitmap) yeniden yazar. Kullan\u0131c\u0131 verisinin b&uuml;y&uuml;k k\u0131sm\u0131, yeni format taraf\u0131ndan hen&uuml;z &uuml;zerine yaz\u0131lmam\u0131\u015f cluster'larda h&acirc;l&acirc; duruyordu. Bu diskler RAID'e COW katman\u0131 &uuml;zerinden dahil edildikten sonra, RAID seviyesinde toparlanan stripe'lar zaten eski veriyi i&ccedil;eriyordu &mdash; &ccedil;&uuml;nk&uuml; format sadece dosya sistemi seviyesinde bir i\u015flemdi, RAID'in stripe d&uuml;zenini de\u011fi\u015ftirmemi\u015fti.<\/p>\n<h2>K\u0131s\u0131m 2: Metadata's\u0131z Veeam Blok Carving<\/h2>\n<p>RAID toparland\u0131ktan sonra elimde tutarl\u0131, okunabilir bir ham disk imaj\u0131 vard\u0131 &mdash; ama i&ccedil;inde ne bir dosya sistemi, ne &ccedil;al\u0131\u015fan bir .vbk, ne index, ne journal.<\/p>\n<h3>Veeam blok yap\u0131s\u0131na dair g&ouml;zlemler<\/h3>\n<p>Veeam backup dosyalar\u0131 (.vbk\/.vib) i&ccedil;eride sabit veya de\u011fi\u015fken boyutlu \"extent\" bloklar\u0131ndan olu\u015fur; her blok genelde bir header\/checksum ile ba\u015flar ve s\u0131k\u0131\u015ft\u0131rma (genelde zlib\/lz4 varyantlar\u0131) uygulanm\u0131\u015f olabilir. Format s&uuml;r&uuml;m&uuml;ne g&ouml;re detaylar de\u011fi\u015fir, ama pratikte her blo\u011fun kendi i&ccedil;inde b&uuml;t&uuml;nl&uuml;k kontrol&uuml;ne izin veren bir imza\/checksum alan\u0131 var. Index kaybolsa bile bu, bloklar\u0131 tek tek tan\u0131may\u0131 m&uuml;mk&uuml;n k\u0131l\u0131yor.<\/p>\n<h3>Carving stratejisi<\/h3>\n<p>Ara&ccedil; \u015fu ak\u0131\u015fla &ccedil;al\u0131\u015f\u0131yor:<\/p>\n<ol>\n<li><strong>Ham tarama<\/strong>: Disk imaj\u0131 sabit boyutlu pencerelerle (chunk) taran\u0131yor, her pencerede bilinen blok header imzalar\u0131 aran\u0131yor.<\/li>\n<li><strong>Blok do\u011frulama<\/strong>: Bir imza bulundu\u011funda, blok boyutu header'dan okunup checksum ile i&ccedil;erik do\u011frulan\u0131yor. Checksum tutmuyorsa blok \"bozuk\/k\u0131smi\" olarak i\u015faretleniyor, at\u0131lm\u0131yor &mdash; &ccedil;&uuml;nk&uuml; ileride ba\u015fka bir kaynaktan tamamlanabilir.<\/li>\n<li><strong>Blok haritas\u0131 (block map) olu\u015fturma<\/strong>: Bulunan her blok, orijinal VM disk offset'ine (blok header'\u0131nda genelde bu bilgi de ta\u015f\u0131n\u0131r) g&ouml;re bir haritaya yerle\u015ftiriliyor. Bu harita asl\u0131nda kaybolan index'in yeniden in\u015fas\u0131.<\/li>\n<li><strong>&Ccedil;apraz yedekten tamamlama<\/strong>: Bir offset i&ccedil;in hi&ccedil;bir sa\u011flam blok bulunamad\u0131\u011f\u0131nda, ayn\u0131 VM'in farkl\u0131 bir restore point'ine ait ikinci bir ham taramadan ayn\u0131 offsete kar\u015f\u0131l\u0131k gelen blok aran\u0131yor. Incremental backup yap\u0131s\u0131 gere\u011fi bloklar aras\u0131nda y&uuml;ksek &ouml;rt&uuml;\u015fme var, bu da eksik par&ccedil;alar\u0131n b&uuml;y&uuml;k k\u0131sm\u0131n\u0131n ba\u015fka bir yedekte sa\u011flam halde bulunmas\u0131n\u0131 sa\u011fl\u0131yor.<\/li>\n<li><strong>Yeniden birle\u015ftirme (reassembly)<\/strong>: Blok haritas\u0131 tamamland\u0131\u011f\u0131nda, bloklar do\u011fru offsetlerde birle\u015ftirilip ya do\u011frudan okunabilir bir disk imaj\u0131 olarak ya da yeni bir .vbk kabu\u011fu i&ccedil;ine yaz\u0131larak Veeam'in kendisinin tan\u0131yabilece\u011fi bir formata sokuluyor.<\/li>\n<\/ol>\n<h3>&Ouml;l&ccedil;ek ve g&ouml;zlemlenebilirlik<\/h3>\n<p>Terabaytlarca ham veriyi taramak I\/O-bound bir i\u015f. Go taraf\u0131nda bunu \u015f&ouml;yle yap\u0131land\u0131rd\u0131m:<\/p>\n<ul>\n<li>Disk imaj\u0131 sabit boyutlu segmentlere b&ouml;l&uuml;n&uuml;p her segment ayr\u0131 bir worker goroutine'e veriliyor (<code>sync.WaitGroup<\/code> + s\u0131n\u0131rl\u0131 say\u0131da worker, disk I\/O bant geni\u015fli\u011fini bo\u011fmamak i&ccedil;in <code>semaphore<\/code>\/buffered channel ile s\u0131n\u0131rland\u0131).<\/li>\n<li>Her worker kendi buldu\u011fu bloklar\u0131 bir sonu&ccedil; channel'\u0131na yaz\u0131yor; ayr\u0131 bir \"collector\" goroutine bunlar\u0131 merkezi blok haritas\u0131na (bir <code>sync.Map<\/code> ya da kilitli bir B-tree benzeri yap\u0131) i\u015fliyor.<\/li>\n<li>\u0130lerleme durumu (taranan byte, bulunan blok say\u0131s\u0131, do\u011frulanamayan\/eksik blok say\u0131s\u0131, &ccedil;apraz yedekten tamamlanan blok say\u0131s\u0131) periyodik olarak tek bir terminal\/TUI ekran\u0131na push ediliyor &mdash; b&uuml;y&uuml;k &ouml;l&ccedil;ekli, uzun s&uuml;ren bir i\u015flemde \"ne kadar kald\u0131, nerede hata var\" g&ouml;r&uuml;n&uuml;rl&uuml;\u011f&uuml; kritik.<\/li>\n<\/ul>\n<h2>&nbsp;<\/h2>\n<p>\u0130ki arac\u0131n da ortak noktas\u0131 \u015fu: <strong>metadata'ya g&uuml;venmemek, ham veriden &ccedil;\u0131kan izlere g&uuml;venmek.<\/strong> RAID taraf\u0131nda bu, config art\u0131klar\u0131ndan geometri okumak ve COW ile hasars\u0131z deneme yapmak anlam\u0131na geldi. Backup taraf\u0131nda ise, blok i&ccedil;eri\u011finin kendi imzalar\u0131ndan bir index'i yeniden in\u015fa etmek ve eksik par&ccedil;alar\u0131 &ccedil;apraz yedekten kapatmak anlam\u0131na geldi.<\/p>\n<p>Piyasadaki genel ama&ccedil;l\u0131 ara&ccedil;lar \"temiz veri, sa\u011flam metadata\" varsay\u0131m\u0131yla optimize edilmi\u015f durumda. O varsay\u0131m &ccedil;&ouml;kt&uuml;\u011f&uuml;nde, i\u015f orada bitmiyor &mdash; asl\u0131nda custom tooling'in ger&ccedil;ekten gerekli oldu\u011fu nokta oras\u0131 oluyor.<\/p>","excerpt":"Bu yaz\u0131, index\/journal\/dosya sistemi hi\u00e7birinin kalmad\u0131\u011f\u0131 bir Veeam kurtarma vakas\u0131nda yazd\u0131\u011f\u0131m iki arac\u0131n teknik i\u00e7 yap\u0131s\u0131n\u0131 ele al\u0131yor. Ama\u00e7 hikaye anlatmak de\u011fil; kararlar\u0131n neden \u00f6yle al\u0131nd\u0131\u011f\u0131n\u0131 ve uygulaman\u0131n nas\u0131l kuruldu\u011funu g\u00f6stermek.","created_at":"2026-08-04 17:10:41","updated_at":"2026-09-23 15:47:38","category_id":6,"view_count":250,"reading_time":9,"status":"published","editor_choice":0,"is_editor_choice":0,"published_at":"2026-08-04 14:10:41","featured_image":"\/uploads\/images\/2026\/08\/6a71f2cdb72b6_1785852621.jpg","slug":"kurtarilamaz-denen-raid-i-sifirdan-geri-kurmak","category_name":"Sistem","category_slug":"sistem","category_color":"#3b82f6"}