Do spisu treści tematu 6
 
 

6.4.4 Specyficzne dla ext2 funkcje zarządzania i-ramkami

 

Spis treści

    Skomentowany plik fs/ext2/inode.c
 

Wprowadzenie

    I-ramka ma za zadanie przechowywać informacje o i-węźle niezależnie od systemu plików, z którego korzystamy. Z tego wynika, że dla każdego systemu dostarczone muszą być funkcje działające na tych obszarach i-ramki, gdzie znajdują się informacje dla niego specyficzne.
    I tak dla odczytania i-węzła z dysku do odpowiedniego miejsca w pamięci - wyznaczonego przez i-ramkę - wykorzystujemy funkcję read_inode, dla zapisu zmienionego i-węzła na dysk uruchamiamy write_inode, żeby dowiedzieć się w którym miejscu na dysku znajduje się n-ty blok pliku wywołujemy funkcję bmap.
    Każda z tych funkcji jest specyficzna dla danego systemu plików, ponieważ musi brać pod uwagę konkretne fizyczne położenie danych na dysku. To położenie może być różne, a czasami nawet musi być takim z powodu różnic koncepcyjnych: np. fat i ext2.
    Te funkcje są oczywiście wysokopoziomowe - w zasadzie ich nazwy są tylko ujednoliconym interfejsem, pod który podstawiane są funkcje interesującego nas systemu. Dokładniej poprzez atrybuty i-ramki można uzyskać dostęp do wskaźników na funkcje wykonujące odpowiednie działania dla odpowiedniego systemu plików.
Przykład:
        Chcąc obliczyć fizyczny numer bloku na podstawie logicznego (algorytm bmap) - sprawdzamy, czy w operacjach na i-węźle zdefiniowanych w i-ramce jest podstawiona specyficzna dla danego systemu plików funkcja realizująca to działanie -  bmap, a następnie ją uruchamiamy i zapamiętujemy wynik. Ta specyficzna funkcja dla systemu ext2 będzie miała nazwę ext2_bmap, a podstawienie polega na przypisaniu polu bmap w odpowiedniej strukturze i-ramki, operacji wskaźnika na naszą funkcję - ext2_bmap.

    Tutaj zajmiemy się opisem funkcji realizujących przedstawione powyżej operacje w systemie ext2, zamieszczonych w pliku fs/ext2/inode.c (skomentowany kod) .
 


 Zapis i-węzła na dysk

    Operacja ta może zostać zrealizowana na dwa sposoby. Jeden z nich wymusza natychmiastowy zapis na dysk (ext2_sync_inode - skomentowany kod), drugi natomiast dopuszcza możliwość opóźnienia fizycznej zmiany na dysku (ext2_write_inode - skomentowany kod). Sposób realizacji obu powyższych funkcji jest na tyle podobny, że zdecydowano się zaimplementować funkcję ext2_update_inode (skomentowany kod), która wywoływana jest przez dwie wymienione wcześniej funkcje - oczywiście zaznaczające jednym parametrem (do_sync), o którą z nich chodzi.

    A oto jakie akcje są wykonywane przy żądaniu zapisu i-węzła:

   Najpierw sprawdzamy, czy i-węzeł do zapisu nie jest przypadkiem i-węzłem korzenia systemu plików, oraz czy jego numer jest poprawny; w  przypadku wykrycia jednej z tych sytuacji - powracamy nic nie robiąc.
    Następnie znajdujemy fizyczną lokalizację i-węzła na dysku, tzn. konkretny blok, w którym jest zapisany, wczytujemy ten blok, aktualizujemy go oraz zapisujemy z powrotem na dysk, żądając natychmiastowego zapisu, jeżeli synchronizacja jest wymuszona (do_sync=1).
    W przypadku, gdy nie udaje nam się odczytać i-węzła z dysku zwracamy błąd (EIO) oraz uznajemy obraz i-węzła w pamięci za zgodny z wersją dyskową.


Odczyt i-węzła z dysku

    Do odczytania i-węzła z dysku przeznaczona została funkcja ext2_read_inode (skomentowany kod), która dla fizycznego odczytu bloku i-węzła z dysku korzysta z ext2_bread (skomentowany kod).
    Jako, że cały dostęp do dysku jest buforowany istnieje konieczność skorzystania z bufora dla wyżej wspomnianego fizycznego odczytu - może się przecież okazać, że wcale nie trzeba sięgać do dysku jeżeli istnieje odpowiednio 'świeża' kopia tego bloku w pamięci - konkretnie istnieje jakiś bufor zawierający ten blok. Za odnalezienie tego bufora odpowiada funkcja ext2_getblk (skomentowany kod).

    Dla poprawy czytelności połączymy opis obu tych funkcji w jednym kawałku, zaznaczając jednakże granice

       na wstępie sprawdza się czy zadany i-węzeł możemy dostać,
       później oblicza się położenie na dysku ( nr grupy, nr bloku, przesunięcie w bloku )
    - ext2_bread (początek)
         wywołuje getblk z zadaniem znalezienia odpowiedniego bufora (dla grupy i bloku) ,
         jeżeli bufor zawiera aktualne dane to już OK
         wpp inicjuje czytanie danych z dysku do tego bufora
    - ext2_bread (koniec)
       a następnie ustawia sie pola w i-węźle na podstawie otrzymanego bufora
 


Zamiana logicznego numeru bloku na adres fizyczny (ext2_bmap)

Tutaj jest skomentowany kod

    Jeżeli chcemy odczytać z pliku bajt o określonym numerze - traktujemy plik jako nieprzerwany i ciągły strumień bajtów - liczymy numer bloku (logiczny adres bloku), w którym ten bajt się znajduje, żeby następnie wyznaczyć na podstawie tego numeru fizyczny adres bloku na dysku (w którym naprawdę mieści się nasz bajt).
    Algorytm bmap ma za zadanie przetworzyć logiczny adres bloku na jego fizyczny odpowiednik.
    Po sprawdzeniu poprawności parametrów - sprawdza się na którym poziomie pośredniości jest dany blok.
Przy bloku bezpośrednim - adres zwracany jest od razu.
Przy pojedynczo pośrednim musimy najpierw odczytać z dysku blok zawierający nasz adres.
Przy podwójnie pośrednim - najpierw czytamy z dysku blok pojedynczo pośredni, zawierający adres do bloku bezpośredniego (którego też musimy wczytać z dysku), w którym znajduje się adres do interesującego nas bloku.
Przy potrójnie pośrednim - analogicznie o jedno zagłębienie niżej.
Więcej informacji na temat algorytmu bmap znajdziesz w opracowaniu na jego temat w projekcie Linux .

Funkcja ext2_bmap korzysta z:

    -    makra inode_bmap, które na podstawie i-ramki oraz numeru bloku zwraca element o numerze numer z tablicy bloków i-węzła zawartego w i-ramce
                do skomentowanego kodu inode_bmap
    -    funkcji block_bmap, która na podstawie bufora zawierającego tablicę bloków i określonego numeru, zwraca element z tej tablicy o numerze numer. Funkcja po wykorzystaniu zwalnia ten bufor.
                do skomentowanego kodu block_bmap


Zwalnianie i-ramki

Tutaj jest skomentowany kod

    Można się zastanawiać dlaczego zwalnianie i-ramki zostało umieszczone wśród funkcji specyficznych dla systemu ext2. Związane jest to między innymi z faktem, że w systemie tym istnieje możliwość wcześniejszego zaalokowania bloków dyskowych dla danego pliku (i-węzła) i te bloki trzeba przy końcu zwolnić, czym zajmuje się specyficzna dla omawianego systemu funkcja ext2_discard_prealloc (skomentowany kod).

    Działanie funkcji polega więc na zwolnieniu wszystkich bloków dyskowych zaalokowanych z wyprzedzeniem dla danego i-węzła, następnie wszystkich bloków i-węzła, a na końcu zwolnieniu pamięci wykorzystywanej przez i-ramkę. 


Bibliografia

        1.    Pliki źródłowe:
            -    linux/fs/ext2/inode.c
            -    linux/fs/ext2/ialloc.c
        2.    Projekt Linux
        3.    Linux Kernel Hackers Guide

Autorzy:     Tomasz Sawicki (odczyt i-węzła z dysku)
Grzegorz Gawron (reszta + korekta)