Filsystem JFFS (Journaling Flash File System) Ett kapitel för kursen Wearable Computers D 10 p



Relevanta dokument
Öppna filer och filsystem i PintOS Hemuppgift TDDI81, 21/

Fö 8: Operativsystem II. Minneshantering. Minneshantering (1) Minneshantering (2) Minneshantering och Virtuelltminne.

Operativsystem - Filsystem

Magnus Nielsen, IDA, Linköpings universitet

Filsystem. Varför? Hur? För att kunna lagra data mer permanent än i RAM. Vettig organisation Vettiga namn

TDDIU81. Processer och trådar. Andreas Dahlberg, Jonathan Doherty, Tony Magnusson, Patrik Ottosson, Rasmus Siljedahl

Operativsystem Lektion 1. Lärare. Schema. Kurssajten Finns på adressen. Jan Erik Moström. Set Norman

Projekt Fake för Virtutech

Tommy Färnqvist, IDA, Linköpings universitet. 1 ADT Map/Dictionary Definitioner Implementation... 2

Anujan Balasingam IDA14 NAND flashminnen

Tommy Färnqvist, IDA, Linköpings universitet. 1 ADT Map/Dictionary Definitioner Implementation... 2

Operative system. LRU-algoritm (2 p) Svar: 7 fel. c) Optimal algoritm (2 p) Svar: 6 fel

komplett kopia av hårddisken 20 minu En instabil dator som ofta drabbas av fel får du snabbt på rätt kurs med en kopia av Windows och alla program.

Laboration 0. Enhetsbokstaven anges med ett kolon efter och man läser ofta ut detta, exempelvis C:(sekolon).

Hantering av begränsat antal skrivningar på Solid State diskar

TIDNINGEN. Konsten att partitionera SSD-flash EMBEDDED. Kongeniala rapporter om inbyggda system etn.se/expert. Claus Giebert Kontron

Inlämningsuppgift : Finn. 2D1418 Språkteknologi. Christoffer Sabel E-post: csabel@kth.se 1

Operativsystem. Informationsteknologi sommarkurs 5p, Agenda. Slideset 7. Exempel på operativsystem. Operativsystem

Allmänt om programvaror och filer i Windows.

Operativsystem ID1200/06 (ID2200/06 6hp) Tentamen :00-18:00

Generell säkerhet. Loggning - Hur mycket ska man logga? Inloggningsrutinerna i Unix. Loggning fortsättning

Operativsystem. Innehåll. Operativsystemets funktion. Vad är ett OS? Vart hittar men ett OS? OS hanterar processorns resurser

Flera processer. Minneshantering. Trashing kan uppstå ändå. Ersätta globalt

Deluppgift 17 Processhantering: exec, sleep, exit, plist

Föreläsning 2. Operativsystem och programmering

Operativsystem (IS1350) :00-12:00

Föreläsning 3.1: Datastrukturer, en översikt

Ladda upp filer fra n PLC till PC

Filsystem användarvy och implementering. Föreläsning 4

Spårbarhet i digitala system. Biografi. Spårbarhet. Osynlig övervakning och de spår vi lämnar efter oss

Fö 7: Operativsystem. Vad är ett operativsystem? Målsättning med operativsystem. Styr operativsystemet datorn?

z/os JCL och Utilities

En Von Neumann-arkitektur ( Von Neumann-principen i föreläsning 1) innebär:

Datorteknik ERIK LARSSON

SharpdeskTM R3.2. Installationsguide Version

SharpdeskTM R3.2. Installationsguide Version

Länkning av Prolog under C

Jämförelse av skrivtekniker till cacheminne

MESI i Intel Core 2 Duo

Databaser - Design och programmering. Minnesteknik. Minnesteknik, forts. Hårddisk. Primärminne (kretsteknik) Fysisk design av databasen

Programmering B med Visual C

Operativsystem ID2200 Tentamen TEN1 3.8 hp :00-18:00

Tommy Färnqvist, IDA, Linköpings universitet

Classes och Interfaces, Objects och References, Initialization

Installationsanvisning för LUQSUS version 2.0

Olika OS. Unix, Linux och Windows. Unix. Unix. En översikt av ett par OS. Titt på hur de gör. Många varianter. Mycket gemensamt. En del som skiljer

Grundkurs 1 IKT Filhantering

Fullständig prestandahantering

Lunds Tekniska Högskola Datorarkitektur med operativsystem EITF60. Superscalar vs VLIW. Cornelia Kloth IDA2. Inlämningsdatum:

Introduktion till MySQL

Introduktion till programmering. Undervisning. Litteratur och examination. Lärare. Föreläsning 1

ZFS. Linuxadministration I 1DV417. Wednesday, January 23, 13

Filsäkerhet i Windows NT (NTFS)

Snapdragon 810: Cacheminnet

Introduktion till programmering och Python Grundkurs i programmering med Python

Pipelining i Intel Pentium II

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 3 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Omkoppling av in- och utmatning. In- och utmatning i Unix. Kommando exempel, ls, pipe forts. Kommando exempel, ls, pipe

Databaser Design och programmering Minnesteknik Minnesteknik, forts Utvecklingen Hårddisk Hårddisk, forts

UNIX Introduktion UNIX. Datorerfarenhet. Vad menar man med operativsystem

Flytt av. Vitec Mäklarsystem

Teoretisk del. Facit Tentamen TDDC (6)

DIG IN TO Dator och nätverksteknik

Operativsystem ID1200/06 (ID2200/06 6hp) Tentamen :00-18:00

Datastrukturer, algoritmer och programkonstruktion (DVA104, HT 2014) Föreläsning 5

BLI VÄN MED DIN DATOR ENHETER MAPPAR FILER

Dagens OS. Unix, Linux och Windows. Unix. Unix. En översikt av dagens OS Titt på hur de gör. Många varianter Mycket gemensamt. En del som skiljer

Steg 1 Minnen, mappar, filer Windows 8

Övningen vill visa på vikten av valet av datastruktur, trots att de ofta erbjuder samma funktionalitet genom sina gränssnitt.

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Institutionen för Datavetenskap Department of Computer Science

Installationsanvisning för LUQSUS-K version 3.0b

Introduktion till hårdvara, mjukvara och operativsystem

Prestandajämförelse - Sekventiell skrivhastighet i RAID 4 och RAID 5

Operativsystem ID2206 Tentamen TEN1 4.5 hp :00-18:00

Vad är en dator? Introduktion till datorer och nätverk. Pontus Haglund Institutionen för datavetenskap (IDA) 21 augusti 2018

Administration / Disk Management. EC Utbildning AB

4 grundregler. Minneshantering. Problemet. Windows minkrav

Steg 1 Minnen, mappar, filer Windows 10

Steg 1 Minnen, mappar, filer Windows 7

Datorsystem 5. På denna föreläsning skall vi prata om Operativsystem Exempel på tenta (typ fjolårets)

Databaser Design och programmering. Fysisk design av databasen att ta hänsyn till implementationsaspekter: minnesteknik filstrukturer indexering

Datastrukturer, algoritmer och programkonstruktion (DVA104, VT 2015) Föreläsning 6

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 3 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Installationsanvisningar VisiWeb. Ansvarig: Visi Closetalk AB Version: 2.3 Datum: Mottagare: Visi Web kund

Bilaga KeyControl Felsökning

Föreläsning 6: Introduktion av listor

Sharpdesk V3.3. Installationsguide Version

Cacheprobe: programbibliotek för extrahering av cacheminnesparametrar

Multi-ported cache En rapport om några lösningar till att få flera minnesaccesser simultant.

Operativsystem och användargränssnitt

Definition DVG A06. Varför operativsystem? Operativsystem. Översikt. - Vad är ett operativsystem?

Ekvivalensrelationer

Laboration 2 Datorverktyg vid LiU

Manual för Typo3 version 4.2

Operativsystem Introduktion

Se till att posten är i Ändringsläge. Gå till rullgardinsmenyn under Föremål och välj Lägg in bild.

Den här texten ska förhoppningsvis underlätta en del av anpassningarna. Det kan säkert finnas en del fel och annat tok.

Operativsystem - input/output, skydd, virtualisering

Uppgift 1 ( Betyg 3 uppgift )

Transkript:

Filsystem JFFS (Journaling Flash File System) Ett kapitel för kursen Wearable Computers D 10 p Namn: Jani Koljonen Användarnamn: da99jkn Datum: 021105 Handledare: Lars Karlsson Björne Lindberg Ulf Brydsten

Innehållsförteckning Allmänt om filsystem... 3 Begreppet fil... 3 Filattribut... 3 Ett allmänt filsystem... 3 Filsystemets organisation... 3 JFFS Journaling Flash File System... 5 Introduktion... 5 Flash... 6 Lagringsformat... 6 Designen: raw inode... 8 Funktion... 10 Garbage Collection... 10 Problem och lösningar (JFFS2)... 10 JFFS2... 11 Förbättringar sen version 1... 11 Nodformat och kompatibilitet... 11 Loggens Layout och blocklistor... 12 Nodtyper... 13 Installation (mounting)... 16 Garbage Collection... 16 Utveckling av JFFS2... 16 Förbättrad feltolerans... 17 Mer utrymme för Garbage Collection... 17 Slutord... 17 Källförteckning... 17 2

Allmänt om filsystem Begreppet fil En dator kan lagra information på olika lagringsmedia så som hårddisk, cd-rom, ram, flash, etc. För att hantera information som lagras på olika enheter, använder datorns operativsystem enhetens fysiska egenskaper för att definiera en logisk lagringsenhet, nämligen filen. Filer mappas av operativsystemet till fysiska enheter. Dessa enheter är ofta s.k. nonvolatile (stabila) och medför att innehållet kvarstår även vid strömavbrott och rebooting (återstart) av systemet. Data kan inte skrivas till en sekundär lagringsenhet utan att det är inom en fil. Filer representerar ofta program eller data. En datafil kan vara numerisk, alfabetisk, alfanumerisk eller binär. Filattribut En fil har ett antal attribut som varierar från ett OS till ett annat. Men några typiska är: Namn: Ett symboliskt namn för att användaren ska kunna få information om filen. Typ: Används av de system som stödjer olika filtyper. Plats: Består av en pekare som anger läget för filen. Var filen finns. Storlek: Filens nuvarande storlek (anges i bytes, words eller blocks) och eventuellt den maximala storleken som tillåts för denna filtyp. Rättigheter (protection): Anger vem/vilka som har rättigheter till använding av filen. Skriv/läs/kör/öppna. Tid/datum/ och användaridentifikation: Attributet används för att lagra information om filens: skapelse, senaste modifikation och senaste användningen. Ett allmänt filsystem För att skriva allmänt om ett filsystem är det bäst att skriva om filsystem till en hårddisk, eftersom den är det vanligaste lagringsenheten i nuvarande datorer. Informationen som finns på lagringsenheten, t ex hårddisken, är uppdelade i s.k. blocks. Varje block består i sin tur av en eller flera sektorer (sectors). Sektorerna varierar från mellan 32 bytes till 4096 bytes, beroende på lagringsenheten. Vanligast är 512 byte per sektor. Hårddiskar är ett mycket bra media för lagring av multipla filer p g a av följande: 1. De kan skrivas över på samma ställe flera gånger. Ett block kan läsas, modifieras och skrivas tillbaka till samma ställe. 2. Det går att komma åt vilket givet block med information som helst, d v s det är enkelt att komma åt vilken fil som helst antingen sekventiellt eller slumpmässigt. Att byta mellan två filer kräver bara flyttning av läs- och skrivhuvuden och låta disken rotera. Filsystemets organisation För åtkomst av information på lagringsenheten tillhandahåller OS:et ett filsystem för att hantering av lagring och lokalisering ska fungera lätt. Filsystemet i sig självt är generellt uppbyggt av flera olika nivåer. Figuren nedan (Figur 1) visar strukturen på ett lager-designatfilsystem (layered design). 3

Application programs Logical file system File-orqanization module Basic file system I/O control Devices Figur1: strukturen på ett lager-designat-filsystem (layered design). Varje nivå i designen använder sig av funktioner från lagret under för att skapa nya funktioner, som i sin tur används av lagret ovanför. Det lägsta lagret, I/O control- lagret består av drivrutiner (device drivers) samt interrupt hanterare för att skicka information mellan minne och enheten. Nästa lager, basic file system, utför generella kommandon till den rätta drivrutinen för att läsa och skriva fysiska blocks till enheten. File-organization module-lagret (filorganisationsmodul) känner till filer och deras logiska och fysiska blocks. Genom att veta typen av filtilldelning som används samt filens position kan lagret översätta logiska block-adresser till fysiska block-adresser för att sedan transporteras av basic file system. Varje fils logiska block är numrerat från 0 (eller 1) till N. Eftersom de fysiska blocken, som innehåller datat, ofta inte överensstämmer med de logiska numrena behövs en översättning för att lokalisera varje block. File-organization-module inkluderar också en free-space-manager som söker icke tilldelade blocks och tillhandahåller dessa till file-organization-module när det behövs. Sista lagret består av logical file system (logiska filsystemet). Det använder katalogstrukturen, (katalogstrukturen består av information om filer, så som namn, position, storlek och typ, som tillhör den aktuella partitionen), till att förse file-organization-module med information som den behöver. Detta genom att den ges ett symboliskt filnamn. Det logiska filsystemet har också ansvaret för säkerhet och skydd av systemet. När ett applikationsprogram vill skapa en fil anropar programmet det logiska filsystemet, som vet vilket format katalogstrukturerna har. För att skapa en ny fil, läser det den gällande katalogstrukturen in i minnet, uppdaterar den med dess nya entry och skriver tillbaka den till disken. Vissa operativsystem, Unix inkluderat, behandlar en katalog som en fil. Andra operativsystem, så som Windows NT, implementerar separata systemanrop för filer och kataloger och behandlar kataloger som enheter separerade från filer. När en katalog behandlas 4

som en speciell typ av fil, kan det logiska filsystemet anropa file-organization module för att mappa katalog I/O till disk-block-nummer. Dessa skickas sedan till basic file system lagret och I/O control lagret. Nu när en fil har skapats kan den användas för I/O. För varje I/O operation kan katalogstrukturen användas för att söka efter filen, dess parametrar kontrolleras, dess datablock lokaliseras och sedan kan operationer utföras på dessa datablock. Men innan filen kan användas för I/O procedurer måste den öppnas. När en fil öppnas söks katalogstrukturen genom för det sökta file entry (där filen ska sättas in i katalogstrukturen). När filen har hittats kopieras information så som storlek, ägare, rättigheter och datablockpositioner till en open file tabell i minnet. Tabellen innehåller information om alla nuvarande öppna filer i systemet. Första referensen till en fil (normalt en open) orsakar en sökning genom katalogstrukturen och positionen för filen kopieras till open file tabellen. Tabellens index returneras till användarprogrammet och alla efterföljande referenser görs via indexet istället för via ett symboliskt namn. Namnet som ges till indexet varierar. I Unix kallas de för file descriptors, i Windows NT för file handles och i andra system för file control block. Så länge en fil inte är stängd sköts alla filoperationer av open file tabellen. När filen är stängd av alla användare som öppnat den, kopieras den uppdaterade filinformationen tillbaka till katalogstrukturen. Vissa system använder sig av multipla nivåer av in-memory (i minnet) tabeller. I t ex BSD Unix filsystem har varje process en open file tabell som innehåller en lista av pekare, som är indexerade av en deskriptor. Pekarna i sin tur pekar på en open tabell som sträcker sig över hela systemet. Denna tabell innehåller information om den underliggande enheten som är öppen. För filer pekar den på en tabell av aktiva inoder. För andra enheter så som nätverksanslutningar och logiska enheter, pekar den på liknande accessinformation. Den aktiva-inoder tabellen är en in-memory cache av inoder som används för nuvarande och inkluderar inod-indexfältet som pekar på datablocken på disken. På detta sätt kommer alla andra datablock förutom det aktuella att vara i minnet för snabb access för en process som försöker komma åt filen. JFFS Journaling Flash File System Introduktion JFFS (Journaling Flash File System) är ett filsystem som är utvecklat av Axis Communications AB. Det är ett filsystem speciellt framställt för flash minnen och ska också klara av strömavbrott och dylikt. Alltså ett filsystem som passar små inbyggda system eller wearable computers. JFFS finns för nuvarande bara implementerat för Linux operativsystem och fungerar bra tillsammans med Linux existerande filsystem. En skillnad mellan JFFS och ett vanligt filsystem som arbetar mot hårdvara är att JFFS inte använder sig av buffrad cache. Se figur nedan (Figur 2). 5

Figur 2: En skillnad mellan ett vanligt filsystem och JFFS är att JFFS inte använder sig av buffrad cache. Flash Flash-minne är uppdelat i block som ofta är 128 KiB (KibiByte, står för att det verkligen är binärt 1024) stora. Minnet fungerar så att varje bit sätts till en logisk etta och sätts till en nolla vid en skrivoperation. Att sätta tillbaka en bit från en nolla (radera) till en etta kan inte ske enskilt, utan då måste ett helt block sättas till ettor (raderas). Ett flashminne har därför en livslängd som är beräknat på dessa raderingscykler. Vanligtvis kan ett flashminne raderas 100 000 ggr per block. För att försäkra att inte radering av ett block överskrider denna gräns före resten av blocken på minnet, försöker man se till att raderingscykler är jämt fördelade över flashminnet. Denna procedur kallas för wear levelling. Lagringsformat JFFS är ett rent log-strukturerat filsystem. Noder med data och metadata lagras på flashminnet i sekvens, d v s i följd, genom lagringsutrymmet som är tillgängligt. JFFS består bara av en typ av nod, nämligen en datastruktur vid namn jffs_raw_inode. Varje sådan nod är associerad med en inod. Varje nod innehåller en header som i sin tur innehåller information så som inod-numret till inoden som den tillhör samt metadata för inoden. För att hålla reda på alla lika noder som tillhör samma inod finns det ett versionsnummer lagrat i varje nod. Versionsnumret ökar för varje ny nod så att varje versionsnummer blir unikt. Versionsnumret är av typen unsigned 32-bit. Detta innebär att ca 4 miljarder noder kan skapas för varje inod under filsystemets livscykel. Detta är acceptabelt då flashminnen har en begränsad livslängd då det gäller skrivning av data. Inod-numret är på liknande sätt lagrat i ett 32-bitars fält men blir däremot aldrig återanvänt. 6

Förutom det vanliga inod metadatat så som userid, groupid, mtime etc, innehåller varje raw_node också information om vilken inod den tillhör och inodens förälders inod-nummer. Varje nod kan också innehålla en mängd data och i detta fall sparar noden filens offset för att veta var detta data är placerat. Eftersom de fysiska noderna är begränsade i storlek har stora filer flera noder associerade till dem, där varje nod har data för områden i olika delar av filen. Noder som innehåller data för ett område i en inod som också omfattar en senare nod, samt noder utan data, kallas för obsoleted (föråldrad) nod. I noder utan data har metadatat blivit uppdaterat av en senare nod. Dessa utrymmen som bildas av just obsoleted nodes kallas för dirty space (smutsigt utrymme). Denna information finns i speciella inoder så som character eller block device och symboliska länkar. Dessa inoder kan bara ha en icke föråldrad (nonobsolete) nod var. Radering av inoder sker på så sätt att en deleted (raderad) flagga sätts i metadatat. Alla senare noder med association till denna inod markeras med samma flagga och när den sista delen av filen som påverkas av inoden är stängd, blir alla noder obsolete. JFFS kan ses som en cirkulär fil som blir skriven på i slutet, läses från vilket ställe som helst och raderas eller skräpsamlas från början. Detta åskådliggörs av figuren nedan (Figur 3). Denna cirkulära fil kan betraktas som lagring av modifikationer till filer och kataloger. Figur3 visar organisationen av JFFS och föreställer en fil som växer och minskar växelvis i början och slutet. De mörka partierna föreställer skräp och resten data. När JFFS filsystemet ska installeras på flashen skapas först en image som sedan kopieras till flash-minnet. Ett flash-minne med ett rent JFFS filsystem visas på bilden nedan (Figur 4). De gråa partierna visar var filsystemets olika noder finns. Ett nyinstallerat system innehåller inget skräp. Figur 4: Ett nyinstallerat JFFS innehåller inget skräp 7

Efter en viss tids användning av filsystemet kan flash-enheten se ut på följande sätt (Figur 5), där det svarta är skräpdata d v s data som inte längre används. Figur 5: Filsystemet efter en tids användning. De svarta partierna är skräpdata. När en markant mängd av flash-minnet innehåller skräpdata kan en Garbage collect (skräpinsamling) genomföras. GC:n kör alltid framifrån och bakåt och detta betyder att skräp som finns i mitten av flashen inte kan raderas. I figuren nedan (Figur 6) har en viss mängd skräp raderats och en viss mängd noder skrivits om. Mer om Garbage Collection längre fram i texten. Figur 6: JFFS efter en Garbage Collection. Giltiga noder flyttas från början till slutet tills ett helt block kan raderas. Det vita är tomt utrymme. Designen: raw inode Den grundläggande datastrukturen som används vid datalagring på flash-enheten är struct jffs_raw_inode-datatypen. En ny raw inode struct skrivs för varje modifikation som görs på en fil eller katalog i filsystemet. Den innehåller all information som behövs för att bygga filsystemet och för att hålla reda på hur olika filer är uppbyggda. Eftersom flashminnen är relativt små och utrymme är en avgörande faktor, måste denna struktur vara liten. Dess storlek är 60 bytes. Se bild nedan (Figur 7). Figur 7: JFFS grundläggande datastruktur, jffs_raw_inode. 8

En förklaring till de olika delarna i jffs_raw_inode struct: Magic innehåller en konstant 0x34383931. Den är nödvändig för att det ska gå att detektera om en raw inode har påträffats under initieringsskanningen av flashen. 0x34383931 är samma som strängen 1984. Ino lagrar filens inod-nummer. Varje fil har ett visst inod-nummer associerad till sig. Varje fil har ett unikt inod-nummer. Pino håller reda på inod-numret till förälderfilen, som är en katalog. Om filen flyttas från en katalog till en annan kan pinofältets innehåll ändras. Versionfältet innehåller raw inodens versionsnummer. En ny raw_inode struktur med ett utökat versionsnummer skrivs till flash-minnet för varje ny modifikation av filen (rename, append, truncation, mm). Versionsnumret är en 32-bitars integer och begränsar därför antalet modifikationer till 32 upphöjt med 2 minus 1. Mode innehåller filaccess-rättigheter och filens typ. Denna är likadan som finns i linux egna struct inod. Uid och gid är standard användar- och grupp-id-nummer. Atime är ett fält med datum för senaste access. Mtime fältet har datum för senaste ändring av filens innehåll. Ctime innehåller senaste ändringen av inoden. Offset, dsize och rsize är relaterade till varandra. De har att göra med hur det skrivna datat ska läggas till filen. De tillgängliga operationerna är truncation (trunkering), append (lägga till), rewrite, write, cut och paste. Offset fältet innehåller positionen där alla ändringar som inoden gör ska ske. Dsize ger information hur mycket som skrivs efter denna raw inod. Rsize visar hur mycket data som ska exkluderas från offset-positionen. Med dessa tre värden kan många operationer utföras. Om t ex en append på 340 bytes görs till en fil med storleken 4681 bytes, skulle offset fältet vara 4681 och dsize 430. Rsize värde ignoreras i detta fall. Om istället en truncate görs på en fil med storlek 1402 bytes så att den blir 400 bytes, skulle offset fältet vara 400, dsize 0 och rsize 1402-400 = 1002. Nsize har hand om filnamnets längd. Nsize kan ha värden mellan 0 254. Nlink håller reda på hur många länka det finns till filen. (Används ej ännu.) Spare används inte än i denna version. Om rename är ett-ställd visar den att denna fil är involverad i en slags namnbytes-operation som innefattar identiska filnamn. Deleted visar om hela filen har blivit raderad. Accurate används till att göra raw inoder förlegade (obsolete). Om värdet är 0xff, är inoden accurate och om noll, obsolete. Om en raw inod är obsolete hoppas resten av innehållet över vid skanning av flashen. Det associerade utrymmet i flashen markeras som skräp. Dchksum innehåller checksumman av det data som hör till denna raw inod. Nchksum innehåller checksumman av namnet på filen som hör till denna raw inod. Chksum innehåller checksumman av själva raw inoden. 9

Funktion Hela mediet (flashen) scannas vid start (mount) och varje nod läses och tyds. Datat som finns lagrat i raw_nodes innehåller information för att bygga hela kataloghierarkin. Dessutom finns en komplett karta över varje inod i den fysiska platsen på flashen över varje område av data. JFFS lagrar all denna information under hela tiden filsystemet mountas. Läsning av filer kan utfärdas genom att de läses direkt från gällande positioner från flash-minnet till en buffert. Ändring av metadatat så som rättigheter och användare görs genom att en ny nod skrivs till slutet av loggen. På liknande sätt sker skrivning av filer, förutom att noden som skrivs till också har data associerat till sig. Garbage Collection Vad händer då utrymmet på mediet blir fullt? Eftersom JFFS hela tiden skriver ut nya jffs_raw_inode strukturer till flashen varje gång nya ändringar görs på filsystemet, måste flashen till slut bli fullproppad. Därför behövs det en mekanism för att hantera det dirty space som innehåller gamla noder som blivit föråldrade (obsoleted) av senare data. JFFS har därför en Garbage Collector (skräpsamlare) som tar hand om gamla noder. Den äldsta noden finns i loggens head (huvud) och nya noder i loggens tail (svans). I ett rent filsystem där garbage collection aldrig körts finns loggens huvud i början av flashen. När svansen närmar sig slutet av flashen startas garbage collection för att göra mer utrymme tillgängligt. Garbage collection startas antingen som en kernel thread (process i kärnan) och försöker göra rent i förebyggande syfte, d v s innan rensning egentligen behövs, eller som en user process (process i användardelen) som letar och gör utrymme tillgängligt på flashen för skrivning. I båda fallen fortsätter GC att köra bara om det finns något dirty space tillgängligt. Om det inte finns tillräckligt med dirty space för att en GC kan ordna mer ledigt utrymme på flashen försätter processen i kärnan sig själv till sleep (sovläge). I detta fall kan man inte skriva till flashen, utan det blir ett ENOSPC fel. GC:s mål är att radera första blocket ur loggen. Vid varje körning undersöks loggens huvud och om noden är föråldrad, hoppas den över och huvudet flyttas till nästa nod. Om noden å andra sidan är giltig så måste den tvingas att bli föråldrad. Detta åstadkommes genom att GC:n skriver ut nytt data eller metadata till loggens svans. Den nyskrivna noden innehåller data för åtminstone original-nodens område och om det finns utrymme, kan GC koden skriva en större nod än den som blivit föråldrad. Detta för att förbättra förvaringskapaciteten genom att förena flera små noder till färre, större noder. När ett helt block är tvingat att bli föråldrat kan det raderas och bli tillgängligt i loggens svansdel. Problem och lösningar (JFFS2) För att GC:n alltid ska kunna starta och skriva ut nya noder, kräver filsystemet en viss mängd utrymme mellan huvudet och svansen i loggen. Närmare förklarat betyder detta följande: För att nästa block ska kunna raderas från huvudet i loggen, måste det finnas tillräckligt med utrymme tillgängligt för att skriva dit nya noder. Dessa noder i sin tur gör alla tidigare noder i blocket föråldrade. Det värsta tänkbara fallet är då alla noder i blocket är giltiga samt att den första noden startar precis i början av blocket och den sista precis innan slutet av blocket och når vidare till nästa. 10

En lösning till detta är att begränsa maximala nod-storleken till halva flash-raderings-sektorn (flash erase sector). Metoden är implementerad på filsystemet och begränsar mängden utrymme som behövs för värsta-fall-scenariot med upp till en och en halv ggr flashsektorernas storlek. Egentligen är inte mängden utrymme som behövs för att GC:n ska kunna fortsätta köra bevisad till något exakt. Allmänna försök har dock visat att värdet av fyra flash-sektorer borde vara tillräckligt, medan det tidigare default-värdet på två flash-sektorer skulle kunna försätta filsystemet i dödläge. Detta genom att loggens svans når loggens huvud. Även om designen på JFFS är imponerande så har vidare testresultat fört fram ytterligare ett antal nackdelar med filsystemet, vissa av dem rätt allvarliga: Garbage Collection GC:n kör linjärt genom hela mediet och skriver ut nya noder för att kunna radera den äldsta blocken ur loggen. Den gör detta även om det äldsta blocket bara innehåller rena noder. Som ett exempel: Om ett 16 MiB:s (MebiByte) system innehåller 12 MiB med kataloger och exekverbara program (statiskt data), 2 MiB löst utrymme och 2 Mib dynamiskt data, skulle GC:n flytta dessa 12 Mib statiskt data från ett ställe till ett annat på flashen vid varje körning genom mediet. JFFS har en perfekt wear-levelling som ser till att varje block raderas exakt lika många gånger. Men detta betyder också att blocken raderas oftare än nödvändigt. Wear-levelling måste tillhandahållas, genom att ett rent block väljs och dess innehåll flyttas. Men detta ska inte ske som en standard utan vid vissa tidpunkter. Komprimering Komprimering stöds inte av JFFS vilket skulle vara av stor vikt eftersom flash-minne är dyrt och kravet på att mer och mer information ska rymmas på det. Hårda länkar Hårda länkar stöds inte heller och innebär bl a att t ex filnamn är lagrade i varje jffs_raw_node och betyder att om ett filnamn ändras, ökar filens längd som i sin tur minskar ledigt utrymme. JFFS2 I januari 2001 påbörjades utvecklingen av JFFS2 efter att kunder bl a velat ha ett filsystem med stöd för komprimering. JFFS2 är en vidareutveckling av JFFS. Version 2 är utvecklat av redhat och fungerar under linux kernel 2.4. Filsystemet är också tänkt att kunna portas speciellt till ecos (embedded Configurable operating system) i framtiden. Förbättringar sen version 1 Nodformat och kompatibilitet Till skillnad från version 1 som bara hade en typ av noder på mediet, är JFFS2 mer flexibelt. Det tillåter nya typer av noder att bli definierade samtidigt som det är bakåtkompatibelt genom användning av liknande kompatibilitets-bitmaskar som används av ext2 filsystemet. 11

Varje typ av nod börjar med en allmän header innehållandes nodens längd, typ och en CRC (cyclic redundancy cheksum). Den allmänna nodstrukturen visas i figuren nedan (Figur 8): Figur 8: Den allmänna nodstrukturen. Förutom ett unikt värde som identifierar nodstrukturen, innehåller nodtyp-fältet en bitmask i de två mest signifikanta bitarna vilken indikerar egenskaperna hos noden. Bitmasken används av en kernel för att få information om den aktuella nodtypen om den inte har stöd för den: JFFS2_FEATURE_INCOMPAT Om implementationen stöter på en nod med denna mask, betyder det att noden inte stöds explicit och en JFFS2 implementation måste vägra utföra en mount av filsystemet. JFFS2_FEATURE_ROCOMPAT En nod med denna mask kan ignoreras av implementationen som inte stöder detta, men filsystemet kan inte skrivas till. JFFS2_FEATURE_RWCOMPAT_DELETE Samma som ovan fast filsystemet kan skrivas till. Vid garbage collection av sektorn med denna nod i, ska noden raderas. JFFS2_FEATURE_RWCOMPAT_COPY Som ovan fast vid garbage collection ska noden kopieras till ett annat ställe i mediet. Loggens Layout och blocklistor Förutom skillnader på de individuella noderna, har själva layouten på loggen till JFFS2 ändrats från det cirkulära log-formatet för att det skapade problemet att GC:n körde linjärt. JFFS2 behandlar istället varje block som ska raderas individuellt och noder får inte överlappa rader-blockens gränser så som de gjorde i version 1. Det här betyder att GC:n kan jobba med ökad effektivitet genom att samla skräp från ett block i taget samt att kunna avgöra vilket block som ska samlas från härnäst. Varje rader-block kan vara i ett av många stadier, beroende på dess innehåll. JFFS2 koden håller reda på varje rader-block genom ett antal länkade listor med strukturer som representerar olika block. Under en normal körning av ett JFFS2 system kommer majoriteten av rader-blocken vara i clean_list (ren lista) eller i dirty_list (smutsig lista). Dessa 12

representerar block som är fulla av giltiga noder och block som innehåller minst en gammal (obsoleted) nod. I ett nyinstallerat filsystem kan många rader-block finnas på free_list (ledig lista) och innehåller då bara en giltig nod. Noden är en markör för att visa att blocket har raderats helt och korrekt. En metod som GC:n kan använda sig av för att avgöra vilket block som ska tas omhand härnäst baseras på jiffies räknaren: Om jiffies % (modulo) 100 inte är lika med noll, väljs ett block från dirty_list. I fall det, i ett fall på hundra, är lika med noll, väljs ett block från clean_list. Med hjälp av det här optimeras GC:n att återanvända block som redan är delvis föråldrade. Men data kommer ändå att flyttas runt i mediet tillräckligt för att försäkra att inte något block ska nötas ut innan de andra (wearlevelling). Nodtyper Den tredje stora förändringen sen version 1 är separeringen av directory entries och inoder, som medför att JFFS2 kan hantera hårda länkar och eliminerar problemet med ändring av filnamn. Det finns tre olika typer av noder som är definierade och implementerade av JFFS2: JFFS2_NODETYPE_INODE Den här noden är mest lik strukturen jffs_raw_inode från version 1. Den innehåller all inodmetadata samt en rad data tillhörande inoden. Den innehåller dock inte längre ett filnamn eller numret till sin nod-förälder (parent node). Istället är inoderna, i likhet med traditionella UNIX-liknande-filsystem, distinkta enheter av directory entries. En inod tas bort när den sista directory entry som refererar till den, avlänkas (unlink) och inga öppna fildeskriptorer till den existerar. Det data som tillhör dessa noder kan komprimeras genom att använda någon av de många komprimeringsalgoritmer som kan pluggas in i JFFS2 koden. De enklaste typerna är none (inga) och zero (noll), som betyder att data inte är komprimerat eller att all data är lika med noll. Två komprimeringsalgoritmer är utvecklade speciellt för JFFS2, men även t ex zlib komprimering kan inkluderas till JFFS2 koden. För att kunna utföra snabb komprimering av data vid en readpage() request, innehåller noderna inte mer än en sida data i enlighet med hårdvarans sidstorlek på plattformen. Portabilitet på JFFS2 mellan olika plattformar saknas därför i vissa fall, men detta spelar inte så stor roll eftersom förflyttning flash-minnen emellan är föga troligt. JFFS2_NODETYPE_DIRENT Den här noden representerar en directory entry, eller en länk till en inod. Den innehåller inodnumret till katalogen där länken finns, länkens namn och inod-numret till inoden som länken refererar till. Versionsnumret i en dirent nod är i samma sekvens som dess förälder-inod. En länk kan tas bort genom att skriva en dirent nod med samma namn men med inod-nummer noll och ett högre versionsnummer. POSIX (Portable Operating System Interface) kräver att när ett filnamn ska ändras måste bytet av länken vara atomisk. Det betyder att det inte ska kunna misslyckas att returnera en 13

gammal eller en ny länk. JFFS2 uppfyller detta krav, men som så många andra filsystem, är inte hela namnändringsproceduren atomisk. Ändring av namn sker i två steg. Först skrivs en ny dirent nod med nya namnet och numret på den inod som håller på att ändras. Det ersätter atomiskt länken till original-inoden med den nya och är identiskt med sättet som en hård länk skapas. Sen avlänkas originalnamnet genom att en dirent nod med originalnamnet och mål-inodnumret noll. Denna tvåstegsprocess medför att under en viss tidpunkt kommer inoden, som håller på att bli ändrad, vara tillgänglig via både de gamla och nya namnen. Detta beteende accepteras av POSIX eftersom kravet för att vara atomiskt bara är för mål-länken. JFFS2_NODETYPE_CLEANMARKER Cleanmarker är en nod som skrivs till ett nyligt raderat block för att visa att operationen är korrekt slutförd och att blocket kan säkert användas för lagring. Version 1 av JFFS förmodade att vilket block som helst som innehöll 0xFF i varje byte vid första skanningen var ledigt. Efter omfattande tester med strömavbrott visade sig detta vara oklokt. För många typer av flash-minnen betyder ett strömavbrott under en radering att några bitar kan hamna i instabilt tillstånd. Däribland de flesta blir återställda till ettor. Om det under initialiseringen råkar hända att ettor läses in och feltolkas så att ett block ses som ledigt, kan data gå förlorat. Resultat har visat att återläsning av hela blockets innehåll åtskilliga gånger, för att hitta instabila bitar, inte var tillräckligt pålitligt för att undvika dataförluster. Därför krävdes en alternativ lösning. Lösningen var att skriva markör-noden till flashblocket på en gång efter en framgångsrik raderingsoperation. När flash-block, som inte verkar innehålla några giltiga noder, hittas utlöser JFFS2 en raderingsoperation och skriver sekventiellt den rätta markör-noden till det raderade blocket. Den här nodtypen introducerades efter att JFFS2 börjades att användas i riktiga applikationer. Nodtypen använder sig av RWCOMPAT_DELETE bitmasken för att visa att en äldre JFFS2 implementation säkert kan ignorera noden. JFFS2 uppför sig i grundutförandet som version 1. Noder, som nu dock består av flera typer, skrivs sekventiellt tills blocket är fyllt och ett nytt block tas fram från free_list och skrivningen fortgår från början av det nya blocket. När utrymmet på free_list börjar bli minimal startar garbage collection och flyttar noder från ett äldre block till det nya blocket tills utrymme kan återvinnas genom att radera den gamla. Däremot håller inte JFFS2 all inod-information i kärnminnet hela tiden. Under mounten av filsystemet byggs hela kartan liksom förut, men strukturerna som hålls i minnet är strikt begränsade till att innehålla information som inte kan återskapas snabbt på beställning. För varje inod på mediet finns en struct jffs2_inode_cache. Strukturen lagrar inodens nummer, numret på nuvarande länkar till inoden och en pekare till början av en länkad lista bestående av de fysiska noderna som tillhör inoden. Dessa strukturer är lagrade i en hash-tabell, där varje del består av en länkad lista. Hash-funktionen är mycket enkel och består endast av inod-numret % (modulo) storleken av hash-tabellen. 14

Varje fysiska nod representeras av en mindre struct jffs2_raw_node_ref. Strukturen visas i bild nedan (Figur 9). Den innehåller två pekare till andra raw node referenser, nämligen den nästa i det fysiska raderingsblocket och nästa i per-inod listan samt fysiska offset och totala nod-längden. Eftersom antalet strukturer och den begränsade mängden RAM som finns tillgängligt på många system är denna struktur väldigt begränsad i storlek. Figur 9: struct jffs_raw_node_ref Eftersom alla noder på mediet är fyra bytes är de två minst signifikanta bitarna på flash_offset fältet redundanta. De är därför tillgängliga för att användas som extra flaggor. Den minst signifikanta biten sätts till ett för att markera att den nuvarande noden är en obsolete nod (gammal) och den andra används inte. För garbage collection är det nödvändigt att finna, genom att en raw nod referens getts, inoden som den tillhör. Företrädesvis adderas fyra bytes som innehåller denna information till varje sådan struktur. Istället för att ha en NULL-terminerad länkad lista för next_in_ino listan, innehåller raw nod referensen en pekare till struct jffs2_inode_cache för den relevanta inoden. Om struct jffs2_raw_node_ref pekar på NULL i jfss2_inode_cache, vet den traverserande GC:n att den är i slutet och pekaren kan göras om till den rätta typen så att inod-numret och annan information kan kommas åt från strukturen. Null fältet som syns i inod cache strukturen används bara under initialiseringen och skanningen av filsystemet för temporär lagring och är garanterat NULL under normal körning. 15

Under normal körning skickas ett inod-nummer till filsystemets read_inode() metod och förväntas att förse en inod-struktur med information. JFFS2 använder sig av inod-numret för att söka den rätta struct jffs2_inode_cache hash-tabellen. Sedan använder den listan av noder för att direkt läsa varje nod som tillhör den inod som krävs. På detta sätt byggs en komplett karta på de fysiska platserna för varje inods dataområde upp. Liknande information som skulle ha lagrats i minnet av JFFS även fast det inte skulle användas. När inod-strukturen är fylld, stannar den i minnet tills kärnan försöker rensa inod-cachen. Då rensas information och kvar lämnas bara raw nod referensen och JFFS2 inod cache strukturen. Detta händer när kärnan får dåligt med minnesutrymme. Installation (mounting) Installationen av JFSS2 filsystemet sker i fyra steg: Det fysiska mediet skannas. Nodernas CRC kontrolleras om de är giltiga samt att raw nod referenserna allokeras. Inod cache strukturerna allokeras också och läggs in i hash-tabellen för varje inod som en giltig nod hittas. Extrainformation från noderna cachas, så som version och dataområdet i noden för att förhindra att kommande steg av installationsprocessen måste läsa om allting igen. Efter den fysiska skanningen görs en check genom alla fysiska noder. En karta över data för varje inod byggs för att föråldrade noder kan raderas. Dessutom ökas nlänkfältet (nlink field) i inod-cachen för den länkade inoden för varje giltig directory entry nod. En andra check görs för att ta reda på inoder som inte har några kvarvarande länkar och raderas. Varje gång en directory inod raderas, startar checken om eftersom andra inoder kan ha blivit föräldralösa. En tredje check görs för att frigöra den temporära informationen som cachades för varje inod. Detta gör så att bara information som normalt ska finnas i struct jffs2_inode_cache under körning finns kvar. Genom att detta görs kommer inod cachen som motsvarar next_in_ino fältet i raw nod referensen att sättas till NULL och därmed går det att detektera slutet av next_in_ino listan. Garbage Collection GC:n I JFFS2 flyttar datanoder genom att bestämma den inod för vilken noden som ska skräpsamlas tillhör. Detta åstadkoms genom anrop till linux-kärnans iget() funktion. Inoden finns ofta i kärnans inod-cache, men kan ibland orsaka ett anrop till JFFS2:s read_inode(). När inod-strukturen blivit full kan en ersättningsnod skrivas för att göra originalnoden obsolete (föråldrad). Om denna nod var en datanod, anropar GC funktionen readpage() för den sida (page) som noden innehåller data. Efter det komprimeras så mycket av sidan som möjligt om och skrivs ut i en ny nod. Om noden som ska skräpsamlas är liten och det inte finns tillräckligt med fritt utrymme för skrivning av hela sidan, eller om sidan som ska skräpsamlas är i slutet av inoden kan en del av sidan skrivas på. Utveckling av JFFS2 En ofta förfrågad ändring i egenskap till JFFS2, som inte är planerad att implementeras, är execute In Place (XIP). När program körs i JFFS2, kopieras den exekverbara koden från flash till RAM innan processorn kan exekvera det. Åtkomst av data sker på liknande sätt inte direkt 16

från flash utan kopieras till RAM vid behov. XIP och komprimering av data motverkar uppenbarligen varandra eftersom komprimering kräver att datat packas upp innan det körs. Vid användning av XIP kan man halvera mängden RAM och vid komprimering halvera mängden flash. Därför är komprimering ett bättre val ur ekonomisk synvinkel, eftersom flash är dyrare än RAM. Förbättrad feltolerans JFFS2 behöver förbättras med anseende på feltoleransen. Det behövs mer sofistikerade metoder för att hantera single-bit errors i flash-minnen. För tillfället innehåller noden en 32 bitars CRC, men denna ger bara ett fel hittat och ger inte filsystemet tillfälle att ordna felen. För arbete med t ex NAND flash är korrektion ett måste och är även att föredra för NOR flash. JFFS2 har redan en enkel metod för att hantera block som har fått ett fel från drivrutinen. Metoden lägger ut dem på en separat bad_list och vägrar att använda dem igen förrän nästa gång filsystemet installeras (mountas) om. Metoden behöver utvecklas vidare. Mer utrymme för Garbage Collection En stor nackdel i JFFS2 är mängden utrymme som behövs för GC:n. I väntan på en algoritm som visar exakta mängden som behövs, måste fem fulla raderingsblock vara tillgängliga för skrivning innan nya skrivningar tillåts av användarutrymmet. Det borde vara möjligt att reducera den summan till ett block för NOR- och tre för NAND-flash, där extrautrymme alltid måste vara tillgängligt för att kopiera bort data från felaktiga block. Slutord Sammanfattningsvis går det att säga att filsystem för flash-minnen befinner sig i ett tidigt stadium och det finns mycket utrymme för vidare utveckling. Men i det stora hela är JFFS ett mycket passande filsystem för t ex wearable computers, som använder sig av flash-minnen som lagringsmedia. Några av de största anledningarna till det är att JFFS är just ett journaling flash file system som är logstrukturerat, opererar direkt på flashen och har wear-levelling. Att det är logstrukturerat innebär att information för varje transaktion sparas undan på en log och medför att filsystemet lätt kan rekonstruera sig själv vid t ex strömavbrott. Källförteckning Operating system concepts fifth edition: Silberschatz, Galvin. http://developer.axis.com/software/jffs/doc/jffs.html Axis Communications AB. http://sources.redhat.com/jffs2/ David Woodhouse, Redhat. 17