getblk() i funkcje pomocnicze:
getblk()getblk() jest dostarczenie bufora z podrecznej pamieci
buforowej odpowiadajacego wskazanemu blokowi. Blok ten jest opisany przez
parametry funkcji podajace urzadzenie (kdev_t dev), z ktorego blok
ma byc pobrany, numeru bloku (int block) oraz jego rozmiaru (int size).
Te trzy parametry jednoznacznie wyznaczaja blok oraz przyporzadkowany mu
bufor z podrecznej pamieci buforowaj.
DEFINICJA: struct buffer_head* getblk(kdev_t dev, int block, int size)
WYNIK: wskaznik do naglowka bufora w przypadku sukcesu
NUll wpp.
getblk().getblk() tzn. ktorego pola b_dev, b_blocknr, b_size z naglowka
bufora sa odpowiednio rowne dev, block, size.
b_state naglowka bufora
rowny jest 0) tzn. jego dane sa takie same jak dane zpisane
w odpowiadajacym mu bloku fizycznego urzadzenia, to ustawiamy czas
zapisu (pole b_flushtime naglowka bufora) na 0. Jesli dodatkowo bufor
zawiera aktualne dane (bit BH_Uptodate pola b_state rowny 1) to
wstawiamy go na koniec odpowiadajacej mu kolejki lru (najdluzej
nieuzywanych buforow) za pomoca funkcji put_last_lru().
Oznaczamy bufor jako dotkniety tzn. ustawiamy bit BH_Touched
pola b_state na 1. Nastepnie zwracamy znaleziony bufor konczac funkcje
getblk().
Uwaga. Wszystkie bufory znajdujace sie w kolejkach haszujacych zawieraja aktualne dane. Dlatego bufor znaleziony w kolejce haszujacej i nie bedacy brudnym zawsze zawiera aktualne dane. (Tak mi sie wydaje)
refill_freelist(). Funkcja ta dostarczy wolne
bufory do danej kolejki,
refill_freelist() jest mozliwosc zasniecia podczas
oczekiwania na pewne zdarzenia,
b_count) rowny 1,
czas zapisu (b_flushtime) rowny 0,
oznaczamy go jako "dotkniety",
okreslamy blok, ktoremu bedzie odpowiadal ten bufor tzn.
urzadzenie (b_dev) rowne podanemu (dev), numer bloku (b_blocknr)
rowny podanemu (block),
insert_into_queues()).
getblk().
refill_freelist().refill_freelist() ma na celu dostarczenie wolnych
buforow podanego rozmiaru i wstawienie ich do kolejki wolnych buforow.
DEFINICJA: void refill_freelist(int size)Algorytm dzialania funkcji
refill_freelist().
needed). Liczba tworzonych buforow podczas
jdnego wywolania funkcji refill_freelist() jest podana w bdf_prm.b_un.nrefill.
nr_free_pages) jest dwa razy wieksza
niz okreslona w zmiennej min_free_pages minimalna liczba wolnych stron
i nie utworzylismy jeszcze wystarczajacej liczby buforow (needed >0 ) to
wywolujemy funkcje grow_buffers(). Funkcja ta probuje zwiekszyc liczbe
buforow podanego rozmiaru
Jesli funkcji grow_buffers() udalo sie stworzyc nowe bufory, to
zmniejszamy zapotrzebowanie na pamiec (needed) i wracamy do punktu 2.
needed <= 0) jesli tak,
to konczymy funkcje refill_freelist().
refill_freelist.
Wyszukiwaniem zbednych buforow i usuwaniem ich zajmuje sie funkcja
maybe_shrink_lav_buffers(), zas tworzeniem nowych funkcja grow_buffers().
b_lru_time naglowka bufora).
Usuwamy go z kolejki lru i haszujacej, nastepnie wstawiamy do kolejki
buforow wolnych.
Wybieramy nastepnego kandydata dla kolejki, z ktorej wybralismy zwyciezce.
Sprawdzamy czy mamy juz dosyc wolnych buforow. Jesli tak, to konczymy
funkcje, jesli nie to wracamy do elekcji.
grow_buffers() jesli tylko liczba wolnych
stron pamieci jest o piec wieksza niz minimalna liczba wolnych stron
( min_free_pages). Jesli udalo sie, to wracamy do punktu piatego.
grow_buffers() z wiekszym priorytetem, niz do tej pory.
Jesli i to zawodzi, to budzimy proces bdflush (zapisuje brudne bufory),
a sami zasypiamy czekajac na zakonczenie jego dzialania.
grow_buffers()grow_buffers() probuje zwiekszyc liczbe dostepnych buforow
podanego rozmiaru.
DEFINICJA: int grow_buffers(int pri, int size)
WYNIK: 1 w przypadku sukcesu
0 wpp
get_free_page(), wywolujac ja
z priorytetem podanym w parametrach (pri).
Jesli to sie nie uda, to zwraca zero.
create_buffers(), podajac w parametrach pobrana strone
oraz rozmiar bufora. Funkcja ta stworzy nam bufory, ktorych dane beda
umieszczane na podanej stronie.
create_buffers().
DEFINICJA: struct buffer_head* create_buffers(unsigned long page, unsigned long size)
WYNIK: wskaznik do naglowka bufora
NULL jesli nie udalo sie stworzyc bufory
Funkcja create_buffers() tworzy bufory podanego rozmiaru, ktorych dane
przechowywane beda na dostarczonej (jako parametr funkcji) stronie pamieci.
Dokladniej dopoki jest miejsce na stronie pamieci pobiera nieuzywany naglowek
bufora (funkcja get_unused_buffer_head()), a nastepnie przydziela mu (pole
b_data naglowka) kolejny kawalek strony. Otrzymane bufory laczymy w liste
przez pola b_this_page w naglowku bufora. Zwracamy pierwszy bufor z tej listy.
get_unused_buffer_head()
DEFINICJA: buffer_head* get_unused_buffer_head(void)
WYNIK: wskaznik do naglowka bufora
NULL jesli nie udalo sie pobrac naglowka bufora
Funkcja get_unused_buffer_head() dostarcza nieuzywany naglowek bufora.
Jesli nie ma nieuzywanych naglowkow, ktore sa trzymane na liscie unused_list,
to probujemy je stworzyc. W tym celu pobieramy wolna strone pamieci i tworzymy
na niej naglowki buforow. Jesli to sie nie uda (mamy za malo pamieci), to
zasypiamy w oczekiwaniu na zwolnienie jakiegos naglowka.
maybe_shrink_lav_buffers().
DEFINICJA: int maybe_shrink_lav_buffers(int size)
WYNIK: 1 w przypadku sukcesu
0 wpp
Funkcja maybe_shrink_lav_buffers() wybiera bufory (dokladniej rozmiar buforow),
o rozmiarze roznym niz podany w parametrze, ktore byly stosunkowo rzadko
uzywane. Nastepnie probuje zwolnic jedna strone pamieci, zajmowana przez te
bufory (korzystajac z funkcji shrink_specific_buffers()).
shrink_specific_buffers().shrink_specific_buffers() probuje zwolnic jedna strone pamieci
zajmowana przez bufory rozmiaru podanego w parametrach.
DEFINICJA: int shrink_specific_buffers(unsigned int priority, int size)
WYNIK: 1 w przypadku sukcesu
0 wpp
Uwaga
Dzialanie tej funkcji opisalem dla wywolania przez funkcje maybe_shrink_lav_buffers(),
czyli z priorytetem (pri) rownym 6.