Linux Kernel (Ядро линукса) (часть 3)


Метод readpage для файлов блочных устройств

Мы видели, как функция init speciai inode устанавливает индексный дескриптор устройства и как функция bikdev open завершает этап открытия файла.
Блочные устройства используют объект address space, который хранится в поле i data соответствующего индексного дескриптора в специальной файловой системе bdev. В отличие от обычных файлов, у которых метод readpage в объекте address space зависит от типа файловой системы, которой принадлежит файл, метод readpage файлов блочных устройств всегда один и тот же. Он реализован функцией bikdev_readpage, которая вызывает функцию block_read_full_page:
int blkdev_readpage(struct file file, struct page page)
{
return block_read_full_page(page, blkdev_get_block);
}
Как видите, здесь опять интерфейсная функция, на этот раз для biock_read_fuii_page. Ее второй параметр указывает на функцию, которая преобразует номер блока в файле в логический номер блока относительно начала блочного устройства. У файлов блочных устройств эти два номера совпадают, и функция bikdev get biock выполняет следующие действия:
1. Проверяет, превышает ли номер первого блока в странице индекс последнего блока в блочном устройстве (этот индекс получается делением размера блочного устройства, который хранится В поле bdev->bd_inode->
i size, на размер блока, хранящийся В поле bdev->bd_block_size, причем bdev указывает на дескриптор блочного устройства). Если проверка дала положительный результат, функция возвращает -ею для операции записи или ноль для операции чтения. (Чтение после конца блочного устройства тоже не разрешено, но здесь не следует возвращать код ошибки: ядро, возможно, просто пыталось передать запрос на чтение последней порции данных блочного устройства, а соответствующая страница буферов отображена не полностью.)
2. Записывает в поле b dev головы буфера значение bdev.
3. Записывает в поле b biocknr головы буфера номер блока в файле, переданный в качестве параметра.
4. Устанавливает флаг BH Mapped головы буфера, чтобы обозначить осмысленность значений полей b dev и b biocknr головы буфера.
Функция biock read fuii page о читает страницу данных по блокам. Как мы уже видели, она вызывается при чтении файлов блочных устройств и при чтении страниц обычных файлов, блоки которых не являются смежными на диске. Она выполняет следующие действия:
1. Проверяет флаг PG private дескриптора страницы. Если он установлен, значит, страница ассоциирована со списком голов буферов, описывающих блоки, составляющие страницу. В противном случае функция вызывает функцию create empty buffers () для выделения голов всем буферам блоков, включенным в страницу. Адрес головы первого буфера в странице хранится в поле page->private. Поле b this page каждой головы буфера указывает на голову следующего буфера в странице.
2. По смещению в файле относительно страницы (поле page->index) вычисляет номер в файле для первого блока на странице.
3. Для каждой головы буфера на странице выполняет следующие действия:
• если установлен флаг BH Uptodate, функция пропускает буфер и переходит к следующему буферу на странице;
• если флаг BH Mapped не установлен, а блок не находится после конца файла, функция вызывает специфичную для файловой системы функцию get biock, адрес которой был получен в качестве параметра. Для обычного файла функция выполняет поиск в дисковых структурах файловой системы и находит логический номер блока буфера относительно начала диска или раздела. Что касается файла блочного устройства, функция считает номер блока в файле логическим номером блока. В обоих случаях функция сохраняет логический номер блока в поле b biocknr соответствующей головы буфера и устанавливает флаг BH_Mapped1;
• снова проверяет флаг BH Uptodate, потому что специфичная для файловой системы функция get biock могла запустить операцию блочного ввода/вывода, которая обновила буфер. Если флаг BH Uptodate установлен, функция переходит к следующему буферу в странице;
• сохраняет адрес головы буфера в локальном массиве агг и переходит к следующему буферу на странице.
4. Если на предыдущем шаге не была обнаружена "дыра” в файле, функция устанавливает для страницы флаг PG mappedtodisk.
5. В настоящий момент локальный массив агг содержит адреса голов тех буферов, содержимое которых устарело. Если тот массив пуст, значит, все буферы страницы содержат осмысленные данные. Поэтому функция устанавливает флаг PG uptodate дескриптора этой страницы, снимает с нее блокировку при помощи функции uniock page и возвращает управление.
6. Локальный массив агг не пуст. Для каждой головы буфера из массива функция biock read fuii page выполняет следующие действия:
• устанавливает флаг вн ьоск. Если он уже установлен, ждет, пока освободится буфер;
• записывает в поле bendio головы буфера адрес функции
endjouf fer_async_read И устанавливает флаг BH_Async_Read ГОЛОВЫ буфера.
7. Для каждой головы буфера из локального массива агг вызывает функцию submit bh , указывая read в качестве типа операции. Как мы видели ранее, эта функция запускает ввод/вывод соответствующего блока.
8. Возвращает 0.
Функция end_buffer_async_read является методом завершения для головы буфера; она выполняется сразу после окончания пересылки данных для буфера блока. Если предположить, что ошибок ввода/вывода не было, функция устанавливает флаг BHUptodate головы буфера и сбрасывает флаг BH Async Read. Затем функция получает дескриптор страницы буферов, содержащей буфер блока (адрес хранится в поле b page головы буфера), и проверяет, нет ли устаревших блоков на странице. Если ни один не устарел, функция устанавливает для страницы флаг PG uptodate и вызывает функцию unlock_page.

Предыдущая страница | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | Следующая страница




Возможно, Вас также заинтересует:

ОС Knoppix - это Linux без про...

ВведениеЕсли вы цените свое время, умеете считать деньги и знаете стоимость информации, то эта книга...

Linux Kernel (Ядро линукса) (ч...

Спин-блокировкаСпин-блокировка необходима в многопроцессорной системе, потому что могут возникнуть...

Linux Kernel (Ядро линукса) (ч...

Копирование при записи В системах Unix первых поколений создание процесса было реализовано довольно...

Linux Kernel (Ядро линукса) (ч...

Буферы блоков и головы буферовУ каждого буфера есть дескриптор голова буфера, имеющий тип buffer...