Usrmerge: различия между версиями

Материал из ALT Linux Wiki
 
(не показано 20 промежуточных версий 3 участников)
Строка 2: Строка 2:


= Usrmerge =
= Usrmerge =
'''''Точный план действий сейчас вырабатывается, и его подробности могут измениться.'''''
Начиная с 23 апреля 2024 реализовано в Sisyphus. Текущие проблемы с обновлением описаны [[Branches/Sisyphus#Ошибки_обновления | тут]] и [[Usrmerge#User-visible_impact | тут]]
Статус воплощения отслеживается в {{altbug|46738}}.
 
== Глоссарий ==
'''{{term|merged-usr}}'''-иерархией называется такая FHS-подобная иерархия каталогов, в которой все неизменяемые при работе файлы из операционной системы (т. е. из состава пакетов в репозитории ОС) помещаются либо внутри префикса ({{path|/usr}}), либо их местоположение является ссылкой внутрь префикса. В такой иерархии {{path|/bin}}, {{path|/lib}} и т. д. будут симлинками на {{path|/usr/bin}}, {{path|/usr/lib}} и т. д. Иерархия, не отвечающая этому правилу (например, та, которую создавал инсталлятор до p11), называется '''{{term|unmerged-usr}}'''.
 
'''{{term|split-usr}}'''-конфигурация подразумевает, что исполнимый файл в процессе pid 1 из корневой файловой системы стартует до монтирования {{path|/usr}}, расположенного на отдельном разделе. {{term|split-usr}} не следует путать с {{term|unmerged-usr}}, хоть системы со свойством {{term|split-usr}} и являются подмножеством систем {{term|unmerged-usr}}.


== Введение ==
== Введение ==
Строка 26: Строка 30:


== Proposed changes ==
== Proposed changes ==
Необходимые действия можно разбить на две стадии.
Необходимые действия можно разбить на три стадии.


=== Стадия 1 ===
=== Стадия 1 ===
* На стадии brp завершаться с ошибкой, если обнаружены разные файлы в {{path|/bin/x}} и {{path|/usr/bin/x}}, ...
1) Определить, что слиянию с аналогами внутри /usr подлежат следующие каталоги:
 
1. Определить, что слиянию с аналогами внутри /usr подлежат следующие каталоги:
<pre>
<pre>
   /bin
   /bin
Строка 42: Строка 44:
На каждой машине есть некоторые каталоги из этого списка; они и будут перенесены.
На каждой машине есть некоторые каталоги из этого списка; они и будут перенесены.


2. Тем или иным образом научить rpm создавать симлинк вида
2) Ввести brp-модуль {{term|brp-dupe-bin}}, который на стадии brp завершается с ошибкой, если обнаружены разные файлы в {{path|/bin/x}} и {{path|/usr/bin/x}}, а если один из них есть ссылка на другой, устанавливает две копии такого файла по обоим путям с совпадающими атрибутами и контентом.
Это нужно, чтобы приблизительно 22 пакета могли устанавливаться на все варианты иерархий: и на unmerged-usr, и на merged-usr. Создавать жёсткую ссылку нежелательно: если {{path|/bin/x}} и {{path|/usr/bin/x}} лежат на разных файловых системах, такой пакет туда не установится: RPM не рассечёт жёсткую ссылку на два одинаковых файла.
Большинство пакетов, требующих исправления, достаточно будет просто пересобрать со специальным brp-модулем.
 
Некоторые пакеты, например, {{pkg|vim-common}}, упаковывают разные
файловые объекты в {{path|/bin}} и {{path|/usr/bin}}; другие пакеты ставят файлы прямо
в {{path|%buildroot/bin}}. Их потребуется исправить руками (готово: [[altbug:49541]]). (Справедливости ради,
многие из них и так понадобится обновить)
 
Полный список таких будущих конфликтов на 2024-03-16:
<pre>
<pre>
  /bin/x -> ../usr/bin/x
[('bin/bsh', {'ash', 'bsh'}),
('bin/ksh', {'ksh', 'pdksh'}),
('bin/mail', {'mailutils', 'mailx'}),
('bin/ex', {'vi-traditional', 'vim-common', 'vim-minimal'}),
('bin/rview', {'vim-common', 'vim-minimal'}),
('bin/vi', {'vi-traditional', 'vim-minimal'}),
('sbin/halt', {'shepherd', 'systemd-sysvinit', 'sysvinit'}),
('sbin/reboot', {'shepherd', 'systemd-sysvinit', 'sysvinit'}),
('sbin/shutdown', {'shepherd', 'systemd-sysvinit', 'sysvinit'})]
</pre>
</pre>
..., если в пакете существует {{path|/usr/bin/x}} и <tt>Provides: /bin/x</tt>. Аналогично для всех каталогов из списка 1. Таким образом, на переходном этапе будет не нужно указывать в <tt>%files</tt> пакетов все эти симлинки, чтобы потом их убирать, и пакеты продолжат удовлетворять зависимостям на такие файлы.
Из перечисленных множеств пересекающихся в будущем пакетов многие уже явно конфликтуют друг с другом.
 
3) Подготовить пакет {{pkg|filesystem}} версии 3: поместить в нём скрипт, срабатывающий в <tt>%pretrans</tt> и переносящий содержимое каталогов из списка 1 внутрь {{path|/usr}} (т. е. под префикс).
Сценарий файлтриггера должен будет давать предельно ясную информацию и диагностические сообщения на стандартные потоки.
Нужно будет либо положиться на static coreutils, либо очень осторожно обращаться с обычными и dynamic linker.
 
4) [[Usrmerge/UpgradePlan|Подготовить p10]] к плавному обновлению на p11 и предшествующие ему срезы сизифа.


Важно, чтобы сначала удалялся старый путь, как обычно при установке
=== Стадия 2 ===
пакета, а симлинк возникал после этой фазы.
Этот пункт вступает в действие на каждой машине индивидуально при
обновлении её пакетов.
Перед транзакцией, в которой ставят новый пакет {{pkg|filesystem}}, скрипт из пункта 2 вводит симлинки, завершая процесс usrmerge на данной системе.


2.1) Бекпортировать поддержку в p10.
Каждая инсталляция перейдёт к ней независимо, по мере обновления пакетов.


3) Подготовить пакет {{pkg|filesystem}} версии 3: поместить в нём файлтриггер,
=== Стадия 3 ===
который проверяет, не состоят ли каталоги из списка 1 целиком из
[[Team|Мейнтейнеры]] пакетов перейдут к ней после выпуска [[Одиннадцатая платформа|p11]].
симлинков внутрь {{path|/usr}}, и превращает такой каталог с симлинками в симлинк
на каталог.
Сценарий файлтриггера должен будет давать предельно ясную информацию и
диагностические сообщения на стандартные потоки. Нужно будет либо
положиться на static coreutils, либо очень осторожно обращаться с
обычными и dynamic linker.


4) Заменить макросы, использующие старые каталоги (<tt>%_udevrulesdir</tt>,
Заменить макросы, использующие старые каталоги (<tt>%_udevrulesdir</tt>,
<tt>%_tmpfilesdir</tt> и другие), и пересобрать с ними пакеты, что-либо
<tt>%_tmpfilesdir</tt> и другие), и <span id="MigrateDirMacros">пересобрать с ними пакеты, что-либо
помещающие в эти каталоги.
помещающие в эти каталоги</span>.
Приближённое число затрагиваемых бинарных пакетов:
Приближённое число затрагиваемых бинарных пакетов:
<pre>
<pre>
Строка 78: Строка 99:
При обновлении на эти пакеты будет действовать правило 2, поэтому их
При обновлении на эти пакеты будет действовать правило 2, поэтому их
содержимое будет доступно.
содержимое будет доступно.
Некоторые пакеты, например, {{pkg|vim-common}}, сейчас упаковывают разные
файловые объекты в {{path|/bin}} и {{path|/usr/bin}}; другие пакеты ставят файлы прямо
в {{path|%buildroot/bin}}. Их потребуется исправить руками. (Справедливости ради,
многие из них и так понадобится обновить)
=== Стадия 2 ===
Этот пункт вступает в действие на каждой машине индивидуально при
обновлении её пакетов.
Файлтриггер из пункта 3 обнаруживает, что можно ввести симлинки, и
делает это, завершая процесс usrmerge на данной системе.
Каждая инсталляция перейдёт к ней независимо, как только все пакеты в этой инсталляции будут содержать свои файлы под {{path|/usr}}.


== Incompatibilities ==
== Incompatibilities ==
Строка 98: Строка 106:
== FAQ ==
== FAQ ==


Рекомендуем прочитать другие материалы о преимуществах предлагаемого решения<ref>[https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/ TheCaseForTheUsrMerge]</ref><ref>[https://www.freedesktop.org/wiki/Software/systemd/separate-usr-is-broken/ separate-usr-is-broken], примеры, где в ранней системе полагаются на наличие {{path|/usr}}}</ref>.
Рекомендуем прочитать другие материалы о преимуществах новой иерархии<ref>[https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/ TheCaseForTheUsrMerge]</ref><ref>[https://www.freedesktop.org/wiki/Software/systemd/separate-usr-is-broken/ separate-usr-is-broken], примеры, где в ранней системе полагаются на наличие {{path|/usr}}}</ref>.


'''Q: А что, если {{path|/usr}} на отдельном разделе по каким-то причинам не примонтируется?'''
'''Q: А что, если {{path|/usr}} на отдельном разделе по каким-то причинам не примонтируется?'''
Строка 112: Строка 120:
* В-третьих, нет ни одного задокументированного случая, где таким образом спасли какую-либо типичную GNU/Linux-систему, включая Альт, есть только [https://www.ecb.torontomu.ca/~elf/hack/recovery.html предание] из 1986 года, касавшееся non-Linux тех времён на компьютере тех времён. Рецептов такого восстановления, отчуждаемых от компетенций разработчиков ALT и умелых сисадминов, нет тем более. Следовательно, можно заключить, что в общем случае цитируемая возможность восстановить {{path|/usr}} из {{path|/}} — призрачна.
* В-третьих, нет ни одного задокументированного случая, где таким образом спасли какую-либо типичную GNU/Linux-систему, включая Альт, есть только [https://www.ecb.torontomu.ca/~elf/hack/recovery.html предание] из 1986 года, касавшееся non-Linux тех времён на компьютере тех времён. Рецептов такого восстановления, отчуждаемых от компетенций разработчиков ALT и умелых сисадминов, нет тем более. Следовательно, можно заключить, что в общем случае цитируемая возможность восстановить {{path|/usr}} из {{path|/}} — призрачна.
* Несмотря на всё это, нет ничего плохого в том, чтобы рецепт такого спасения (при помощи операционной избыточности инсталляции альта) администратору ''предложить'', но это должен быть явный механизм с минимумом издержек для остальной структуры системы. Есть множество вариантов это реализовать с разными преимуществами и минусами в разных установках; все они out of scope for this document.
* Несмотря на всё это, нет ничего плохого в том, чтобы рецепт такого спасения (при помощи операционной избыточности инсталляции альта) администратору ''предложить'', но это должен быть явный механизм с минимумом издержек для остальной структуры системы. Есть множество вариантов это реализовать с разными преимуществами и минусами в разных установках; все они out of scope for this document.
'''Q: Зачем вам отдельная программа-конвертер? Есть же пакетный менеджер.'''
A: {{pkg|rpm}} не умеет заменять каталог (например, {{path|/x}}) на символическую ссылку. Ему надо помочь:
* скопировать всё из каталога {{path|/x}} под префикс (под {{path|/usr}}) в новый каталог,
* скопировать туда же содержимое аналогичного каталога {{path|/usr/x}} под префиксом,
* атомически поменять местами новый каталог и {{path|/usr/x}},
* атомически поменять местами {{path|/x}} и ссылку на новый,
* проследить, что в процессе ничего не потерялось, и удалить лишнее.
Проще всего это сделать на стадии <tt>%pretrans</tt> (дословно: ''перед транзакцией'', перед манипуляцией пакетов), чтобы к началу установки пакетов всё уже было готово и процесс не зависел от порядка, в котором {{prg|rpm}} ставит пакеты.
'''Q: Почему перед обновлением нужно явно устанавливать пакет {{pkg|usrmerge-hier-convert}}?'''
A: Его не так-то легко вытянуть по зависимостям. Совершая обновление системы, {{prg|apt}} формирует ''транзакцию'' для {{prg|rpm}} — своего рода техническое задание: «установи пакеты X, удали пакеты Y, обнови пакеты Z». Если в эту транзакцию попадает новый пакет {{pkg|filesystem}}, то {{pkg|usrmerge-hier-convert}} должен уже быть в системе на этапе <tt>%pretrans</tt>; его нельзя установить в той же транзакции.
'''Q: Зачем вы лезете в каталоги на стадии <tt>%pretrans</tt>? Почему бы не научить RPM автоматом класть compat-симлинки в {{path|/bin}}, если это самостоятельный каталог, а оригиналы в {{path|/usr/bin}}, и т. п.? А замену {{path|/bin}} на симлинк упаковать в файлтриггер и проводить тогда, когда там не осталось оригиналов.'''
A: Да, можно было бы написать файлтриггер, который проверяет, не состоят ли каталоги из списка 1 целиком из
симлинков внутрь {{path|/usr}}, и, если да, превращает такой каталог с симлинками в симлинк на каталог.
Правда, не вполне ясно, что он должен делать с {{path|/lib}}, внутри которого произвольная структура.
Главная же сложность здесь в том, что не так-то просто пропатчить {{prg|rpm}} соответствующим способом, особенно в условиях нехватки времени (core team минимум с 2017 года накладывали veto, пока не стало невмоготу). А ещё нужно было бы держать в репозитории два варианта пакета {{pkg|filesystem}}.


== User-visible impact ==
== User-visible impact ==
Меньше каталогов верхнего уровня в корне, кроме симлинков.
Меньше каталогов верхнего уровня в корне, кроме симлинков.
{{pkg|kernel-modules-nvidia}} для совместимости потребовалось переупаковать.
Для ядер, собранных в Sisyphus до момента переупаковки, эти модули обновить невозможно; соответственно, не получится на них откатиться, даже если они установлены в системе и известны загрузчику.
Чтобы обновить Sisyphus с unmerged-usr на merged-usr, недостаточно просто запустить обновление; нужно выполнить следующие действия:
# apt-get install usrmerge-hier-convert
Иными словами, программа {{prg|usrmerge-hier-convert}} должна уже быть в системе перед обновлением.
Перед установкой {{pkg|usrmerge-hier-convert}} проверяет, возможно ли преобразование файловой системы. Некоторые пакеты (их исчезающе мало) могут быть несовместимы с usrmerge, их придётся обновить или удалить заранее. Самый известный — {{pkg|vim}} (см. {{altbug|49541}}), который нужно обновить:
# apt-get install vim-console
После обновления и/или удаления таких пакетов надо снова попытаться установить {{pkg|usrmerge-hier-convert}}. Если проверка прошла успешно, можно обновляться.
# apt-get dist-upgrade
После обновления на новый {{pkg|filesystem}} пакет {{pkg|usrmerge-hier-convert}} ни для чего не нужен, и его можно смело удалить.
Это не коснётся обновления с p10; всё необходимое будет установлено в качестве обновлений в бранче p10.


== Appendix ==
== Appendix ==

Текущая версия от 03:14, 25 мая 2024


Usrmerge

Начиная с 23 апреля 2024 реализовано в Sisyphus. Текущие проблемы с обновлением описаны тут и тут

Глоссарий

merged-usr-иерархией называется такая FHS-подобная иерархия каталогов, в которой все неизменяемые при работе файлы из операционной системы (т. е. из состава пакетов в репозитории ОС) помещаются либо внутри префикса (/usr), либо их местоположение является ссылкой внутрь префикса. В такой иерархии /bin, /lib и т. д. будут симлинками на /usr/bin, /usr/lib и т. д. Иерархия, не отвечающая этому правилу (например, та, которую создавал инсталлятор до p11), называется unmerged-usr.

split-usr-конфигурация подразумевает, что исполнимый файл в процессе pid 1 из корневой файловой системы стартует до монтирования /usr, расположенного на отдельном разделе. split-usr не следует путать с unmerged-usr, хоть системы со свойством split-usr и являются подмножеством систем unmerged-usr.

Введение

Исторически[1] в UNIX System V, а позже и в мейнстримных линукс-дистрибутивах разделяли каталоги /bin и /usr/bin, /lib$suff и /usr/lib$suff, и т. п., давая возможность разместить /usr на отдельной файловой системе от /, содержащего все эти подкаталоги.

Позже, с увеличением средних размеров устройств хранения в машинах, сторонники разделения придумали другие обоснования (например, возможность из окружения в /{bin,sbin,libX,...}/ починить немонтирующуюся /usr). Но на сегодняшний день непонятно, какой набор утилит и нужных им so/иных файлов стоит признать частью "системы спасения", которая должна быть доступна без /usr, а какой — нет, ибо сами утилиты приобретают универсальный вид и широкие границы применимости. С развитием механизмов initramfs и живых загрузочных/установочных носителей, а также практикой "раздела восстановления" на локальном хранилище машины среди настольных дистрибутивов этот аргумент теряет всякий смысл.

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

  • либо переложить /usr/{bin,sbin,lib,libx32,lib64,libexec,local,share,src,...} в корень,
  • либо поместить аналоги этих каталогов из / в /usr.

Из двух вариантов, входящих в рамки FHS[2], второй лучше хотя бы тем, что уменьшает количество top-level каталогов, куда упаковывается постоянное содержимое пакетов, до одного. Сейчас среди FHS-совместимых дистрибутивов это типичный подход, на который в том числе потихоньку начинают полагаться апстримы прикладных пакетов.

Rationale

  • Один каталог (пусть с не очень удачным именем /usr) как объект манипуляции и как общий носитель фиксированного содержимого пакетов удобнее россыпи каталогов, полный список которых даже невозможно построить. Появляется даже смысл рассматривать его в виде отдельной точки монтирования, которую можно держать общей на многих машинах под общим управлением.
    • Один каталог легче снапшотить, по нему легче гонять find, ...
  • Упаковка всего пакетного содержимого в /usr открывает дорогу к виртуальному /, который не находится на устройстве хранения и содержит только пустые каталоги-точки-монтирования.
  • Возникает осмысленное разделение между /usr, /var и /etc: первый каталог несёт в себе постоянное содержимое пакетов, не предназначенное к ручной модификации (не через пакетную систему или доставку образа), а другие два уже исторически применяются для переменного хранимого состояния и общесистемных конфигов.
  • Сборочным скриптам и прочим интеграционным программным компонентам не нужно будет перебирать каталоги, в которых находится искомая программа.[3]
  • Начиная с версии 255, выпущенной в декабре 2023, systemd прекратит поддержку split-usr и unmerged-usr; вот коммит.
    • Из кода проекта systemd, помимо прочего, исчезнут все упоминания старых каталогов; например, директива ProtectKernelModules= больше не будет монтировать заглушку поверх /lib/modules, и т. п.

Proposed changes

Необходимые действия можно разбить на три стадии.

Стадия 1

1) Определить, что слиянию с аналогами внутри /usr подлежат следующие каталоги:

  /bin
  /lib
  /lib32
  /lib64
  /libx32
  /sbin

На каждой машине есть некоторые каталоги из этого списка; они и будут перенесены.

2) Ввести brp-модуль brp-dupe-bin, который на стадии brp завершается с ошибкой, если обнаружены разные файлы в /bin/x и /usr/bin/x, а если один из них есть ссылка на другой, устанавливает две копии такого файла по обоим путям с совпадающими атрибутами и контентом. Это нужно, чтобы приблизительно 22 пакета могли устанавливаться на все варианты иерархий: и на unmerged-usr, и на merged-usr. Создавать жёсткую ссылку нежелательно: если /bin/x и /usr/bin/x лежат на разных файловых системах, такой пакет туда не установится: RPM не рассечёт жёсткую ссылку на два одинаковых файла. Большинство пакетов, требующих исправления, достаточно будет просто пересобрать со специальным brp-модулем.

Некоторые пакеты, например, vim-common, упаковывают разные файловые объекты в /bin и /usr/bin; другие пакеты ставят файлы прямо в %buildroot/bin. Их потребуется исправить руками (готово: altbug:49541). (Справедливости ради, многие из них и так понадобится обновить)

Полный список таких будущих конфликтов на 2024-03-16:

[('bin/bsh', {'ash', 'bsh'}),
 ('bin/ksh', {'ksh', 'pdksh'}),
 ('bin/mail', {'mailutils', 'mailx'}),
 ('bin/ex', {'vi-traditional', 'vim-common', 'vim-minimal'}),
 ('bin/rview', {'vim-common', 'vim-minimal'}),
 ('bin/vi', {'vi-traditional', 'vim-minimal'}),
 ('sbin/halt', {'shepherd', 'systemd-sysvinit', 'sysvinit'}),
 ('sbin/reboot', {'shepherd', 'systemd-sysvinit', 'sysvinit'}),
 ('sbin/shutdown', {'shepherd', 'systemd-sysvinit', 'sysvinit'})]

Из перечисленных множеств пересекающихся в будущем пакетов многие уже явно конфликтуют друг с другом.

3) Подготовить пакет filesystem версии 3: поместить в нём скрипт, срабатывающий в %pretrans и переносящий содержимое каталогов из списка 1 внутрь /usr (т. е. под префикс). Сценарий файлтриггера должен будет давать предельно ясную информацию и диагностические сообщения на стандартные потоки. Нужно будет либо положиться на static coreutils, либо очень осторожно обращаться с обычными и dynamic linker.

4) Подготовить p10 к плавному обновлению на p11 и предшествующие ему срезы сизифа.

Стадия 2

Этот пункт вступает в действие на каждой машине индивидуально при обновлении её пакетов. Перед транзакцией, в которой ставят новый пакет filesystem, скрипт из пункта 2 вводит симлинки, завершая процесс usrmerge на данной системе.

Каждая инсталляция перейдёт к ней независимо, по мере обновления пакетов.

Стадия 3

Мейнтейнеры пакетов перейдут к ней после выпуска p11.

Заменить макросы, использующие старые каталоги (%_udevrulesdir, %_tmpfilesdir и другие), и пересобрать с ними пакеты, что-либо помещающие в эти каталоги. Приближённое число затрагиваемых бинарных пакетов:

% grep -E '^/(bin|lib[^/]*|sbin)/[a-zA-Z0-9_-]+' contents-index \
  | grep -vE '^/lib/(systemd|udev|sysusers.d|modules[^/]*|modprobe.d|security|tmpfiles.d)'
  \ # exclude known places
  | cut -f2 -d$'\t' | grep -v '^/' # exclude path provides
  | sort -u | wc -l
524

Это оценка по x86_64 + noarch. Исходных, конечно, будет меньше (333).

При обновлении на эти пакеты будет действовать правило 2, поэтому их содержимое будет доступно.

Incompatibilities

Если корневая файловая система — каскадная композиция на базе, например, overlayfs, и каталоги /bin и подобные находятся не в верхнем слое стека — автоматически обновить такую корневую файловую систему на filesystem > 3 не выйдет. Придётся либо не обновляться, либо пересобрать контейнер/систему на обновлённой пакетной базе.

FAQ

Рекомендуем прочитать другие материалы о преимуществах новой иерархии[4][5].

Q: А что, если /usr на отдельном разделе по каким-то причинам не примонтируется?

A: Тогда система не сможет загрузиться, как и в случае, если / по каким-то причинам не примонтируется.

Q: А раньше можно было, пользуясь программами в /, починить /usr

A: Несколько тезисов:

  • В-нулевых, для того, чтобы возникла такая ситуация, систему должны были установить так, чтобы /usr был отдельным от /, т. е. такая разметка преследовала какую-либо цель.
  • Во-первых, для этого нужно, чтобы / смог смонтироваться, а /usr не смог.
  • Во-вторых, всё ещё нет критерия, по которому ту или иную программу и её зависимости можно либо отнести к "системе спасения", либо исключить из неё и сослать в /usr.
  • В-третьих, нет ни одного задокументированного случая, где таким образом спасли какую-либо типичную GNU/Linux-систему, включая Альт, есть только предание из 1986 года, касавшееся non-Linux тех времён на компьютере тех времён. Рецептов такого восстановления, отчуждаемых от компетенций разработчиков ALT и умелых сисадминов, нет тем более. Следовательно, можно заключить, что в общем случае цитируемая возможность восстановить /usr из / — призрачна.
  • Несмотря на всё это, нет ничего плохого в том, чтобы рецепт такого спасения (при помощи операционной избыточности инсталляции альта) администратору предложить, но это должен быть явный механизм с минимумом издержек для остальной структуры системы. Есть множество вариантов это реализовать с разными преимуществами и минусами в разных установках; все они out of scope for this document.

Q: Зачем вам отдельная программа-конвертер? Есть же пакетный менеджер.

A: rpm не умеет заменять каталог (например, /x) на символическую ссылку. Ему надо помочь:

  • скопировать всё из каталога /x под префикс (под /usr) в новый каталог,
  • скопировать туда же содержимое аналогичного каталога /usr/x под префиксом,
  • атомически поменять местами новый каталог и /usr/x,
  • атомически поменять местами /x и ссылку на новый,
  • проследить, что в процессе ничего не потерялось, и удалить лишнее.

Проще всего это сделать на стадии %pretrans (дословно: перед транзакцией, перед манипуляцией пакетов), чтобы к началу установки пакетов всё уже было готово и процесс не зависел от порядка, в котором rpm ставит пакеты.

Q: Почему перед обновлением нужно явно устанавливать пакет usrmerge-hier-convert?

A: Его не так-то легко вытянуть по зависимостям. Совершая обновление системы, apt формирует транзакцию для rpm — своего рода техническое задание: «установи пакеты X, удали пакеты Y, обнови пакеты Z». Если в эту транзакцию попадает новый пакет filesystem, то usrmerge-hier-convert должен уже быть в системе на этапе %pretrans; его нельзя установить в той же транзакции.

Q: Зачем вы лезете в каталоги на стадии %pretrans? Почему бы не научить RPM автоматом класть compat-симлинки в /bin, если это самостоятельный каталог, а оригиналы в /usr/bin, и т. п.? А замену /bin на симлинк упаковать в файлтриггер и проводить тогда, когда там не осталось оригиналов.

A: Да, можно было бы написать файлтриггер, который проверяет, не состоят ли каталоги из списка 1 целиком из симлинков внутрь /usr, и, если да, превращает такой каталог с симлинками в симлинк на каталог. Правда, не вполне ясно, что он должен делать с /lib, внутри которого произвольная структура. Главная же сложность здесь в том, что не так-то просто пропатчить rpm соответствующим способом, особенно в условиях нехватки времени (core team минимум с 2017 года накладывали veto, пока не стало невмоготу). А ещё нужно было бы держать в репозитории два варианта пакета filesystem.

User-visible impact

Меньше каталогов верхнего уровня в корне, кроме симлинков.

kernel-modules-nvidia для совместимости потребовалось переупаковать. Для ядер, собранных в Sisyphus до момента переупаковки, эти модули обновить невозможно; соответственно, не получится на них откатиться, даже если они установлены в системе и известны загрузчику.

Чтобы обновить Sisyphus с unmerged-usr на merged-usr, недостаточно просто запустить обновление; нужно выполнить следующие действия:

# apt-get install usrmerge-hier-convert

Иными словами, программа usrmerge-hier-convert должна уже быть в системе перед обновлением.

Перед установкой usrmerge-hier-convert проверяет, возможно ли преобразование файловой системы. Некоторые пакеты (их исчезающе мало) могут быть несовместимы с usrmerge, их придётся обновить или удалить заранее. Самый известный — vim (см. altbug #49541), который нужно обновить:

# apt-get install vim-console

После обновления и/или удаления таких пакетов надо снова попытаться установить usrmerge-hier-convert. Если проверка прошла успешно, можно обновляться.

# apt-get dist-upgrade

После обновления на новый filesystem пакет usrmerge-hier-convert ни для чего не нужен, и его можно смело удалить.

Это не коснётся обновления с p10; всё необходимое будет установлено в качестве обновлений в бранче p10.

Appendix

  1. [1]
  2. [2]
  3. Вообще-то для этого нужно ещё провести слияние sbin и bin, но оно не несёт срочности и не рассматривается на этой странице.
  4. TheCaseForTheUsrMerge
  5. separate-usr-is-broken, примеры, где в ранней системе полагаются на наличие /usr}