Поиск грязных страниц для записи на диск
Каждое базисное дерево может включать в себя грязные страницы, подлежащие записи на диск. Чтобы получить все такие страницы, необходим исчерпывающий поиск среди объектов address space, ассоциированных с индексными дескрипторами, имеющими образ на диске. Поскольку кэш страниц может содержать большое количество страниц, сканирование всего кэша за один проход может надолго занять центральный процессор и диски. Поэтому в системе Linux принят сложный механизм, разбивающий сканирование кэша страниц на несколько проходов.
Функция wakeup bdfiusho принимает в качестве аргумента количество грязных страниц в кэше, подлежащих принуительной записи на диск, причем ноль означает, что на диск должны быть записаны все грязные страницы кэша. Эта функция вызывает функцию pdflush_operation , чтобы разбудить” поток pdflush и делегирует ей выполнение функции обратного вызова background writeout . Последняя извлекает из кэша страниц указанное количество грязных страниц и записывает их на диск.
Функция wakeup bdfiusho выполняется либо при нехватке памяти, либо когда пользователь явно требует операцию сброса страницы на диск. В частности, эта функция вызывается в следующих случаях:
- процесс режима пользователя делает системный вызов sync о - функции grow buffers не удается выделить новую страницу буферов
- алгоритм утилизации СТраНИЧНЫХ кадрОВ ВЫЗЫВаеТ фуНКЦИЮ free_more_ memory ИЛИ try_to_f ree_pages
- функции mempo о i_a 11 о с не удается выделить новый элемент пула памяти
Кроме того, поток pdflush, выполняющий функцию обратного вызова background writeout о, пробуждается” каждым процессом, который модифицирует содержание страниц в кэше и увеличивает долю грязных” страниц до значения, превышающего некий фоновый порог. Этот фоновый порог обычно устанавливается на уровне 10% от общего количества страниц в системе, но его можно изменить, записав новое значение в файл /proc/sys/vm / d irty_background_ratio.
Функция background writeout использует в своей работе структуру writeback controi, которая действует как коммуникационное устройство. С ОДНОЙ стороны, она сообщает вспомогательной функции writeback_inodes , что надо сделать, а с другой — содержит статистическую информацию о количестве страниц, записанных на диск. Назовем самые важные поля этой структуры:
- sync mode — задает режим синхронизации:
• wb sync all— при обнаружении заблокированного индексного дескриптора следует ждать его разблокирования;
• wb sync hold — заблокированные индексные дескрипторы помещаются в список для дальнейшего рассмотрения;
• wb sync none — заблокированные индексные дескрипторы можно просто игнорировать;
- bdi— если это поле не содержит null, оно указывает на структуру backing dev info. В этом случае на диск будут сброшены только грязные страницы, принадлежащие соответствующему блочному устройству;
- oider than this — если это поле не содержит null, индексные дескрипторы, "моложе” заданного значения, должны быть проигнорированы;
- nr to write— количество грязных страниц, еще подлежащих записи на данном проходе;
- nonblocking — если этот флаг установлен, процесс нельзя блокировать.
Функция background writeout принимает один параметр, nr pages, задающий минимальное количество страниц, подлежащих принудительной записи на диск. Она выполняет следующие действия:
1. Читает из переменной page state (имеющейся у каждого процессора) количество страниц, в том числе грязных, хранящихся в кэше. Если доля грязных страниц ниже установленного порога, и, по меньшей мере, nr pages страниц было сброшено на диск, функция завершает работу. Значение этого порога обычно составляет 40% от общего количества страниц в системе, но его можно изменить, записав новое значение в файл / ргос/ sy s/vm/d irtyjratio.
2. Вызывает функцию writeback inodes () в попытке записать на диск 1024 грязных страниц.
3. Проверяет количество фактически записанных страниц и уменьшает количество страниц, еще подлежащих записи.
4. Если было записано менее 1024 страниц, или если страницы были пропущены, это, вероятнее всего, свидетельствует о переполнении очереди запросов блочного устройства.
5. Функция приостанавливает выполнение текущего процесса, помещая его в специальную очередь на 100 мс, либо до момента, когда очередь запросов перестанет быть переполненной.
6. Переходит к шагу 1.
Функция writeback inodes принимает единственный параметр, указатель wbc на дескриптор writeback controi. Поле nr to write этого дескриптора содержит количество страниц, подлежащих сбросу на диск. Когда функция возвращает управление, это поле содержит количество еще не сброшенных страниц. Если все прошло гладко, поле содержит ноль.
Предположим, что функция writeback inodes вызвана при следующих условиях: указатели wbc->bdi и wbc->oider_than_this равны null, выбран режим синхронизации WB SYNC NONE И установлен флаг wbc->nonblocking (все эти значения заданы функцией background writeout ). Тогда функция сканирует список суперблоков с корнем в переменной super blocks. Сканирование заканчивается, когда либо просмотрен весь список, либо достигнуто заданное количество страниц, сбрасываемых на диск.
Для каждого суперблока sb функция проверяет, пусты ли списки sb->s_dirty и sb->s_io. Первый из них содержит грязные” индексные дескрипторы суперблока, а второй — индексные дескрипторы, ожидающие записи на диск. Если оба списка пусты, значит, индексные дескрипторы в этой файловой системе не имеют грязных страниц, и функция переходит к следующему суперблоку.
Допустим, суперблок имеет грязные” индексные дескрипторы. Функция вызывает sync sb inodes о для суперблока sb. Вызванная функция:
1. Заносит все индексные дескрипторы из списка sb->s_dirty в список sb->s_io и очищает список грязных” индексных дескрипторов.
2. Читает следующий указатель inode из списка sb->s_io. Если список пуст, возвращает управление.
3. Если индексный дескриптор стал грязным” после старта функции sync sb inodes , она игнорирует грязные страницы этого индексного дескриптора и возвращает управление. Обратите внимание, что в списке sb->s_io могут остаться грязные” индексные дескрипторы.
4. Если текущим процессом является поток ядра pdflush, функция проверяет, не пытается ли другой поток pdflush, работающий на другом процессоре, записать грязные страницы файлов, принадлежащих этому блочному устройству. Это можно сделать с помощью атомарной операции проверки и установки флага BDi pdfiush структуры backing dev info данного индекс- ного дескриптора. В сущности, нет смысла иметь более одного потока ядра pdflush для одной очереди запросов
5. Увеличивает на единицу счетчик обращений индексного дескриптора.
6. Вызывает функцию writeback_singie_inode , чтобы записать на диск
грязные” буферы, ассоциированные с выбранным индексным дескриптором:
• если индексный дескриптор заблокирован, функция переносит inode В СПИСОК грязных” индексных дескрипторов (inode->i_sb->s_dirty) И
возвращает 0. Поскольку мы предположили, что поле wbc->sync_mode не равно wb sync all, функция не ждет разблокирования индексного дескриптора;
• вызывает метод writepages адресного пространства данного индексного дескриптора (или функцию mpage writepages , если такого метода нет), чтобы записать до wbc->nr_to_write "грязных” страниц. Эта функция использует функцию find_get_pages_tag ДЛЯ быСТрОГО ПО- лучения всех грязных” страниц в адресном пространстве индексного дескриптора
• если индексный дескриптор грязен”, функция вызывает метод суперблока write inode, чтобы записать индексный дескриптор на диск. Функции, реализующие этот метод, обычно используют функцию submit bh для пересылки одного блока данных
• проверяет состояние индексного дескриптора. По результатам проверки переносит индексный дескриптор либо обратно в список sb-> s dirty, если какая-то страница индексного дескриптора еще грязная”, либо в список inode unused, если счетчик ссылок индексного дескриптора равен нулю, либо в список inode in use, если первые два условия не удовлетворены
• возвращает код ошибки функции find get pages tag, вызванной в начале этого шага.
7. Продолжается выполнение функции sync sb inodes . Если текущим процессом является поток ядра pdflush, функция сбрасывает флаг BDi pdf lush, установленный на шаге 4.
8. Если в только что обработанном индексном дескрипторе некоторые страницы были пропущены, значит, он содержит заблокированные буферы. Функция переносит все индексные дескрипторы, оставшиеся в списке sb->s_io, обратно в список sb->s_dirty; они будут повторно рассмотрены позже.
9. Уменьшает на единицу счетчик обращений индексного дескриптора.
10. Если wbc->nr_to_write больше 0, функция возвращается к шагу 2, чтобы искать другие "грязные" индексные дескрипторы того же суперблока. В противном случае sync sb inodes завершает свою работу.
Далее продолжается выполнение функции writeback inodes . Если wbc-> nr to write больше нуля, она переходит к обработке следующего суперблока в глобальном списке. В противном случае заканчивает работу.
Предыдущая страница | 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 | Следующая страница