Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
16.4. Несколько других подробностей
hardorsoft
26.10.10 в 00:42
|
|
Этот подраздел содержит дополнительную информацию об уровне блочных устройств, которая может быть интересна тем, кто хочет достичь более глубокого понимания. Можно написать корректный драйвер и без нижеследующих возможностей, но, в некоторых ситуациях, они могут быть полезны.
hardorsoft
26.10.10 в 00:42
|
|
16.4.1. Предварительная подготовка команд
hardorsoft
26.10.10 в 00:43
|
|
Уровень блочных устройств предоставляет механизм для драйверов, который осуществляет проверку и предварительную обработку запросов перед тем, как их вернет elv_next_request. Этот механизм позволяет драйверу подготовить устройство к будущим операциям, решить могут ли быть обработаны все запросы, или выполнить еще какие-то вспомогательные действия.
hardorsoft
26.10.10 в 00:43
|
|
Если вы хотите использовать это свойство, создайте функцию предварительной подготовки, в соответствии со следующим прототипом: typedef int (prep_rq_fn) (request_queue_t *queue, struct request *req);
hardorsoft
26.10.10 в 00:43
|
|
Структура request содержит поле cmd, которое является массивом из BLK_MAX_CDB байт. Этот массив может быть использован функцией предварительной подготовки для хранения аппаратных команд или любой другой информации. Эта функция возвращает одно из следующих значений:
hardorsoft
26.10.10 в 00:44
|
|
BLKPREP_OK Подготовка прошла успешно, и запрос может быть обработан функцией request вашего драйвера.
hardorsoft
26.10.10 в 00:44
|
|
BLKPREP_KILL Запрос не может быть выполнен. Сопровождается кодом ошибки.
hardorsoft
26.10.10 в 00:44
|
|
BLKPREP_DEFER Запрос не может быть выполнен в настоящее время. Он остается в начале очереди, но не обрабатывается функцией request.
hardorsoft
26.10.10 в 00:44
|
|
Функция предварительной подготовки вызывается из elv_next_request непосредственно перед возвратом из нее в ваш драйвер. Если возвращается значение BLKPREP_DEFER, то elv_next_request вернет NULL. Данный режим может быть использован, например, тогда, когда количество выполняемых запросов в вашем устройстве достигло максимального значения.
hardorsoft
26.10.10 в 00:45
|
|
Чтобы уровень блочных устройств мог вызывать вашу функцию, передайте ее в:
hardorsoft
26.10.10 в 00:45
|
|
void blk_queue_prep_rq(request_queue_t *queue, prep_rq_fn *func);
hardorsoft
26.10.10 в 00:45
|
|
По умолчанию очередь запросов не имеет функции предварительной подготовки. 16.4.2. Пометка команд очереди
hardorsoft
26.10.10 в 00:46
|
|
Аппаратное обеспечение, которое может обслуживать сразу несколько запросов, обычно поддерживает пометку команд очереди (TCQ – tagged command queueing). TCQ – простая технология, прикрепляющая целочисленную метку (tag) к каждому запросу, что позволяет устройству сообщить драйверу о выполнении одного из запросов. В предыдущих версиях ядра, драйвера реализующие TCQ, выполняли всю работу самостоятельно. В ядре 2.6, в уровень блочных устройств добавлена инфраструктура поддержки TCQ.
hardorsoft
26.10.10 в 00:46
|
|
Если ваш драйвер использует TCQ, вы должны проинформировать об этом ядро во время инициализации с помощью вызова:
hardorsoft
26.10.10 в 00:46
|
|
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. Уровень блочных устройств должен сам инициализировать массив, и он не экспортирует функцию инициализации в модули.
hardorsoft
26.10.10 в 00:47
|
|
Поскольку функция blk_queue_init_tags производит выделение памяти, ее работа может завершиться неудачей, в этом случае возвращается отрицательное число.
hardorsoft
26.10.10 в 00:47
|
|
При изменении размера массива меток tags, необходимо проинформировать об этом ядро с помощью функции:
hardorsoft
26.10.10 в 00:47
|
|
int blk_queue_resize_tags(request_queue_t *queue, int new_depth);
hardorsoft
26.10.10 в 00:47
|
|
При вызове этой функции блокировка очереди должена быть захвачена. Вызов может завершиться неудачей, в этом случае возвращается отрицательное число.
hardorsoft
26.10.10 в 00:48
|
|
Массив меток ассоциируется со структурой request, вызовом функции blk_queue_start_tag. При вызове этой функции блокировка очереди так же должена быть захвачена.
hardorsoft
26.10.10 в 00:48
|
|
int blk_queue_start_tag(request_queue_t *queue, struct request *req);
hardorsoft
26.10.10 в 00:48
|
|
Если имеется доступная метка, эта функция использует ее для запроса, сохраняя ее значение в req->tag и возвращает «0». Так же функция выводит запрос из очереди и связывает его со структурой хранения меток. Таким образом, вашему драйверу не требуется убирать запросы из очереди, если он использует TCQ. В случае, когда нет больше свободных меток, функция blk_queue_start_tag оставляет запрос в очереди и возвращает не нулевое значение.
hardorsoft
26.10.10 в 00:48
|
|
Когда данные запроса полностью переданы, ваш драйвер должен освободить метку. Для этого используется команда:
hardorsoft
26.10.10 в 00:48
|
|
void blk_queue_end_tag(request_queue_t *queue, struct request *req);
hardorsoft
26.10.10 в 00:49
|
|
Перед этим вызовом вы снова должны захватить блокировку очереди. Функция должна вызываться только после того, как вызов blk_queue_start_tag вернул нулевое значение, и до вызова end_that_request_last. И помните, что запрос уже выведен из очереди.
hardorsoft
26.10.10 в 00:49
|
|
Если требуется найти запрос ассоциированный с меткой (например когда драйвер сообщает о выполнении) используйте функцию:
hardorsoft
26.10.10 в 00:49
|
|
struct request *blk_queue_find_tag(request_queue_t *qeue, int tag);
hardorsoft
26.10.10 в 00:49
|
|
Возвращаемое значение является ассоциированной структурой request, если все работает правильно.
hardorsoft
26.10.10 в 00:49
|
|
Если действительно произошел какой-то сбой, ваш драйвер может произвести сброс, или какое-либо еще действие над устройством. В этом случае оставшиеся команды не будут выполнены. Предоставляется функция, которая может помочь в исправлении этой ситуации:
hardorsoft
26.10.10 в 00:50
|
|
void blk_queue_invalidate_tags(request_queue_t *queue);
hardorsoft
26.10.10 в 00:50
|
|
Эта функция возвращает все ожидающие исполнения запросы обратно в очередь. При выполнении этого вызова, блокировка очереди должна быть захвачена.
hardorsoft
26.10.10 в 00:50
|
|