Zarządzanie mapą bitową zajętości bloków.
Michał Fiejka
1. Wstęp
Każda grupa posiada własną mapę bitową zajętości bloków w tej grupie. Mapa ta zajmuje dokładnie jeden blok. W szczególności oznacza to że rozmiar grupy, czyli ilość bloków w grupie jest ograniczona przez rozmiar bloku na dysku. Np. jeżeli przyjmiemy, że rozmiar bloku jest równy 2048 bajtów to oznacza, że w grupie może być co najwyżej 2048*8 bloków, czyli grupa jest rozmiaru 32 MB. Mapa bitowa znajduje się w grupie za blokami deskryptorów innych grup:
Z map bitowych zajętości bloków korzystają funkcje alokujące i dealokujące bloki na dysku, zdefiniowane w pliku balloc.c.
2. Zarządzanie
Istnieje funkcja ext2_check_block_bitmap sprawdzająca, czy informacje, które zawiera bitmapa są poprawne.
Nagłówek:
void ext2_check_blocks_bitmap (struct super_block * sb)
Funkcja ta wywoływana jest w chwili montowania systemu plików. Zakładamy, że super-blok jest zablokowany. Jako parametr, funkcja otrzymuje super-blok. W pętli dla każdej grupy sprawdza następujące rzeczy: czy w mapie tej grupy jest ustawiony bit dla super-bloku (pierwszy bit), bity odpowiadające blokom deskryptorów grup, bit odpowiadający blokowi mapy zajętości bitów, oraz bit odpowiadający blokowi mapy zajętości i-węzłów. Potem sprawdza, czy wszystkie używane bloki są odznaczone w mapie. Następnie zlicza wolne miejsce w bitmapie i porównuje je z wartością w deskryptorze grupy. Zlicza przy okazji wszystkie wolne bity we wszystkich grupach. Na koniec porównuje tę wartość z wartością przechowywaną w super-bloku.
Gdy któraś z wartości jest niezgodna, funkcja wywołuje ext2_error z odpowiednim komunikatem.
Istnieje również funkcja load_block_bitmap.
Nagłówek:
static inline int load_block_bitmap (struct super_block * sb, unsigned int block_group)
Korzystają z niej funkcje alokujące i dealokujące bloki. Jej zadaniem jest załadowanie do cache'u super-bloku, przekazywanego jako parametr, mapy bitowej grupy, do której należy ten super-blok. Wartością zwracaną jest numer slot'u w cache'u pod którym zapisana została mapa.
Funkcja ta w pierwszej kolejności sprawdza, czy to żądanie jest tym samym żądaniem co poprzednie i czy tamto się nie powiodło. Jeżeli tak to to żądanie również się nie powiedzie. Potem rozważamy przypadek kiedy mamy do czynienia z małym systemem plików - wtedy wszystkie bloki znajdują się w cache'u i wystarczy zwrócić ten numer który dostaliśmy. Jeżeli te próby się nie powiodą to wywołujemy funkcję __load_block_bitmap, i zwracamy to co od niej otrzymamy.
Nagłówek:
static int __load_block_bitmap (struct super_block * sb, unsigned int block_group)
Funkcja __load_block_bitmap otrzymuje jako parametry to samo co load_block_bitmap, czyli super-blok i numer bloku. Korzystamy tu z cache'u super-bloku jak z bufora na którym zaimplementowany jest algorytm LRU. Funkcja zwraca numer slot'u pod którym jest załadowany blok.
Dwie uwagi. Po pierwsze, dla każdego systemu plików istnieje oddzielny cache. Po drugie, dla odpowiednio małych systemów plików nie uruchamiamy algorytmu LRU (i tak wszystkie bloki mamy w cache'u).
Algorytm ten korzysta z funkcji read_block_bitmap. Dostaje ona super-blok, numer bloku do odczytania i numer slot'u, pod który ma wczytać blok. Do wczytania odpowiedniego bloku, wykorzystuje funkcję bread.