/*
* Zwolnij nagłówek bufora
*/
void __brelse(struct buffer_head * buf)
{
/*czekaj na bufor*/
wait_on_buffer(buf);
/* Jeżeli bufor przeznaczony do zapisu,
zaznacz czas, w którym powinien zostać zapisany*/
set_writetime(buf, 0);
/*uporządkuj pola nagłówka bufora*/
refile_buffer(buf);
/*zmniejsz licznik odwołań do bufora*/
if (buf->b_count) { /*jeżeli w ogóle jest
co zmniejszać*/
buf->b_count--;
return;
}
printk("VFS: brelse: Trying to free free buffer\n"); /*jeżeli
nie ma co zmniejszać to błąd*/
}
/*czekanie na
ewentualne zwolnienie bufora z blokady*/
void __wait_on_buffer(struct buffer_head * bh)
{
struct wait_queue wait = { current, NULL };
bh->b_count++; /*zwiększ
liczbę odwołań do bufora*/
add_wait_queue(&bh->b_wait, &wait);
repeat:
run_task_queue(&tq_disk);
current->state = TASK_UNINTERRUPTIBLE; /*wyłącz
przerwania*/
if (buffer_locked(bh)) { /*jeżeli bufor
zablokowany*/
schedule();
/*zapisz się do kolejki czekających*/
goto repeat;
}
remove_wait_queue(&bh->b_wait, &wait); /*usuń
kolejkę do czekania*/
bh->b_count--; /*zmniejsz liczbę odwołań
do bufora*/
current->state = TASK_RUNNING; /*przywróć
normalny stan obecnego zadania*/
}
void set_writetime(struct buffer_head *
buf, int flag)
{
int newtime;
if (buffer_dirty(buf)) {
/* Move buffer to dirty list if jiffies is clear */
/*obliczenie nowego czasu opóźnionego
zapisu*/
/*na podstawie obecnego czasu oraz
czasu, po którym superblok/bufor starzeje się
(zależnie od zmiennej flag)*/
newtime = jiffies + (flag ? bdf_prm.b_un.age_super
:
bdf_prm.b_un.age_buffer);
/*jeżeli czas opóźnionego zapisu bufora
nie jest zerem, to nie można go zwiększyć*/
if(!buf->b_flushtime || buf->b_flushtime > newtime)
buf->b_flushtime = newtime;
} else {
buf->b_flushtime = 0;
}
}
/*
* A buffer may need to be moved from one buffer list to another
* (e.g. in case it is not shared any more). Handle this.
*/
/* Być może bufor musi zostać przeniesiony
z jednej listy buforów do drugiej
* (np. gdy przestał już być dzielony)
*/
void refile_buffer(struct buffer_head * buf)
{
int dispose; /*zmienna pomocnicza -
gdzie przesuniemy ten bufor*/
if(buf->b_dev == B_FREE) { /*błąd
- próbujemy wykonać tą funkcję na wolnym buforze*/
printk("Attempt to refile free buffer\n");
return;
}
/*bity w polu b_list nie zawsze odpowiadają
rzeczywistym kolejkom LRU, w których znajduje się bufor*/
/*trzeba to uaktualnić*/
if (buffer_dirty(buf)) /*sprawdzenie
bitu BH_Dirty pola b_state*/
dispose = BUF_DIRTY;
else if (buffer_locked(buf)) /*jeżeli
bit BH_Lock pola b_state jest ustawiony na 1 (czyli gdy bufor jest zablokowany)*/
dispose = BUF_LOCKED;
else
dispose = BUF_CLEAN;
if(dispose == BUF_CLEAN) buf->b_lru_time = jiffies; /*zaznaczamy
czas ostatniego użycia*/
if(dispose != buf->b_list) {
if(dispose == BUF_DIRTY)
buf->b_lru_time = jiffies;
if(dispose == BUF_LOCKED &&
(buf->b_flushtime - buf->b_lru_time) <=
bdf_prm.b_un.age_super)
dispose = BUF_LOCKED1; /*jeżeli
różnica między czasem zapisu a czasem ost. użycia <= czasu starzenia
superbloku*/
remove_from_queues(buf); /*usuń bufor
z dotychczasowej kolejki LRU*/
buf->b_list = dispose;
/*to będzie nowa kolejka dla tego bufora*/
insert_into_queues(buf); /*włóż
bufor do nowej kolejki*/
if (dispose == BUF_DIRTY) {
/* This buffer is dirty, maybe we need to start flushing. */
/* If too high a percentage of the buffers are dirty... */
/* Jeżeli ten bufor jest przeznaczony
do zapisu, to może trzeba zacząć zapisywać wszystkie takie bufory na dysk*/
/* Gdy zbyt duży procent buforów jest
przeznaczony do zapisu...*/
if (nr_buffers_type[BUF_DIRTY] > nr_buffers * bdf_prm.b_un.nfract/100)
wakeup_bdflush(0); /*obudź
demona zapisującego bufory*/
/* If this is a loop device, and
* more than half of the buffers are dirty... */
/* (Prevents no-free-buffers deadlock with loop device.) */
/* jeżeli urządzenie wskazywane przez
bufor jest urządzeniem cyklicznym
/* oraz więcej niż połowa buforów jest
przeznaczona do zapisu*/
/* (zapobiega blokadzie z powodu braku
wolnych buforów na urządzeniu cyklicznym)*/
if (MAJOR(buf->b_dev) == LOOP_MAJOR &&
nr_buffers_type[BUF_DIRTY]*2>nr_buffers)
wakeup_bdflush(1);
}
}
}
/*zmienna globalna zwierająca
dane dot. opóźnionego zapisu buforów na dysk*/
/* the dummy values in this structure are left in there for compatibility
with old programs that play with the /proc entries */
/* zmienne "dummy" zostały zachowane ze względu
na kompatybilnos'ć
ze starszymi programami,
które używają /proc*/
union bdflush_param{
struct {
/*procent pamięci buforowej, który
zajmują bufory przeznaczone do zapisu*/
int nfract; /* Percentage of buffer cache dirty to
activate bdflush */
/*maksymalna liczba bloków, którą można
zapisać za jednym razem po obudzeniu demona bd_flush*/
int ndirty; /* Maximum number of dirty blocks to write
out per
wake-cycle */
/*liczba czystych buforów (czyli nie
przeznaczonych do zapisu), które próbujemy uzyskać
za każdym razem,
gdy wywołujemy refill*/
int nrefill; /* Number of clean buffers to try to obtain
each time we call refill */
int nref_dirt; /* Dirty buffer threshold for activating bdflush
when trying to refill buffers. */
int dummy1; /* unused */
/*czas, po którym normalny bufor się
starzeje i trzeba go zapisać*/
int age_buffer; /* Time for normal buffer to age before
we flush it */
/*czas, po którym superblok się starzeje
i trzeba go zapisać*/
int age_super; /* Time for superblock to age before we
flush it */
int dummy2; /* unused */
int dummy3; /* unused */
} b_un;
unsigned int data[N_PARAM];
} bdf_prm = {{40, 500, 64, 64, 15, 30*HZ, 5*HZ, 1884, 2}};