Journalling Flash File System version 2 lubJFFS2 (nie mylić zsystemem plików JFS) –system plików o strukturze dziennika używany w urządzeniach zpamięcią Flash. Jest następcą systemu plikówJFFS. JFFS2 został włączony do jądra systemuLinux od wydania 2.4.10. JFFS2 jest również dostępny wprogramach rozruchowycheCos, RTOS orazRedBoot.
JFFS2 posiada następujące cechy:
Podobnie jak w przypadku systemu plików JFFS, zmiany w plikach oraz katalogach są „logowane” w pamięci flash w postaci „węzłów”, przy czym w JFFS2 wyróżnia się ich trzy rodzaje:
I-węzeł jest usuwany, jeśli ostatni wpis w katalogu odnoszący się do i-węzła został odlinkowany (usunięty) oraz gdy zamknięte zostały wszystkie deskryptory odnoszące się do i-węzła.
Usunięcie dowiązania (wpisu w katalogu) polega na zapisaniu węzła typu JFFS2_NODETYPE_DIRENT z tą samą nazwą, co usuwane dowiązanie, lecz z numerem i-węzła, do którego odnosi się dowiązanie, równym zero (i zwiększonym polemversion).
Tutaj również, tak jak wJFFS, węzły rozpoczynają swój cykl życia jako „ważne”, po czym, gdy w innym miejscu powstanie nowsza ich wersja, zostają „unieważnione”.
W przeciwieństwie do JFFS, w JFFS2 nie ma koncepcji cyklicznego loga. W jego miejsce pojawiły siębloki, jednostki tych samych rozmiarów, co blok kasowania w pamięciach flash. Bloki są pojedynczo wypełniane i-węzlami, od dołu ku górze. Bloki są ze sobą powiązane w kilku listach:
W tle działagarbage collector, który, wykorzystując powyższe listy bloków, przekształca bloki „brudne” w bloki „wolne”. Robi to poprzez skopiowanie „ważnych” węzłów znajdujących się w „brudnych” blokach do nowych bloków, pomijając przy tym węzły „unieważnione”. Następnie oznacza „brudne” bloki w specjalny sposób tak, aby oznaczały bloki „wolne”, a następnie usuwa je (oznaczanie jest stosowane w celu uniknięcia problemów w przypadku, gdy podczas operacji usuwania zniknie zasilanie).
Garbage collector wyznacza blok do odśmiecenia na podstawie licznikajiffies: : jeśli jiffies % 100 (dzielenie modulo 100) da w wyniku wartość niezerową, odśmiecany jest blok z listydirty_list; gdy wynikiem jest zero, odśmiecany jest blok z listyclean_list. Jest to ważna optymalizacja: bloki z ważnymi węzłami nie są, jak w przypadku jffs, odśmiecane równie często, jak bloki, w których są zdezaktualizowane węzły, a jedynie w jednym przypadku na sto; ograniczona jest więc liczba niepotrzebnych operacji przepisywania danych z miejsca na miejsce na nośniku, a jednocześnie, dzięki występującemu od czasu do czasu wyborowi bloku z listyclean_list, zapewnione jest równoważenie zużycia nośnika.
Węzły zapisywane są po kolei do bieżącego bloku; gdy ten zostanie zapełniony, brany jest nowy blok z listyfree_list. Gdy na liście free_list zaczyna brakować bloków, włączany jest garbage collector, którego zadaniem jest przeniesienie ważnych węzłów ze starszego bloku do nowszego, co umożliwi wyczyszczenie starszego bloku i odzyskanie w ten sposób bloku do ponownego użycia. Węzły nie są przechowywane w pamięci przez cały czas; choć przy montowaniu budowana jest pełna mapa i-węzłów, to podczas działania modyfikowane są jedynie pewne struktury w pamięci (ograniczonych rozmiarów).
Dla każdego i-węzła na nośniku w pamięci przechowywana jest strukturastruct jffs2_inode_cache, która przechowuje:
Struktury te są przechowywane w tablicy haszującej o bardzo prostej funkcji haszującej (numer i-węzła dzielony modulo długość tablicy), dzięki czemu zapewniony jest równomierny rozkład tych struktur w tablicy .
Dla każdego węzła przechowywana jest w pamięci strukturajffs2_raw_node_ref, która przechowuje:
Garbage collector musi na podstawie strukturyjffs2_raw_node_ref odnaleźć i-węzeł, którego ta struktura dotyczy. Jest to możliwe dzięki temu, że na końcu listy wskaźników wskazujących na strukturyjffs2_raw_node_ref reprezentujące kolejne węzły odnoszące się do tego samego węzła, nie umieszczono wartości NULL wprost, tylko wskaźnik do struktury jffs2_inode_cache (reprezentującej szukany i-węzeł). Struktura ta, pod przesunięciem, pod którym kod przechodzący po strukturachjffs2_raw_node_ref spodziewałby się wskaźnika do kolejnej strukturyjffs2_raw_node_ref lub wartości NULL, posiada właśnie wartość NULL, dzięki czemu kod przeszukujący wie, że wystarczy zrzutować wskaźnik na odpowiedni typ (jffs2_inode_cache), by móc odczytać numer i-węzła i inne potrzebne dane.
W trakcie działania do metody systemu plikówread_inode() przekazywany jest numer i-węzła, w jej wyniku zaś zostaje wypełniona odpowiednimi informacjami struktura danychstruct inode. Odbywa się to w następujący sposób: