Меню Рубрики

Есть данные после конца блока полезных данных

На 7-Zip.org доступны сборки для всех поддерживаемых ОС, исходные коды, а также пакет 7-Zip Extra (автономная консольная версия, библиотеки и плагин для FAR)

Расшифровка обозначения аппаратных платформ к таблицам:

IA32 Win32 для x86/х86-64 и совместимых по набору машинных команд процессоров от i386 и новее
AMD64 Win64 для AMD64/Intel EMT64 х64-86 совместимые процессоры от AMD K8 и новее
IA64 Win64 для Intel Itanium/Itanium 2
ARM Win32 для DEC StrongARM SA-110/Intel XScale совместимые процессоры

7-Zip — бесплатный качественный архиватор, поддерживающий распаковку следующих форматов файлов:
7z, Arj, Bkf, BZ2, BZIP2, Cab, Chm, Compound, CPIO, Deb, Dmg, ELF, FLV, GZip , LZH, lzma, MachO, MSI, Mub, NSIS, PE, Rar, Rpm, Split, SWF, SWM, TAR, WIM, Xar, xz, Z, zip, zipx, образы ISO, UDF, FAT, NTFS, HFS, ext2, ext3, ext4, VHD, VDI, VMDK, GPT, QCOW2.

  • степень сжатия архивов ZIP и GZIP, создаваемых с помощью 7-Zip, на 2-10% выше, чем у PKZip и WinZip;
  • высокая степень сжатия в собственном формате 7z;
  • создание самораспаковывающихся архивов (для формата 7z);
  • шифрование по алгоритму AES-256 (для формата 7z);
  • интеграция в оболочку Windows;
  • наличие плагина для FAR Manager;
  • наличие версий GUI и для командной строки.

    Системные требования: Windоws 98/ME/NT/2000/XP/Vista/7/8/8.1 (имеется портированные версии для Linux/Unix).
    Языки интерфейса: русский, английский и др. (более 80).

    Achtung!

    Некоторые провайдеры, например, ТТК, блокируют официальный сайт заходить туда можно через ТОР/прокси или скачивать файлы со страницы проекта на SourceForge.net
    Скачивать с посторонних ресурсов, типа различных файлопомоек не рекомендуется, можно легко нарваться на различную заразу.

    Alpha и Beta-версии 7-Zip зачастую являются развитием «стабильных» версий с улучшениями и исправлениями багов.
    Ссылки на альфы ищем в разделе Open Discussion форума проекта 7-Zip, там же можно получить и консультацию от разработчика.

    Дополнительные ресурсы:

  • 7-Zip разработан для работы под Windows, но если вам необходимо использовать именно Win-сборку, то он может быть запущен на UNIX/Linux или Mac OS X в среде WINE HQ 1.6 и выше без ограничений.
  • Порт для платформ UNIX/LINUX называется p7zip и распространяется в виде прекомпилированных бинарных пакетов и исходных текстов. Смотрите нужные Вам версии архиватора и зависимые для его работы и сборки пакеты на сайтах своих операционных систем либо, при наличии, в репозиториях. При нарушении зависимостей программа работать не будет!
  • Код LZMA SDK является общественным достоянием (public domain). Архиватор 7-Zip распространяется бесплатно под лицензией GNU LGPL. Если он вам понравился, зарегистрируйтесь и заплатите небольшую сумму (от $50) авторам.
  • На момент тестирования в программе не было замечено ни баннеров, ни так называемого Spyware.

    Bak старой шляпы (01.10.2018): Link

    Всего записей: 7232 | Зарегистр. 18-02-2006 | Отправлено: 22:35 20-12-2016 | Исправлено: bthgroup, 18:18 22-02-2019
  • Alexandr111990

    Member

    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Здравствуйте

    ВНИМАНИЕ!

    ( Хорошо бы добавить в шапку для пояснения! )

    Решение заядлой Ошибки-Предупреждения!
    Кто сталкивался с таким типом предупреждения (при открытии, тестирования и распаковки архива RAR ):

    Предупреждения Есть данные после конца блока полезных данных

    Оказывается эта ошибка унаследовалась ещё с версии 9.20 и только с архивом RAR.
    И это не проблема в архиве а просто мелкая ошибка.
    В этой теме обсуждается данная ошибка
    А вот официальное сообщения разработчика

    Там говорится следующее:
    Вы можете извлечь этот архив rar5 в режиме парсера:

    7z x JDownloader2Setup.exe -t #
    После rar-архива есть блок данных с хвостом (около 44 КБ).
    Начальные данные в шестнадцатеричном формате:
    «47 0C 57 32 42 6F 4D 70 C6 01 93 5B AA DD 7E 26«
    Я не знаю, что это за блок.
    Вы можете попытаться объединить exe-заглушку с блоком rar без этого хвоста и проверить, как он работает.
    Если вы знаете, что такое данные хвоста, напишите мне.
    Возможно, это некоторые данные (сжатые или зашифрованные), которые используются установщиком.
    Эти данные помещаются после заголовка заголовка RAR end_of_archive. Я не думаю, что это часть архива rar.

    (Пояснение!)
    Эта ошибка возникает из-за того что — при создании архива RAR архиватором WinRAR, отмечена опция Добавить запись восстановления в опции Архивирование.

    А вот решение для борьбы с данной ошибкой или как ещё можно назвать — Предупреждением!

    Оказывается при открытии архива (с любого места на накопителе данных!) архиватором 7-Zip (с любого места и даже через контекстное меню) и последующим нажатием на: Информация и Извлечь ( Такая ошибка будет появляться! ) Но при нажатии тестировать все будет в порядке (так как ошибка не в архиве!)
    (Также если нажать Распаковать или же Распаковать здесь и даже Тестировать (через Контекстное меню ) то ошибка Появится снова)

    Но если просто открыть архив архиватором (в обеих случаях с любого места!) и просто (Выделить все файлы и переместить (мышью) в нужное Вам место) То в данном случае никаких ошибок или же Предупреждений не наблюдается!
    (А если короче описать данную проблему (вернее не проблему а мелкую. ) то просто в архиве RAR созданным архиватором WinRAR создаются данные (около 44 КБ) которые нужны для. (чего?)). А архиватор 7-Zip просто предупреждает так как это (Предупреждение а не Ошибка) и всё, и с легкостью это сообщение можно ИГНОРИРОВАТЬ!

    Всего записей: 221 | Зарегистр. 13-05-2016 | Отправлено: 19:41 06-06-2018 | Исправлено: Alexandr111990, 04:27 08-06-2018
    Engaged Clown

    Что это с автором?

    ———-
    Опросы ru-board’а
    Всего записей: 8311 | Зарегистр. 08-06-2006 | Отправлено: 11:51 07-06-2018
    Pasha_ZZZ

    Gold Member

    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору Engaged Clown
    Еще январская новость.
    Всего записей: 7951 | Зарегистр. 11-03-2002 | Отправлено: 12:05 07-06-2018
    Engaged Clown

    Gold Member

    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Pasha_ZZZ
    Это я помню. Только вот автор говорил — форкайте, если хотите.
    А тут взял и удалил вообще всё.
    ———-
    Опросы ru-board’а
    Всего записей: 8311 | Зарегистр. 08-06-2006 | Отправлено: 12:25 07-06-2018
    maxvlas

    Gold Member

    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Почему у меня строки повторяются? плагины что ли какие лишние у меня или что?

    Плагины что ли лишние у меня какие или глюк или у тебя также, 2 снимок видно повторяются строки

    Цитата:

    Имя: DxO PhotoLab.exe
    Размер: 597354920 байтов (569 MiB)
    CRC32: 613D5674
    CRC64: 3908C82A3D7CB5C4
    SHA256: 777B46839E4CF5826D7E47AC459D139E6683D3949AB8FEFA0BF49C1B59BA609C
    SHA1: 35FA80A52DDDEA67C1796CFD68A5414E2479743C
    BLAKE2sp: 5D085845A5F02107C56E343E32ACBF0C4564087AA821A559F1BA3F3C61EFB70B
    MD5: 5307A34621AF132BCFE2AF4FDC345715
    SHA-1: 35FA80A52DDDEA67C1796CFD68A5414E2479743C
    SHA-256: 777B46839E4CF5826D7E47AC459D139E6683D3949AB8FEFA0BF49C1B59BA609C
    SHA-512: B557E938E35B89D1FC1D8D3EBB9D47F773FEAC5422174B2B67C6A5E45873CCFC9BF77938C7A3A984AC817458BA6108FD15C04F36E1E2FC6DA60772897299439B

    Установил программу в C:\Program Files\7-Zip и отсюда взял дополнения положил к себе

    Всего записей: 6173 | Зарегистр. 08-02-2011 | Отправлено: 12:27 07-06-2018 | Исправлено: maxvlas, 12:53 07-06-2018
    Aniskin

    Full Member

    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору maxvlas
    Вот что происходит при бездумном копировании всего я вся из интернета.

    Дело в плагине WinCryptHashers, точнее в его ini файле. Откройте его и поменяйте строку SHA-1=1 на строку SHA-1=0

    Всего записей: 481 | Зарегистр. 09-01-2006 | Отправлено: 12:43 07-06-2018
    Victor_VG

    Tracker Mod

    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору maxvlas

    Ага, воспроизвёл, файл по привычке удалил. Ну теперь понятно что посмотреть — настройки дополнений. Разберусь, дам исправления настроек. Это я с ними перемудрил — мне и править.

    ———-
    Жив курилка! (Р. Ролан, «Кола Брюньон»)
    Всего записей: 23504 | Зарегистр. 31-07-2002 | Отправлено: 12:43 07-06-2018
    Pasha_ZZZ

    Gold Member

    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору maxvlas
    В файле WinCryptHashers.ini удалите те, которые уже есть в самом архиваторе
    Всего записей: 7951 | Зарегистр. 11-03-2002 | Отправлено: 12:43 07-06-2018
    Victor_VG

    Tracker Mod

    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Aniskin

    Там я не только её зря включил, но и SHA-256. Туда же подумал, но решил сначала на стенде всё проверить.

    Забыл что и сам 7-Zip хэши считает и машинально поручил эту же задачу плагину.

    Цитата:

    [Main]
    MD2=0
    MD4=0
    MD5=1

    SHA-1=0
    SHA-256=0
    SHA-384=0
    SHA-512=1

    ; ViPNet CSP 4.2
    GOST R 34.11-94=0
    GOST 34.11-2012 256=0
    GOST 34.11-2012 512=0

    [Create]
    MD5=md5:%HASH% *%FILENAME%
    SHA-1=sha1:%HASH% *%FILENAME%
    SHA-256=sha256:%HASH% *%FILENAME%
    ;SHA-384=sha384:%HASH% *%FILENAME%
    SHA-512=sha512:%HASH% *%FILENAME%

    ;CRC32=sfv:%FILENAME% %HASH%
    ;CRC64=crc64:%HASH% *%FILENAME%
    ;BLAKE2sp=blake2sp:%HASH% *%FILENAME%

    ———-
    Жив курилка! (Р. Ролан, «Кола Брюньон»)
    Всего записей: 23504 | Зарегистр. 31-07-2002 | Отправлено: 12:44 07-06-2018
    maxvlas

    Gold Member

    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Aniskin
    Pasha_ZZZ
    Victor_VG за помощь и быстрый ответ
    Victor_VG здесь наверно надо перезалить

    Что то опять не то

    Цитата:

    Имя: DxO PhotoLab.exe
    Размер: 597354920 байтов (569 MiB)
    CRC32: 613D5674
    CRC64: 3908C82A3D7CB5C4
    SHA256: 777B46839E4CF5826D7E47AC459D139E6683D3949AB8FEFA0BF49C1B59BA609C
    SHA1: 35FA80A52DDDEA67C1796CFD68A5414E2479743C
    BLAKE2sp: 5D085845A5F02107C56E343E32ACBF0C4564087AA821A559F1BA3F3C61EFB70B
    MD2: 878DA351CF2F0E67411C24D6165CE765
    MD4: 25E7F0E08F52E09F6FA5143A402CA5CF
    MD5: 5307A34621AF132BCFE2AF4FDC345715
    SHA-1: 35FA80A52DDDEA67C1796CFD68A5414E2479743C
    SHA-256: 777B46839E4CF5826D7E47AC459D139E6683D3949AB8FEFA0BF49C1B59BA609C
    SHA-384: 87AAAD97D25589522DBC3AA2B9494DFB67C24360F889D4BFE678CC29FCDBE2D41048ED1CC3DDE8FE1A21374E038C8B59
    SHA-512: B557E938E35B89D1FC1D8D3EBB9D47F773FEAC5422174B2B67C6A5E45873CCFC9BF77938C7A3A984AC817458BA6108FD15C04F36E1E2FC6DA60772897299439B
    Всего записей: 6173 | Зарегистр. 08-02-2011 | Отправлено: 12:58 07-06-2018 | Исправлено: maxvlas, 13:01 07-06-2018
    Pasha_ZZZ

    Gold Member

    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору maxvlas
    Сам руками поправь, в указанном файле. Поставь нули, нафиг их вообще столько, особенно MD2, MD4. Ну и SHA-384 — нечасто используется.
    Всего записей: 7951 | Зарегистр. 11-03-2002 | Отправлено: 13:05 07-06-2018
    maxvlas

    Gold Member

    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Pasha_ZZZпост
    Цитата:
    maxvlas
    Сам руками поправь, в указанном файле. Поставь нули, нафиг их вообще столько, особенно MD2, MD4. Ну и SHA-384 — нечасто используется.

    Я в этом не очень шарю. Там вроде стоят же нули

    Всего записей: 6173 | Зарегистр. 08-02-2011 | Отправлено: 13:13 07-06-2018
    Pasha_ZZZ

    Gold Member

    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору maxvlas
    Значит что-то не там правишь. Когда файла нет (или плагин его не находит) — выводит все что можно
    Всего записей: 7951 | Зарегистр. 11-03-2002 | Отправлено: 13:23 07-06-2018
    maxvlas

    Gold Member

    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Pasha_ZZZпост
    Цитата:
    maxvlas
    Значит что-то не там правишь

    Вот папку залил

    Всего записей: 6173 | Зарегистр. 08-02-2011 | Отправлено: 13:31 07-06-2018
    Pasha_ZZZ

    Gold Member

    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору maxvlas
    Зачем она мне? У меня нормально установленный по-человечески 7-Zip, плагины добавлены, все работает.
    Всего записей: 7951 | Зарегистр. 11-03-2002 | Отправлено: 13:42 07-06-2018
    Victor_VG

    Tracker Mod

    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору maxvlas

    Будет время — перезалью. Выше я написал содержимое ини. Правится в любом текстовом редакторе. Трудов на доли секунды, а паники до небес.

    Имя: 2.htm
    Размер: 195733 байтов (191 KiB)
    CRC32: 4152BC31
    CRC64: 27A9A4B1672FAD3D
    SHA256: 43B7D1F647C2B6AD6461EFA22DF6366FDE340792D8441EB6F5CF0FBC0FC8BF11
    SHA1: 2B52458F3F77400EE0F14C4016F54BA67C5CDF21
    BLAKE2sp: 2AD9C63C8F7D18A22CDAEF13BF0FCFFAA4BC2A7CE1CC0C455B9ECF4D57A4FB23
    MD5: 6D970B5D151A07220D6265726A41273F
    SHA-1: 2B52458F3F77400EE0F14C4016F54BA67C5CDF21
    SHA-256: 43B7D1F647C2B6AD6461EFA22DF6366FDE340792D8441EB6F5CF0FBC0FC8BF11
    SHA-512: CA1E6FD4B3F67B99D96445BE7DEB03D58C05432921463A46AF1A892AA1E71AE520075F244427CE3E8F35262C6DC0AF2F88D1D56DB42DEC5041B8E320D0CAD284

    Имя: 2.htm
    Размер: 195733 байтов (191 KiB)
    CRC32: 4152BC31
    CRC64: 27A9A4B1672FAD3D
    SHA256: 43B7D1F647C2B6AD6461EFA22DF6366FDE340792D8441EB6F5CF0FBC0FC8BF11
    SHA1: 2B52458F3F77400EE0F14C4016F54BA67C5CDF21
    BLAKE2sp: 2AD9C63C8F7D18A22CDAEF13BF0FCFFAA4BC2A7CE1CC0C455B9ECF4D57A4FB23
    MD5: 6D970B5D151A07220D6265726A41273F
    SHA-512: CA1E6FD4B3F67B99D96445BE7DEB03D58C05432921463A46AF1A892AA1E71AE520075F244427CE3E8F35262C6DC0AF2F88D1D56DB42DEC5041B8E320D0CAD284

    ЧЯДНТ?

    ———-
    Жив курилка! (Р. Ролан, «Кола Брюньон»)
    Всего записей: 23504 | Зарегистр. 31-07-2002 | Отправлено: 13:46 07-06-2018
    maxvlas

    Gold Member

    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Victor_VGпост
    Цитата:
    Добавлено:

    Вообще ничего не пойму, удалил все из ini, проверяю и такое

    Всего записей: 6173 | Зарегистр. 08-02-2011 | Отправлено: 14:28 07-06-2018
    Pasha_ZZZ

    Gold Member

    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору maxvlas
    Возможно запускается совсем не тот 7-Zip, в котором вы правите.
    Всего записей: 7951 | Зарегистр. 11-03-2002 | Отправлено: 14:31 07-06-2018

    Все ответы на андроидные ядерные вопросы: как устроено ядро Linux вообще и для Андроида в частности, механизмы взаимодействия внутри ядра, программирование ядра, обсуждение различных ошибок, возникающих при сборке ядра и при его функционировании, общие правила конфигурации ядра и прочие системные вопросы.
    Здесь обсуждается ядро на уровне исходных текстов. В силу этого к своему вопросу рекомендуется приложить ссылку на репозиторий с исходными текстами ядра, протоколы (dmesg) в текстовом виде.
    Вопросы сборки образов ядра и упаковки этих образов в формат конкретного загрузчика для конкретного аппарата лучше задать в специализированной теме раздела. Например, Самостоятельная компиляция ядра из исходников, Сборка ядра Android 4.4.x (KitKat) / 5.x.x(Lollipop) / 6.x.x (Marshmallow)/ 7.х.х (Nougat) для процессоров MTK, Помощь в разработке и портировании Android OS на устройствах МТК, Разработка ядра и прошивки Android 6.0 для Asus Zenfone Go, Разработка и портирование для устройств на платформе Spreadtrum SC7731, Разработка ядер и прошивок Redmi 4 (prada), RockChip rk3188 и новее,сборка ядра и другое и т.д.
    Тема выросла отсюда: Скрипты на shell под Android. В родительской теме обсуждаются системные вопросы функционирование Андроида в пользовательском пространстве (userspace): начальный старт, низкоуровневое взаимодействие с системными компонентами Андроида.

    Нормативные материалы по ядру Linux

    • Основополагающий документ по внутреннему устройству Андроида, Android Interfaces and Architecture, содержит раздел Kernel, в котором изложены базовые требования к ядру со стороны Андроида, освещены вопросы конфигурирования ядра, оптимизации отдельных компонент ядра и т.п.

    Некоторые материалы темы:

    • Рассказ про root в Андроиде
    • Работа Андроида на многоядерных системах. Так ли они нужны, эти 4-8 процессоров? (Обсуждение, читайте 6-10 сообщений ниже по ветке).

    По вопросам наполнения и актуализации шапки темы, Вам всегда готов помочь Куратор username11

    Сообщение отредактировал username11 — 26.07.18, 15:29


    [offline]

    Группа: Друзья 4PDA
    Сообщений: 4564
    Регистрация: 09.06.10

    Репутация: 801


    [online]

    Группа: Друзья 4PDA
    Сообщений: 3503
    Регистрация: 16.11.12
    LG G3 S

    Репутация: 1650


    [offline]

    Репутация: 280

    vitaly51370,
    В рамдиск лежит начальная конфигурация с инструкциями подготовки оборудования, монтирования разделов и запуска процесов, отвечающих за жизнь андройда. Kernel — ядро, не декомпилируется. Компилмруется с исходников из-под линукса. Да и вообще рекомендую работать с андройдом только из-под linuxа (ubuntu, linux mint — рекомендую их)

    Сообщение отредактировал Timofey777 — 21.11.14, 00:29


    [online]

    Группа: Друзья 4PDA
    Сообщений: 3503
    Регистрация: 16.11.12
    LG G3 S

    источник

    Администратор

    Группа: Главные администраторы
    Сообщений: 14349
    Регистрация: 12.10.2007
    Из: Twilight Zone
    Пользователь №: 1

    Продолжаем цикл статей о создании файловой системы в ядре Linux, основанный на материалах курса ОС в Академическом университете .

    В прошлый раз мы настроили окружение, которое понадобится нам, чтобы знакомится с ядром. Затем мы взглянули на загружаемые модули ядра и написали простой «Hello, World!». Ну и наконец, мы написали простую и бесполезную файловую систему. Пришло время продолжить.

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

    Почему так мало? Дело в том, что в этом посте нам потребуется определить структуру нашей файловой системы — то как она будет хранится на диске. Кроме того мы столкнемся с парой интересных моментов, таких как SLAB и RCU. Все это потребует некоторых объяснений — много слов и мало кода, так что пост и так будет довольно объемным.

    Наша файловая система должна быть простой, поэтому и хранится на диске она будет просто:

    • data blocks — блоки полезных данных, т. е. содержимое файлов и папок;
    • table of inodes — таблица индексных узлов; количество индексных узлов определяется при форматировании и хранятся они в непрерывной последовательности блоков;
    • free inodes — битовая карта свободных/занятых индексных узлов, которая занимает ровно 1 блок;
    • free blocks — битовая карта свободных/занятых блоков, так же занимает 1 блок;
    • super block — очевидно, суперблок нашей файловой системы; он хранит размер блока, количество блоков в таблице индексных узлов, номер индексного узла корневой папки;

    Собственно похожая разметка диска используется и в других файловых системах. Например, группа блоков в ext2/3 имеет похожую структуру, только ext2/3 работает с несколькими такими группами, а мы ограничимся одной. Такой формат считается устаревшим, и новые файловые системы отходят от него. Например, btrfs использует более интересную схему , которая дает ряд преимуществ над семейством ext. Но да вернемся к нашим баранам.

    Мы определили, что суперблок и битовые карты блоков/индексных узлов занимают первые три блока файловой системы, а сколько занимает таблица индексных узлов? Вообще говоря, фиксировать эту величину не правильно, она сильно зависит от того, как файловая система будет использоваться. Например, если вы собираетесь хранить преимущественно большие файлы, то имеет смысл сделать эту таблицу поменьше, т. к. маловероятно, что вы исчерпаете индексные узлы раньше, чем пространство на диске. С другой стороны, если вы собираетесь хранить много мелких файлов, есть вероятность исчерпать индексные узлы раньше, чем свободное место на диске, если таблица будет слишком маленькой.

    В утилите mke2fs, которая используется для форматирования диска под файловые системы ext2/3, есть ключик -i , который указывает на какой объем диска нужно создавать индексный узел, т. е. если указать -i 16384, то на каждые 16 килобайт дискового пространства будет создано по индексному узлу. Я воспользуюсь самым простым вариантом — буду создавать индексный узел на каждые 16 Кб дискового пространства, без возможности изменения этого значения (пока по крайней мере).

    Последний общий момент, который стоит затронуть — размер блока. Файловая система может работать с блоками разного размера, я буду поддерживать блоки в 512, 1024, 2048 и 4096 байт — ничего необычного. Это связано с тем, что с блоками, влезающими в страницу работать проще (мы вернемся к этому чуть позже), но делать так совсем не обязательно, более того, большие размеры блоков могут способствовать большей производительности.

    Вообще подбор правильного размера блока для классических файловых систем — довольно занятная тема. Например, в известной книге по ОС приводятся информация о том, что при размере блока в 4 Кб 60 — 70% файлов будут помещаться в один блок. Чем больше файлов помещается в один блок, тем меньше фрагментация, выше скорость чтения, но и больше места используется впустую. В нашем случае, ко всему прочему, размер блока является главным ограничителем файловой системы — при размере блока в 4 Кб битовая карта свободных блоков может покрыть всего 128 Мб дискового пространства.

    Настало время написать немного кода. Начнем со структур, которые мы будем использовать, начиная с самой простой:

    struct aufs_disk_super_block
    __be32 dsb_magic;
    __be32 dsb_block_size;
    __be32 dsb_root_inode;
    __be32 dsb_inode_blocks;
    >;

    Структура супер блока хранится в самом начале 0 блока диска. Начинается она с магического числа, по нему мы можем убедиться, что на диске хранится именно aufs (я упоминал об этом в предыдущий раз).

    Учитывая, что мы будем поддерживать разные размеры блоков (что, впрочем, не потребует от нас никаких усилий), мы должны знать какой размер используется в данной конкретной файловой системе, и суперблок хранит для нас эту информацию в поле dsb_block_size.

    Кроме того, в поле dsb_inode_blocks хранится количество блоков в таблице индексных узлов — я уже упоминал, что размер этой таблицы может быть различным.

    Поле dsb_root_inode хранит номер индексного узла корневого каталога. Конечно, хранить его не обязательно, можно просто использовать фиксированный номер для корня, но тогда структура будет совсем пустой, а с ним она кажется солиднее.

    Обратите внимание, что для полей используются типы фиксированного размера. Это потому что мы будем записывать эту структуру на диск «как есть». Однако зафиксировать размер недостаточно, нужно зафиксировать еще порядок байт. Я буду использовать big endian , он же сетевой порядок байт, о чем говорит название типа (__be32).

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

    Тип __be32, по факту, является синонимом uint32_t, но его название подчеркивает, что переменная хранит данные в big endian (этакий способ документации). В ядре есть аналогичный тип и для little endian.

    Теперь посмотрим, пожалуй, на самую главную структуру файловой системы — индексный узел:

    struct aufs_disk_inode
    __be32 di_first;
    __be32 di_blocks;
    __be32 di_size;
    __be32 di_gid;
    __be32 di_uid;
    __be32 di_mode;
    __be64 di_ctime;
    >;

    Индексный узел, в первую очередь, определяет где на диске хранится файл/каталог. Способы хранения файлов могут быть самыми разнообразными, я буду использовать довольно простой — один экстент на один файл. Экстент — непрерывная последовательность блоков диска, т. е. каждый файл/каталог будет храниться в непрерывной последовательности блоков. Поля di_first и di_blocks хранят первый блок и количество блоков в экстенте соответственно.

    Тут вы скажете, а как же в такой файловой системе дописывать данные в конец файла и добавлять записи в каталог? Действительно, полноценная реализации операций, приводящих к изменению размера файла/каталога, при таком способе хранения — это головная боль (и это не говоря об эффективности такой реализации), поэтому мы не будем делать полноценную реализации записи, но об этом в другой статье.

    Однако у такой организации есть и положительные моменты — файлы не фрагментированы, а это хорошо влияет на скорость последовательного чтения. Поэтому такая структура может замечательно использоваться в файловых системах рассчитанных только на чтение, например, в iso 9660 (хотя и она уже поддерживает фрагментацию файлов).

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

    Кроме указания на место на диске, индексный узел так же хранит реальный размер файла в поле di_size. И правда, не обязан же размер файла точно попадать в размер блока.

    Поля di_gid и di_uid — идентификаторы группы и пользователя. Сохранять такую информацию в файловой системе не всегда имеет смысл, я вставил их для примера.

    Поле di_mode — хранит права доступа для группы владельца файла, владельца файла и всех остальных пользователей. Раз уж я сохранил группу и владельца то и права доступа стоит сохранить. Еще di_mode хранит тип объекта, который описывает индексный узел, например, является ли объект каталогом или файлом.

    Наконец поле di_ctime хранит дату создания файла. Обычно файловые системы хранят вместе с датой создания еще и даты последней модификации и доступа к файлу, но мы забьем на них.

    Итак, когда мы определили формат хранения файловой системы на диске, пора написать утилиту, которая приведет диск в правильный формат. Диск в Linux — это просто файл (тут уместно вспомнить известное дизайнерское решение Unix ). Так что форматирование диска — просто запись в файл нужных данных. А нужные данные в нашем случае — суперблок, битовые карты, и корневой каталог (пока пустой).

    Чтобы не превращать статью о ядре Linux в статью о C++ (особенно в свете отношения Линуса к последнему ) я предлагаю вам самостоятельно разобраться с исходниками на github, но кратко пройдусь по основным классам:

    • Configuration — класс который хранит конфигурацию будущей файловой системы (размер блока, размер таблицы индексных узлов, количество блоков, имя файла устройства).
    • Block — представляет один блок диска. Данные пишутся и читаются с диска блоками.
    • BlocksCache — предоставляет доступ к блокам.
    • Inode — обертка над индексным узлом. Она скрывает преобразования порядка байт, запись и чтение данных индексного узла из блока.
    • SuperBlock — обертка на суперблоком. Как и в случае с Inode скрывает запись и чтение из блока, заполняет битовые карты, выделяет индексные узлы и блоки, т. е. по факту выполняет форматирование.

    Утилита позволяет изменять размер блока через ключи -s или —block_size, и количество блоков, которые будут использованы под файловую систему через ключи -b или —blocks.

    В целом утилита совсем не хитрая, но многие могут справедливо подумать, что код слишком навороченный для такой простой задачи. Дело в том, что в первую очередь мы научим файловую систему читать с диска, а потом уже возьмемся за запись. Но, чтобы проверить работу нашего драйвера, нужно записать что-то на диск. Поэтому мы в последствии добавим в утилиту возможность импортировать файлы/каталоги при форматировании диска, что очень нам поможет.

    Теперь вернемся к нашему загружаемому модулю. Начнем мы с чтения суперблока с диска. Но перед этим заведем еще одну структуру для суперблока:

    struct aufs_super_block
    uint32_t asb_magic;
    uint32_t asb_inode_blocks;
    uint32_t asb_block_size;
    uint32_t asb_root_inode;
    uint32_t asb_inodes_in_block;
    >;

    Эта структура будет представлять суперблок в памяти. Идея простая — читаем с диска aufs_disk_super_block и преобразуем его в aufs_super_block выполняя преобразования порядка байт и попутно вычисляя всякие полезные данные (в данном случае asb_inodes_in_block). Вообще эта структура — отличное место для всяких глобальных переменных файловой системы.

    Вспоминая прошлый пост, мы имеем уже три структуры для представления суперблока:

    • super_block — структура, которую предоставляет ядро;
    • aufs_disk_super_block — структура, которая хранится на диске;
    • aufs_super_block — еще одна структура, которая будет хранится в памяти;

    Две структуры — это понятно, но зачем нам третья? Дело в том, что Linux не знает ничего о нашей файловой системе, поэтому вполне вероятно, что super_block (как и inode, как и любая другая структура ядра Linux) не содержит всех нужных нам полей. Поэтому мы вынуждены заводить свои дополнительные структуры и связывать их со структурами ядра. Как же их связать?

    В ядре есть два распространенных способа организации такой связи (назовем их композицией и наследованием). Для супер блока мы воспользуемся композицией. Этот способ требует поддержки со стороны ядра — внутри структуры super_block есть интересное поле:

    struct super_block .
    void *s_fs_info;
    .
    >;

    В это поле мы можем сохранить указатель на любые данные, собственно, туда мы сохраним указатель на aufs_super_block. И везде, где у нас есть доступ к структуре super_block мы можем получить доступ и к структуре aufs_super_block. Но да это все лирика, наша задача прочитать суперблок с диска. Для этого мы напишем пару функций:

    static struct aufs_super_block *aufs_super_block_read(struct super_block *sb)
    struct aufs_super_block *asb = (struct aufs_super_block *)kzalloc(sizeof(struct aufs_super_block), GFP_NOFS);
    struct aufs_disk_super_block *dsb = NULL;
    struct buffer_head *bh = NULL;

    if (!asb)
    pr_err(«aufs cannot allocate super blockn»);
    return NULL;
    >

    bh = sb_bread(sb, 0);
    if (!bh)
    pr_err(«cannot read 0 blockn»);
    goto free_memory;
    >

    dsb = (struct aufs_disk_super_block *)bh->b_data;
    aufs_super_block_fill(asb, dsb);
    brelse(bh);

    if (asb->asb_magic != AUFS_MAGIC)
    pr_err(«wrong magic number %un», (unsigned)asb->asb_magic);
    goto free_memory;
    >

    free_memory:
    kfree(asb);
    return NULL;
    >

    Первое, что делает эта функция — это выделяет память под структуру суперблока. Для выделения памяти в ядре есть довольно много способов, kzalloc (и kmalloc вместе с ним) — самый простой. Работает как и обычный malloc, только требует передачи дополнительного набора флагов. Отличие kzalloc от kmalloc в том, что первый заполняет выделенную память нулями (что просто сводится к передаче дополнительно флага внутрь kmalloc).

    Я упомянул о флагах, зачем они? Дело в том, что разные части ядра должны удовлетворять различным гарантиям. Например, в контексте обработки сетевого пакета нельзя блокироваться, а чтобы задействовать DMA требуется выделять память в специальном регионе памяти. Так как выделение памяти используется везде, требуется механизм «настройки». В нашем случае используется флаг GFP_NOFS, который говорит, что аллокатор памяти не будет обращаться к средствам файловой системы, что логично при реализации файловой системы, хотя в данном конкретном случае и не обязательно.

    Естественно в ядре не забываем проверить, что память была выделена без проблем.

    Следующий принципиальный момент — вызов функции sb_bread . Вот оно чтение с диска! Функция принимает указатель на суперблок и номер блока, который нужно прочитать — совсем просто. Возвращает функция указатель на структуру buffer_head , а сами данные блока доступны через поле b_data этой структуры.

    Естественно и в этом случае не забываем проверить, что чтение прошло удачно.

    Далее мы просто преобразуем указатель на char к указателю на структуру aufs_disk_super_block. Функция aufs_super_block_fill заполняет структуру aufs_super_block используя aufs_disk_super_block не делая ничего необычного:

    static inline void aufs_super_block_fill(struct aufs_super_block *asb,
    struct aufs_disk_super_block const *dsb)
    asb->asb_magic = be32_to_cpu(dsb->dsb_magic);
    asb->asb_inode_blocks = be32_to_cpu(dsb->dsb_inode_blocks);
    asb->asb_block_size = be32_to_cpu(dsb->dsb_block_size);
    asb->asb_root_inode = be32_to_cpu(dsb->dsb_root_inode);
    asb->asb_inodes_in_block =
    asb->asb_block_size / sizeof(struct aufs_disk_inode);
    >

    Как не трудно догадаться функция be32_to_cpu преобразует число из big endian в порядок байт используемый платформой.

    После того, как мы закончили работу с блоком его нужно освободить, для этого существует функция brelse . Она на самом деле просто уменьшает счетчик ссылок на этот блок. Блок не будет освобожден сразу, как только счетчик ссылок дойдет до 0 — для блоков в ядре работает сборщик мусора, который без серьезной необходимости не будет освобождать блок. Причина в том, что чтение блоков с диска — довольно дорогая операция, поэтому разумно поддерживать кеш прочитанных блоков, и при повторном чтении того же блока возвращать уже прочитанный (если, конечно, он еще присутствует в кеше).

    Последнее что мы делаем — проверяем магическое число, нужно же убедиться, что на диске хранится действительно aufs.

    Для обративших внимание на goto, в ядре goto используется довольно часто. В основном, для организации обработки ошибок — в языке C нет исключений, а идея разделения основного пути выполнения и обработки ошибок довольно привлекательна, тут то нам и приходит на выручку goto. В данном случае использование goto почти ничего не дает — я вставил его сюда намерено, как пример того, зачем он используется. Вообще среди разработчиков ядра ненавистников goto не так уж и много, так что есть места в коде злоупотребляющие злосчастным оператором — стоит быть к этому готовым.

    Внимательный читатель, наверно, обратил внимание на одну нестыковку. Как я уже говорил, файловые системы могут работать с разными размерами блока, и хранится эта информация скорее всего в суперблоке. Так какого же размера блок прочитает функция sb_bread при чтении суперблока? В нашем случае все просто, по-умолчанию, размер блока устанавливается в размер блока блочного устройства (как много блоков. ). И мы надеемся, что его размера достаточно для структуры суперблока — в нашем случае так и есть.

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

    static int aufs_fill_sb(struct super_block *sb, void *data, int silent)
    struct inode *root = NULL;
    struct aufs_super_block *asb = aufs_super_block_read(sb);

    sb->s_magic = asb->asb_magic;
    sb->s_fs_info = asb;
    sb->s_op = &aufs_super_ops;

    if (sb_set_blocksize(sb, asb->asb_block_size) == 0)
    pr_err(«device does not support block size %un»,
    (unsigned)asb->asb_block_size);
    return -EINVAL;
    >

    root = aufs_inode_get(sb, asb->asb_root_inode);
    if (IS_ERR(root))
    return PTR_ERR(root);

    sb->s_root = d_make_root(root);
    if (!sb->s_root)
    pr_err(«aufs cannot create rootn»);
    return -ENOMEM;
    >

    Как я уже упоминал, мы сохраняем указатель на aufs_super_block в поле s_fs_info. Кроме того мы устанавливаем правильный размер блока вызовом sb_set_blocksize . Как говорит комментарий внутри функции размер блока должен быть от 512 байт до размера страницы — этим и обусловлен наш выбор размеров блока. Если файловая система должна работать с большим размером блока — потребуются дополнительные усилия (впрочем не такие большие).

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

    static void aufs_put_super(struct super_block *sb)
    struct aufs_super_block *asb = (struct aufs_super_block *)sb->s_fs_info;
    if (asb)
    kfree(asb);
    sb->s_fs_info = NULL;
    pr_debug(«aufs super block destroyedn»);
    >

    Не трудно догадаться что парной к функции kmalloc является функция kfree , точнее даже функции, так как есть несколько реализаций kfree в ядре (еще тут и тут ), но не будем углубляться в детали.

    Еще одно важное изменение внутри функции aufs_fill_sb — вызов aufs_inode_get. В прошлой статье мы создавали фиктивный inode, теперь мы научимся читать их с диска.

    Но перед этим обращу ваше внимание на интересный момент — пару IS_ERR и PTR_ERR . Это простые преобразования указателей к числу и обратно, основанные на том, что ядро владеет полной информацией о расположении своей памяти и, соответственно, о том какие биты указателя можно использовать не по прямому назначению. Это самый простой пример использования знания о структуре указателя, есть и более интересные, причем не только в ядре .

    Работу с индексными узлами мы начнем с расширения структуры super_operations , с которой мы познакомились в прошлый раз. Теперь мы заполним ее таким образом:

    static struct super_operations const aufs_super_ops = .alloc_inode = aufs_inode_alloc,
    .destroy_inode = aufs_inode_free,
    .put_super = aufs_put_super,
    >;

    Мы добавили в нее еще пару указателей на функции aufs_inode_alloc и aufs_inode_free. Это специфичные функции для аллокации и освобождения inode, тут то мы и столкнемся с SLAB (с этим зверем мы, на самом, деле уже столкнулись в виде kmalloc) и RCU (совсем чуть-чуть).

    Итак выделение памяти для индексного узла начнем с определения еще одной структуры — представления индексного узла в памяти (как это было с суперблоком):

    struct aufs_inode
    struct inode ai_inode;
    uint32_t ai_block;
    >;

    В этот раз мы будем использовать «наследование» вместо композиции. Наследование в C выглядит совсем не хитро (что не удивительно, учитывая, что в C нет поддержки наследования). Для этого мы просто делаем первым полем структуры aufs_inode базовую структуру (базовый класс) — структуру inode . Таким образом указатель на aufs_inode можно использовать в качестве указателя на inode, как впрочем и наоборот (если конечно мы точно знаем, что данный указатель ссылается именно на aufs_inode).

    По сравнению с композицией, «наследование» само по себе не требует поддержки со стороны ядра, кроме того оно выгоднее с точки зрения числа выделений памяти — на каждый индексный узел требуется одно выделение, вместо двух (как это было с суперблоком). Так же в отличие от суперблока, почти все нужные поля уже присутствуют внутри inode. Однако это скорее исключение, чем правило, ведь наша файловая система хранит данные на диске очень просто.

    Для выделения памяти под индексные узлы мы будем использовать SLAB аллокатор. SLAB аллокатор — кэширующий аллокатор, который позволяет выделять блоки памяти одного размера. Не трудно догадаться, что за счет этого ограничения можно упростить управление памятью и ускорить выделение памяти. SLAB аллокатор запрашивает у ОС большие куски памяти и выделяет из них небольшие участки по запросу, соответственно, запросы к менеджеру памяти ОС происходят реже, а запросы пользователей удовлетворяются быстрее.

    Но изначально выигрыш в скорости выделения памяти при использовании SLAB-ов был не только (и не столько) за счет более простого управления памяти, а за счет сокращения расходов на инициализацию этой памяти. Действительно, SLAB аллокатор зачастую используется не просто для выделения объектов одного размера, а для выделения объектов одного типа, что позволяет пропустить инициализацию некоторых полей при повторном выделении одного участка памяти. Например, мьютексы, спинлоки и другие подобные объекты при освобождении объекта скорее всего имеют «правильное» значение, и при повторном выделении не нуждаются в повторной инициализации. За деталями и результатами измерений прошу обратиться к оригинальной статье .

    На данный момент в Linux имеется три различных вида SLAB аллокаторов — SLAB, SLUB и SLOB. Не будем вдаваться в различия между ними, интерфейс они предоставляют один и тот же. Итак, для создания SLAB аллокатора мы будем использовать следующую функцию:

    int aufs_inode_cache_create(void)
    aufs_inode_cache = kmem_cache_create(«aufs_inode»,
    sizeof(struct aufs_inode),
    0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
    aufs_inode_init_once);

    if (aufs_inode_cache == NULL)
    return -ENOMEM;

    При создании SLAB-а функции kmem_cache_create передаются имя, размер объекта, функция инициализации (функция, которая будет вызвана только один раз, при первом выделении объекта), и еще пара параметров, в суть которых я вдаваться не буду. Но чтобы не оставлять интересующихся совсем без информации я скажу, что создание SLAB-а для индексных узлов во всех файловых системах выглядит одинаково — различия не существенны.

    Вызывать функцию aufs_inode_cache_create мы будем при загрузке модуля, перед регистрацией файловой системы в ядре. Есть так же парная функция, которую мы вызовем при выгрузке модуля:

    void aufs_inode_cache_destroy(void)
    rcu_barrier();
    kmem_cache_destroy(aufs_inode_cache);
    aufs_inode_cache = NULL;
    >

    Функция kmem_cache_destroy уничтожает SLAB аллокатор. К моменту уничтожения все объекты из этого кеша должны быть освобождены, иначе мы получим неприятное сообщение об ошибке в системном логе, вместе с целым букетом трудно отлавливаемых неприятностей.

    Теперь обещанное касание RCU. В двух словах, RCU — распространенный в ядре механизм синхронизации (а также безопасного освобождения памяти для lock-free алгоритмов). RCU сам по себе заслуживает отдельной статьи и на хабре есть такая . Более того, создатель этой техники, а по совместительству, мейнтейнер RCU в ядре Linux написал целую книгу , в которой коснулся и своего детища тоже.

    Но нам из всего зоопарка RCU функций необходимо разобраться только с rcu_barrier (как и с kfree, есть и другая реализация этой функции тут ). Если по-простому, то эта функция дождется, пока все отложенные работы над защищенными RCU данными завершатся, после чего вернет управление тому, кто ее вызвал, соответственно функция блокирующая. Зачем нам это нужно мы увидим чуть ниже.

    Вернемся к выделению памяти, рассмотрим уже упомянутую выше функцию:

    struct inode *aufs_inode_alloc(struct super_block *sb)
    struct aufs_inode *const i = (struct aufs_inode *)
    kmem_cache_alloc(aufs_inode_cache, GFP_KERNEL);

    Она использует созданный ранее SLAB аллокатор (через одну из реализаций kmem_cache_alloc ) и возвращает указатель на inode — ничего необычного, а вот функция освобождения немного более интересная:

    Тут мы опять сталкиваемся с RCU. Тут стоит сказать пару слов о lock-free алгоритмах, проблема таких алгоритмов в том, что без блокировок нет гарантий, что объект не используется параллельно каким-либо другим потоком исполнения, а значит освобождать память занятую этим объектом нельзя — другой поток может хранить указатель на него. Поэтому в lock-free алгоритмах приходится задумываться о стратегиях безопасного освобождения памяти, а RCU предоставляет средства для решения этой проблемы. Все реализации функции call_rcu откладывают выполнение некоторой функции (в нашем случае функции освобождения aufs_free_callback) до тех пор, пока это не станет безопасным. А уже упомянутая выше rcu_barrier ждет завершения всех отложенных функций.

    Вы устали? Ничего страшного, мы уже приближаемся к финалу. Теперь мы будем читать индексный узел с диска. Для этого я написал уже упомянутую функцию aufs_inode_get:

    struct inode *aufs_inode_get(struct super_block *sb, uint32_t no)
    struct aufs_super_block const *const asb = AUFS_SB(sb);
    struct buffer_head *bh = NULL;
    struct aufs_disk_inode *di = NULL;
    struct aufs_inode *ai = NULL;
    struct inode *inode = NULL;
    uint32_t block = 0, offset = 0;

    inode = iget_locked(sb, no);
    if (!inode)
    return ERR_PTR(-ENOMEM);

    ai = AUFS_INODE(inode);
    block = aufs_inode_block(asb, no);
    offset = aufs_inode_offset(asb, no);

    pr_debug(«aufs reads inode %u from %u block with offset %un»,
    (unsigned)no, (unsigned)block,
    (unsigned)offset);

    bh = sb_bread(sb, block);
    if (!bh)
    pr_err(«cannot read block %un», (unsigned)block);
    goto read_error;
    >

    di = (struct aufs_disk_inode *)(bh->b_data + offset);
    aufs_inode_fill(ai, di);
    brelse(bh);

    read_error:
    pr_err(«aufs cannot read inode %un», (unsigned)no);
    iget_failed(inode);

    Объяснение я начну с простых моментов — функции AUFS_SB и AUFS_INODE позволяют получить указатель на структуры aufs_super_block и aufs_inode, через указатели на super_block и inode соответственно. Я не буду приводить их код (он довольно простой), потому что я уже описал выше как эти структуры связаны.

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

    А вот теперь интересный момент — пара функций iget_locked и unlock_new_inode . Как и в случае с блоками ядро поддерживает кеш inode-ов, это нужно не только для того, чтобы лишний раз не читать индексный узел с диска. Дело в том, что один и тот же файл/каталог может быть открыт сразу несколькими процессами, в этом случае все они должны оперировать одним экземпляром inode, чтобы их можно было синхронизировать друг с другом. Аналогичное рассуждение справедливо для блоков пожалуй даже в большей степени, так что к блока это тоже применимо.

    Итак функция idet_locked в первую очередь ищет inode в кеше и выделяет память под новый, если inode не найден. Если индексный узел был выделен заново, а не найден в кеше, в поле i_state будет установлен флаг I_NEW, а также будет захвачен спинлок этого узла (поле i_lock). Поэтому наша функция сначала проверяет поле i_state, и если флаг I_NEW сброшен просто возвращаем кешированный inode. В противном случае мы должны заполнить inode, для этого мы читаем нужный блок с диска (с помощью уже известной вам sb_bread).

    Функция aufs_inode_fill как раз и занимается заполнением:

    static void aufs_inode_fill(struct aufs_inode *ai,
    struct aufs_disk_inode const *di)
    ai->ai_block = be32_to_cpu(di->di_first);
    ai->ai_inode.i_mode = be32_to_cpu(di->di_mode);
    ai->ai_inode.i_size = be32_to_cpu(di->di_size);
    ai->ai_inode.i_blocks = be32_to_cpu(di->di_blocks);
    ai->ai_inode.i_ctime.tv_sec = be64_to_cpu(di->di_ctime);
    ai->ai_inode.i_mtime.tv_sec = ai->ai_inode.i_atime.tv_sec =
    ai->ai_inode.i_ctime.tv_sec;
    ai->ai_inode.i_mtime.tv_nsec = ai->ai_inode.i_atime.tv_nsec =
    ai->ai_inode.i_ctime.tv_nsec = 0;
    i_uid_write(&ai->ai_inode, (uid_t)be32_to_cpu(di->di_uid));
    i_gid_write(&ai->ai_inode, (gid_t)be32_to_cpu(di->di_gid));
    >

    Опять никакой магии, за исключением пары функций i_uid_write и i_gid_write . Но и они не делают ничего особенного — просто присваивают значения соответствующим полям.

    Кроме того обращу внимание на представление времени в виде структуры timespec , эта структура состоит всего из пары чисел — количество секунд и наносекунд. Т. е. потенциально время можно хранить довольно точно.

    Наконец в самом конце функции мы должны освободить спинлок и вернуть указатель, для этого и используется функция unlock_new_inode.

    Пост получился действительно большим и даже так не покрывает всех моментов. Я постарался объяснить все ключевые части реализации.

    Все исходники доступны по ссылке. В репозитории теперь две папки — kern и user. Как не трудно догадаться, одна хранит код нашего модуля, вторая — код утилиты для форматирования. Кода стало больше, а значит вероятность появления в нем ошибок стала больше — замечания, исправления, любая конструктивная критика и pull request-ы приветствуются.

    Чтобы получить образ диска для монтирования можно сделать так:

    dd bs=1M count=100 if=/dev/zero of=image
    ./mkfs.aufs ./image

    Теперь можно использовать файл image так, как это показано в предыдущем посте.

    Из примеров кода в этой статье убрано некоторое количество дебажного вывода, но если вы буде использовать код из репозитория, вы сможете убедиться, что модуль работает используя команду dmesg.

    источник

    Victor_VG

    Tracker Mod

    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Pasha_ZZZ

    А кстати, вполне возможно коли стоят две и более копии.

    источник


    [online]

    Группа: Друзья 4PDA
    Сообщений: 5990
    Регистрация: 09.11.10
    Xiaomi Redmi 4X 3/32

    Репутация: 850

    Источники:
    • http://4pda.ru/forum/index.php?showtopic=622232&st=2400
    • http://dml.compkaluga.ru/forum/index.php?showtopic=92788
    Читайте также:  Чем полезна черника форте ягоды