Do tematu: Podsystem wejścia-wyjścia

Do tematu: Struktury danych

Struktura blk_dev_struct

Struktura blk_dev_struct opisuje urządzenie blokowe. Zawiera listę żądań skierowanych do danego urządzenia oraz wskaźnik do zdefiniowanej w sterowniku urządzenia funkcji, realizującej żądania. Struktury blk_dev_struct są pamiętane w tablicy blk_dev, której definicja znajduje się w pliku /drivers/block/ll_rw_blk.c:

MAX_BLKDEV 128

struct blk_dev_struct blk_dev[MAX_BLKDEV]

Tablica ta jest indeksowana numerami głównymi urządzeń blokowych. Definicja struktury blk_dev_struct znajduje się w pliku /include/linux/blkdev.h.

typ nazwa pola opis
void (*request_fn)(void) Wskaźnik do funkcji zdefiniowanej w sterowniku urządzenia. Funkcja ta realizuje obsługę żądań zapisu/odczytu do/z urządzenia.
struct request * current_request Kolejka żądań skierowanych do urządzenia.
struct request * plug (ang. korek) Pole plug jest żądaniem, które dla większości urządzeń jest wstawiane na listę żądań current_request, gdy lista ta jest pusta. W funkcji blk_dev_init, zdefiniowanej w pliku /drivers/block/ll_rw_blk.c, która inicjalizuje tablicę blk_dev, nadawane są również wartości początkowe żądaniu plug. Są one następujące:

plug.rq_status = RQ_INACTIVE

plug.cmd = -1

plug.next = NULL

Funkcja add_request, realizująca szeregowanie żądań do urządzeń blokowych, po wstawieniu żądania na pustą listę current_request, wywołuje funkcję zdefiniowaną w sterowniku urządzenia, której zadaniem jest doprowadzenie do wykonania operacji wejścia-wyjścia. Jeśli lista current_request nie jest pusta, to niskopoziomowa funkcja sterownika nie jest wywoływana. Wyjątek stanowią tu urządzenia SCSI.

Jeżeli o tym, kiedy rozpocząć obsługę żądań, chcemy decydować poza funkcją add_request, możemy posłużyć się żądaniem plug. Aby wstawić na pustą listę current_request żądanie plug, wywołujemy funkcję plug_device zdefiniowaną w pliku /drivers/block/ll_rw_block.c. Funkcja ta dodatkowo, rejestruje w kolejce zadań tq_disk funkcję unplug_device, jako funkcję "bottom half". Funkcja add_request nie rozróżnia żądania plug od innych żądań, w związku z tym wszystkie nadchodzące żądania ustawia na liście current_request za żądaniem plug, nie rozpoczynając, przy tym, ani razu niskopoziomowej obsługi żądań.

Dopiero, gdy wywołana zostanie funkcja run_task_queue dla kolejki tq_disk, funkcja unplug_device, usunie żądanie plug z listy current_request i zainicjalizuje obsługę żądań. (Funkcja run_task_queue wywołuje wszystkie funkcje "bottom half" zarejestrowane w odpowiedniej kolejce zadań)

struct tq_struct plug_tq Pole plug_tq reprezentuje funkcję "bottom half", której zadaniem jest inicjalizowanie obsługi żądań do urządzenia blokowego. Pole to otrzymuje wartości początkowe w funkcji blk_dev_init:

plug_tq.routine = &unplug_device

plug_tq.data = dev

dev jest wskaźnikiem do struktury blk_dev_init, argumentem dla funkcji unplug_device. Informacje na temat wykorzystania funkcji unplug_device zostały podane przy opisie pola plug.


Autor: Maciej Kaczmarek