Létezik fordított fájlrendszer?

Fórumok

Sziasztok!

Kerestem, de nem találtam. Ismertek olyan eszközt, ami az nbdkit linuxdisk pluginhoz hasonlóan egy könyvtár tartalmából készít egy fájlrendszert tartalmazó blokkos eszközt, de nem hoz létre átmeneti fájlt, és másolja bele a teljes tartalmat, hanem csak bemapeli valamilyen módon a forrás fájlok tartalmát a megfelelő helyre?

Tisztában vagyok a feladat nehézségeivel és buktatóival, de semmi komolyra nem használnám. Csak retro cuccokhoz szeretnék usb gadget driverrel eszközt emulálni, anélkül, hogy meg kellene várnom a fájlok imagebe másolását, illetve duplán kellene tárolnom az adatokat. A fogadó eszközök miatt FAT32, esetleg NTFS fájlrendszerre lenne szükségem.

Köszönöm!

Hozzászólások

Hát nem tudom hogy mekkora segítség, de a qemu tud ilyet. Read-only (ne zavarjon az rw flag, nem lehet írni), és FAT16-ra limitált.

https://en.wikibooks.org/wiki/QEMU/Devices/Storage

Egy ügyesen felhúzott guest-ből ki lehet szedni talán valahogy a blokk eszközt... AoE, vagy hasonló trükkel?

Ezen elgondolkodtam, egyáltalán hogyan lehet megcsinálni. Ha jól értem, nem a bind mount-ot keresed. Ez a mappelős dolog menne, ha minden változatlan, de amennyiben változik az eredeti tartalom, a filerendszer emulációjában is módosítani kell a leírókat. Ez viszont nem triviális, ha például méretek változása miatt fragmentáció keletkezik.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Jól érted. Nyilván csak úgy működhet, ha a "host" oldalon nem változik a könyvtárszerkezet, mert a dinamikus frissítés egyrészt nehéz is lenne, másrészt a kiszolgált eszköz valószínűleg feltételezi, hogy egy USB Mass Storage tartalma csak akkor változik, ha ő maga ír rá. Ugyanezért a fájlok tartalma sem módosulhatna. A kliens oldal módosításait meg talán valami CoW réteggel lehetne megoldani.

De erre igazából nincs szükségem, elég lenne, ha tudnék csinálni egy read-only filerendszert anélkül, hogy alkalmanként percekig várok az image összeállására.

> A kliens oldal módosításait meg talán valami CoW réteggel lehetne megoldani.

Nekem is ez volt az első gondolatom az első postot olvasva. A mke2fs vagy valamelyik hasonló cucc forrása valószínűleg egyszerűen átírható, hogy cow-ozni próbáljon (ioctl(..., FICLONERANGE, ...)), upstream is biztos örülne ilyen patchnek, de az is lehet hogy már megcsinálták; és az egész alá beraksz egy cow-képes fájlrendszert és kész.

Szerkesztve: 2020. 06. 18., cs – 10:16

.

Azért ez a mapelés nekem egyelőre még zavaros. Hogyan érné el a másik fél? USB masstorage? Akkor lenne ott egy mikrokontroller, ami emulálja ezt? Vagy biztosan meg lehet győzni egy Linuxot is arról, hogy az USB portja ne host legyen a gépnek, hanem device, csak nem tudom, hogy hogyan. Ha meg egy image file-ba kell ez, akkor az a gyanúm, magának a filerendszernek az implementációjába kell belenyúlni kernel szinten. Hiszen amikor az emulált fs egy szektorát akarod elérni, az fs leírója alapján ki kell bogarászni, ez melyik file hanyadik szektora, s ekkor a host filerendszerén meg kell keresni az eredeti file ugyanannyiadik szektorát, s vissza kell azt adni a hívónak.

Vagy ami még eszembe jutott, hogy a fuse API-n keresztül lehetne ezt implemetálni.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

fuse ugrott be nekem is elsőre. de az épphogy a "normális" irányra való: van adatod valamin és felcsatolható kvt struktúraként akarod láttatni. ugyanakkor megvalósítható ha mondjuk láttatsz egy blokkeszközfájlt (readdir, getattr) és azon az egyetlen fájlon az open/write/read op call-okon kereszül egy fat fájlrendszert láttatsz. de így a fuse a kisebbik része a dolognak. a nagyobbik a fat implementáció.

Viszonylag egyszerű. Jelenleg egy odroid C2 lapka OTG portján használom a mass storage gadgetet, ami egy fileból (mondjuk a helyi MMC flashből) vagy egy blokkos eszközről (pl. NBD kliens) képes USB mass storage-et emulálni. Ez így lényegében egy rugalmas pendrive, ami mögé hálózaton elérhető tartalmakat tudok tenni.

Ami jelenleg nem tetszik a folyamatban, hogy az emulációhoz szükséges imagek előállításához kell egy fileba irányított loop eszköz, amin létrehozok egy FS-t, ezt csatolom, belemásolgatom a cuccokat, majd így adom az Odroidnak. Ez így nagyobb méretű tartalom esetén sokáig tart és sok tárhelyet igényel.

Amit helyette szeretnék, az az lenne, hogy valami program, pl. egy NBD szerver dinamikusan előállít egy vékony imaget, amiben csak a fájlrendszer struktúra van benne, a tényleges tartalom nincs. Ha az imaget olvasni próbáló kliens olyan területre hivatkozik, ahol egy fájl adatai lennének, akkor a program kinyúl a háttér fájlrendszerbe, és onnan kiolvassa az adatokat. Ha ez csak readonly módon megy, azzal együtt tudok élni.

Van a kernelben olyan, hogy usb-gadget tamogatas. A gyari gadgetek kozott pedig van mass-storage gadget. Ennek at kell adni egy image allomanyt. Az eszkoz az USB kabel vegen pedig szabvanyos USB Mass Storage eszkoznek fogja latni a gepedet, a korabban megadott image allomannyal. Annyi a bibi, hogy a kernel doksija kiemeli, hogy senki mas nem modosithatja az image allomanyt, csak az eppen azzal dolgozo usb master eszkoz (tehat, az a gep, ahova bedugtad, mint egy pendrive).

Nem ez az igazi bibi, hanem hogy neki pont az a réteg kéne, ami ebből hiányzik, ami a random fájlkupacból a kívánt FS típus szerint struktúrát mappeléssel előállítja. Azaz az image állományt odahazudja valahová, úgy, hogy a benne látszó fájlok tartalmát ne kelljen másolni sehova, maradjanak az eredeti fájlkupacban.

nem tudom a use-caset hogy milyen gyakran kell uj tartalmat tenni arra a fs-re, de mi lenne ha elore csinlnal 2 db eleg nagy fat fs-t (vagy ahany kliensed van + n db "csere" fs-t attol fuggoen milyen gyakoran kell uj virtualis pendrive-ot bedugni es az image generalasahoz szükséges ido) es ha ki akarod cserelni az egyik tartalmat, akkor megcsinalod az egyik spare fs-re, es ha kesz kicsereled a kliensen (VM restart vagy emulalt mass storage pull/plug). ez mondjuk nem muködik ha "azonnal" kell a tartalom miutan megtudta a rendszer hogy mi az a tartalom, ami kell. igz ugzan duplan lesy tarolva ay adat, de a duplikatum volatile.

ok, erdekes a tema amit felvetsz, ugyhogy itt van meg egy otlet:

mivel tudtommal a fat nem igazan "keveri meg" a block-szinu nyers adatot amikor letárol egy-egy fajlt, ezt kihasznalva csinalhatod, azt hogy legeneralod egyszer azokat az image-ket (feltetelezve hogy veges szamu fs-re van szukseged) amikre szukseged lesz es valamilyen forensic vagy block dedup tool-lal kiszeded, hogy a fat fs image es az eredeti fajlok közt hol van duplikacio, es azokat a range-eket lementeni (ez a mapping, amit fentebb irsz). az image-ben amit nem talal meg mint duplikatum, azt meghagyni, az viszonylag keves adat lesz szerintem, gyakorlatilag a fat struktura, meta adat. utana a block device accessor-t ugy megirni, hogy eloször is oké, olvassa a "hianyos" image fajlt, de ahol mapping referenciat talal, ott a map-elt fajlbol adja vissza az adatot. ez a block device accessor lehet egy fuse-zal emulalt blockspecial file is, de a rendes linuxos device mapper is kepes ilyere, hogy 0-tol 4095. byte-ig innen vedd az adatot, 4096-tl valameddig meg emebbol a forrasbol, ettol az offsettol szamolva vedd, stb.

ezzel igy ugyan lesznek image-eid, de ki lesz beolük szedve a duplikalt adat ami egyebkent is megvan külön fajlokban.

továbbgondolva a témát és az ékezeteimet visszakapva, nem vagyok FAT-expert, de sztem megérne egy próbát, hogy egy elkészült image-et és az eredeti fájlokat is 4K-s blokkokra szedve (a fájlok darabjait zérókkal paddolni) valami sima dedup-ot ráereszteni és a kimenetből (tudva hogy az image melyik darabja, melyik byterange-et tartalmazza a komplett image-ből) egy dmsetup block device leírót készíteni. valami ilyesmi:

0 4095 linear /egyik_image/block_1.dat 0   # meta-data, fat sallang, vegye az image-ből
4096 8191 linear /eredeti_fajlok/doom.exe 0   # ez a block teljes egészében megvan egy eredeti fájlban
8192 8999 linear /eredeti_fajlok/doom.exe 4096  # folytatás
9000 12123 linear /egyik_image/block_3.dat 808  # utolsó adatblokk vége, padding
12124 16123 linear /egyik_image/block_4.dat 0   # megint fat meta data

például

igen ez kétségtelen.

az lenne a szép megoldás ha egyszer se kéne adatot másolni. ehhez pedig valamilyen fat/ntfs író alkalmazást kéne átírni, hogy amikor adatot "kap". fuse szintjén pl nem tudni, honnan jön az adat, nincs referencia a "cp parancs source fájljára", de szerintem a vfs szintjén sem. tehát én nem a standard mount.vfat meg in-kernel vfat implementációból indulnék ki, hanem mondjuk az mtools-ból, az userspace-ben emulál dos-os eszközöket, pl van benne "mcopy -i floppy.img ~/test.dat ::test.dat" parancs, ami egy FAT image-be felmásol fájlt. ehhez mondjuk elengedhetetlen hogy először legyen egy image-d, de az az image fájl mar emulálható mondjuk fuse-zal. ugyanez a fuse fs megteheti, hogy amikor blokkokat kérnek tőle, akkor a meghekkelt mcopy által előállított mapping alapján szedi elő blokkokat az eredeti fájlokból (~/test.dat).

amit én POC-oltam az a fuse-os rész, tehát ami egy mapping alapján arbitrary helyről kiszolgálja a blokkokat. valamint egy dedupper, ami az mcopy-s komponens helyett van és azt csinálja hogy egy kész image és a forrásfájlok ismeretében "visszakeresi" melyik blokk honnan jött. tehát a dedupper-nél nem is az adatdeduplikálás a lényeg, hanem hogy a duplikált részek felfedezése révén elő tudja állítani a "fat-block : eredeti fájl : offset" mappinget. ezt a deduppert ha kicserélnénk egy hekkelt mcopy-ra, akkor tényleges adat írás nélkül is előállítható a mapping fájl.

megevett? tehát a program inputja egy már összeállítótt iso9660 image? mert akkor nem nagy találmány. azt közvetlen is fel loop-olhatod.

avagy egy könyvtár path az inputja és (egy egyszeri dir list után) abból épít fel egy iso imaget memóriában?

gergov, neked az ISO is jó lenne? mert ha igen, annak talán még egyszerűbb a belső struktúrája, tekintve, hogy eredetileg is readonly-ra tervezték. habár gondolom, nem, mert a retro/legacy/dos/win32-es cuccok nem számítanak CD fs-re egy usb drive-on.

Iso image is jó volt, de rengeteg más formátumot is kezelt, ez volt a lényege, hogy ne kelljen iso-ba konvertálni. Tehát ez már "majdnem" az, sőt talán több is, mint ami ide kellene, mert másik fájlformátumból kellett neki on-the-fly előállíania a megfelelő blokk-eszközt. De az tény, hogy (gondolom) a fájlrendszer ismerete nélkül csinálta.

Amúgy igen, egy iso nem is rossz ötlet, és jó a visszafele kompatibilitása is. mkisofs egy tmpfs-re elhelyezett image-re? Amit egyből lehet is törölni, ha fel van csatolva, és amint umount-olva lesz, már meg is szűnik :)

De mivel pontosan nem értem a use-case-t lehet hogy ez nem segít.

nem biztos hogy "csak ezért" hajlandó egy új függőséget beiktatni a rendszerébe. egy fájlrendszernek ahol értékes adatot tárolsz (márpedig az eredeti fájlokat zfs-re kell mozgatnia hogy a zfs össze tudja deduppolni a fat image-ekkel), több gondoskodás kell, mint egy egyszeri dedup futtatasnak. vagy jobban mondva nem dedup hanem duplikátum keresés.

Jó, most ez egy hobbi otthonra, semmi komoly, azt telepítek, amit akarok, és ha véletlenül minden megsemmisül, akkor sem fogok a kardomba dőlni.

Mivel úgyis btrfs-t használok, a dedup lehetőség adott, de ha már ezzel kell vacakolni, akkor maradok a bevált módszernél. Mint feljebb írtam, tulajdonképpen a qemu hasonló funkciója adta az ötletet, de mivel a keresőzés nem adott hasznos eredményt, rákérdeztem itt, hogy hátha ismer valaki valamit, ami jó lenne erre.

sztem ez pontosan illeszkedik az általad vázoltakba.

 

./nbdkit -v -f -o -p 12345 -r plugins/floppy/.libs/nbdkit-floppy-plugin.so dir=.

nbd-client host 12345 /dev/nbd0

fdisk  -l /dev/nbd0

Disk /dev/nbd0: 40 MB, 40583168 bytes
255 heads, 63 sectors/track, 4 cylinders, total 79264 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

     Device Boot      Start         End      Blocks   Id  System
/dev/nbd0p1            2048       79263       38608    c  W95 FAT32 (LBA)

losetup -o $[2048*512] /dev/loop0 /dev/nbd0

mount /dev/loop0 /mnt/test

és ott vannak a fájlok!

gyors check strace-szel és úgy fest az nbdkit csak O_RDONLY-val nyit meg fájlokat, szóval szerintem nem ment le átmeneti állományt.

és a vicces az egészben hogy a topik indítóban magad írtad az nbdkit-et. úgyhogy most is tanultam.

off

Ez egy kicsit felcsigázott. Ha jól értem, az nbd egy hálózaton elérhető block device. Ha így van, akkor ez használható file szervernek, nem? Akkor érdemes kínlódni samba-val vagy nfs-sel, amikor nbd-vel mindez sokkal egyszerűbbnek tűnik? Lehet ezt, célszerű ezt fileszerverként használni? Vagy itt az lesz a probléma, hogy egy device-hoz csak egy kliens csatlakozhat, míg fileszerver esetében pedig sok? Tényleg, egy nbd szervert egyszerre hány kliens piszkálhat?

Szerk.: érzem már, hol lesz a baj. A block eszközt többen használhatják ugyan, de az azon lévő egy-egy filerendszert csak mindig egy kliens mount-olhatja fel.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Nem hagyományos fileszerverként, csak file-ok mentésére vagy otthonról elhozására használom azt, hogy a router-embe dugott USB hub-ban van egy 60 GB-os pendrive, rajta egy f2fs filerendszer. Amikor kell hozzáférés, ssh-zok a router-re, felcsatolom a pendrive filerendszerét, majd midnight commanderből elérem távolról lényegében ssh tunnelingen. Ha készen vagyok, umount majd exit.

Nem fogok a routeren nbd szervert indítani, mert ahhoz folyamatosan felcsatolva kellene lennie a pendrive-nak, szóval marad a mostani, bevált megoldás.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

pontosan, az nbd modul csinál /dev/nbd* device-okat, amiket nbd szerverrel megosztott volume-okhoz csatolhatsz. block device over net gyakorlatilag. samba, nfs, sshfs más nyújt, komplett könyvtárfa, nem csak egy blokk amin bármi lehet (partíció, azon valamilyen tipusú fs, azon a kvt fa). több klienst is kiszolgál egyszerre, ro és rw kapcsolatokat is, de nyilván az fs konzisztenciáért nem felel, mert az nbd server blokk szinten operál. 

Kettő limitáció van a topikindító megoldására használt pluginben: a cucc readonly, és a mögöttes fájlokhoz nem szabad hozzányúlni.

Ha amúgy az NBD-t általánosan akarnád használni, valóban, ott ha egynél több gépen akarod használni, akkor olyan problémád lesz, hogy vagy egyszerre csak egy gépen mountolhatod, vagy csak readonlyba, vagy cluster fájlrendszert kell használnod.

visszakanyarodva a topikindító kérdéshez, valóban az nbdkit floppy plugin önmagában csak readonly accesst tesz lehetővé ha változnak alatta a fájlok, akkor megbízhatatlan lesz az nbd device.

viszont egy okos processzt köré építve a rw accesszt se találom képtelenségnek:

az nbd device fölé húzunk egy CoW réteget. alkalomadtán (amikor a kliens elengedi a virtuális storage devicet) a CoW-os block device-on lévő fs-ből kimentjük a fájlokat felülírva az eredeti fájljainkat, amiből az nbdkit-floppy dolgozik.
továbbá ha a kimentés révén vagy máshogyan változnak a forrásfájlok (mondjuk inotify-lyal figyelve), akkor újraindítjuk az nbdkit-et (mondjuk ha csak inotify eventre reagálva kilőjük az nbd szervert, akkor fennáll a race condition, szóval valami lock-olást kéne beépíteni az egészbe, vagy az nbdkit maga figyelné az inotify eventeket - nem tudom mennyire atomikus). ehhez még csak az kell, hogy ha az nbd kliensnek megszakad a kapcsolat, akkor az OS felé azt úgy kommunikálja, mintha remove-olva lenne a kapcsolódó (/dev/nbd0) device.

ennek az unchunkfs része lenne jó arra hogy az fs image darabjai külön fájlokban vannak tárolva és kívülről egyesítve mutatja őket egy fájlként. viszont nem tud offset eltolást, tehát a fájlok az fs image-ben folytonosan kell elhelyezkedjenek. elképzelhetőnek tartom hogy lehet ilyen fs image-t generálni talán fat image-t is, de iso-t jobban.