Готовый перевод Linux Device Drivers 3 / Драйверы устройств Линукс (третье издание): 16.4. Несколько других подробностей

Внимание! Этот перевод, возможно, ещё не готов, так как модераторы установили для него статус «перевод редактируется»

16.4. Несколько других подробностей

Этот подраздел содержит дополнительную информацию об уровне
блочных устройств, которая может быть интересна тем, кто хочет достичь
более глубокого понимания. Можно написать корректный драйвер и без
нижеследующих возможностей, но, в некоторых ситуациях, они могут
быть полезны.

16.4.1. Предварительная подготовка команд

Уровень блочных устройств предоставляет механизм для драйверов,
который осуществляет проверку и предварительную обработку запросов
перед тем, как их вернет elv_next_request. Этот механизм позволяет
драйверу подготовить устройство к будущим операциям, решить могут ли
быть обработаны все запросы, или выполнить еще какие-то
вспомогательные действия.

Если вы хотите использовать это свойство, создайте функцию
предварительной подготовки, в соответствии со следующим прототипом:
typedef int (prep_rq_fn) (request_queue_t *queue, struct request *req);

Структура request содержит поле cmd, которое является массивом
из BLK_MAX_CDB байт. Этот массив может быть использован функцией
предварительной подготовки для хранения аппаратных команд или любой
другой информации. Эта функция возвращает одно из следующих
значений:

BLKPREP_OK
Подготовка прошла успешно, и запрос может быть обработан
функцией request вашего драйвера.

BLKPREP_KILL
Запрос не может быть выполнен. Сопровождается кодом ошибки.

BLKPREP_DEFER
Запрос не может быть выполнен в настоящее время. Он остается в
начале очереди, но не обрабатывается функцией request.

Функция предварительной подготовки вызывается из
elv_next_request непосредственно перед возвратом из нее в ваш драйвер.
Если возвращается значение BLKPREP_DEFER, то elv_next_request вернет
NULL. Данный режим может быть использован, например, тогда, когда
количество выполняемых запросов в вашем устройстве достигло
максимального значения.

Чтобы уровень блочных устройств мог вызывать вашу функцию,
передайте ее в:

void blk_queue_prep_rq(request_queue_t *queue, prep_rq_fn *func);

По умолчанию очередь запросов не имеет функции предварительной
подготовки.
16.4.2. Пометка команд очереди

Аппаратное обеспечение, которое может обслуживать сразу
несколько запросов, обычно поддерживает пометку команд очереди (TCQ
– tagged command queueing). TCQ – простая технология, прикрепляющая
целочисленную метку (tag) к каждому запросу, что позволяет устройству
сообщить драйверу о выполнении одного из запросов. В предыдущих
версиях ядра, драйвера реализующие TCQ, выполняли всю работу
самостоятельно. В ядре 2.6, в уровень блочных устройств добавлена
инфраструктура поддержки TCQ.

Если ваш драйвер использует TCQ, вы должны проинформировать об
этом ядро во время инициализации с помощью вызова:

int blk_queue_init_tags(request_queue_t *queue, int depth, struct
blk_queue_tag *tags);
Параметр queue – это ваша очередь запросов, depth – количество
помечаемых запросов, которое ваше устройство может обработать. Параметр tags – опциональный указатель на массив структур
blk_queue_tag, состоящий из depth элементов. Обычно параметр tags
равен NULL, в этом случае функция blk_queue_init_tags создает массив.
Однако, если вам необходимо, чтобы массив tags был общим у нескольких
устройств, вы можете передать в tags указатель из другой очереди
запросов, хранящийся в поле queue_tags. Вы не должны самостоятельно
выделять массив tags. Уровень блочных устройств должен сам
инициализировать массив, и он не экспортирует функцию инициализации
в модули.

Поскольку функция blk_queue_init_tags производит выделение
памяти, ее работа может завершиться неудачей, в этом случае
возвращается отрицательное число.

При изменении размера массива меток tags, необходимо
проинформировать об этом ядро с помощью функции:

int blk_queue_resize_tags(request_queue_t *queue, int new_depth);

При вызове этой функции блокировка очереди должена быть
захвачена. Вызов может завершиться неудачей, в этом случае
возвращается отрицательное число.

Массив меток ассоциируется со структурой request, вызовом
функции blk_queue_start_tag. При вызове этой функции блокировка
очереди так же должена быть захвачена.

int blk_queue_start_tag(request_queue_t *queue, struct request *req);

Если имеется доступная метка, эта функция использует ее для
запроса, сохраняя ее значение в req->tag и возвращает «0». Так же
функция выводит запрос из очереди и связывает его со структурой
хранения меток. Таким образом, вашему драйверу не требуется убирать
запросы из очереди, если он использует TCQ. В случае, когда нет больше
свободных меток, функция blk_queue_start_tag оставляет запрос в
очереди и возвращает не нулевое значение.

Когда данные запроса полностью переданы, ваш драйвер должен
освободить метку. Для этого используется команда:

void blk_queue_end_tag(request_queue_t *queue, struct request *req);

Перед этим вызовом вы снова должны захватить блокировку
очереди. Функция должна вызываться только после того, как вызов
blk_queue_start_tag вернул нулевое значение, и до вызова
end_that_request_last. И помните, что запрос уже выведен из очереди.

Если требуется найти запрос ассоциированный с меткой (например
когда драйвер сообщает о выполнении) используйте функцию:

struct request *blk_queue_find_tag(request_queue_t *qeue, int tag);

Возвращаемое значение является ассоциированной структурой
request, если все работает правильно.

Если действительно произошел какой-то сбой, ваш драйвер может
произвести сброс, или какое-либо еще действие над устройством. В этом
случае оставшиеся команды не будут выполнены. Предоставляется функция, которая может помочь в исправлении этой ситуации:

void blk_queue_invalidate_tags(request_queue_t *queue);

Эта функция возвращает все ожидающие исполнения запросы
обратно в очередь. При выполнении этого вызова, блокировка очереди
должна быть захвачена.

Внимание! Этот перевод, возможно, ещё не готов.
Его статус: перевод редактируется

Переведено на Нотабеноиде
http://notabenoid.org/book/11832/38378

Переводчики: hardorsoft

Настройки

Готово:

100.00% КП = 1.0