PIVOT_ROOT(2)

ИМЯ
pivot_root - изменяет корневую файловую систему

ОБЗОР
int pivot_root(const char *new_root, const char *put_old);

Замечание: В glibc нет обёрточной функции для данного системного вызова; смотрите ЗАМЕЧАНИЯ.

ОПИСАНИЕ
Вызов pivot_root() перемещает корневую систему вызывающего процесса в каталог put_old и делает каталог new_root новой корневой файловой системой у вызывающего процесса.

Обычно, pivot_root() используется при загрузке, когда система монтирует временную корневую файловую систему (например, initrd), а затем монтирует настоящую корневую файловую систему, делая, тем самым, её корневой для всех последующих процессов или нитей.

Вызов pivot_root() может изменить (или не изменить) текущий корневой и текущий рабочий каталоги во всех процессах или нитях, использующих старый корневой каталог. Вызывающий pivot_root() должен быть уверен в том, что процессы у которых корневой или текущий рабочий каталог равен старому корневому каталогу, работают нормально в каждом случае. Самый простой способ достичь этого — сменить их корневой и текущий рабочий каталог на new_root до вызова pivot_root().

Содержимое предыдущего абзаца, на самом деле, является не совсем определённым, потому что реализация pivot_root() может измениться в будущем. На момент написания этого документа pivot_root() изменяет корневой и текущий рабочий каталоги каждого процесса или нити на new_root, если они указывают на старый корневой каталог. Это необходимо для того, чтобы нити ядра не занимали старый корневой и текущий рабочий каталог, даже если они вообще не обращались к файловой системе. В будущем, возможно, будет создан механизм, заставляющий нити ядра отказаться от доступа к файловой системе, что позволит удалить этот довольно навязчивый механизм из pivot_root().

Заметим, что всё это относится и к вызывающему процессу: pivot_root() может изменить (а может и не изменить) его текущий рабочий каталог. По этой причине рекомендуется вызывать chdir("/") сразу после вызова pivot_root().

На значения new_root и put_old накладываются следующие ограничения:

-   Они должны быть каталогами.

-   Аргументы new_root и put_old не могут быть в одной файловой системе с текущим корневым каталогом.

-   Аргумент put_old должен быть в дереве каталогов new_root, т.е., путём добавления ненулевого количества /.. в строке, на которую указывает put_old, можно получить каталог, равный new_root.

-   К put_old не должны быть подмонтированы файловые системы.

См. также страницу pivot_root(8), в которой приведены примеры возможного использования.

Если текущий корневой каталог не является точкой монтирования (например, после chroot(2) или pivot_root(), см. ниже), то к put_old подключается не старый корневой каталог, а точка монтирования этой файловой системы.

Значение new_root должно быть точкой монтирования (если это не точка монтирования, то достаточно привязать монтирование new_root поверх самой себя).

Типа распространения new_root и его родительского монтирования не должно быть MS_SHARED; схожим образом, если put_old — существующая точка монтирования, то её тип распространения не должен быть MS_SHARED.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.

ОШИБКИ
Вызов pivot_root() может возвращать (в errno) любые ошибки, которые возвращаются stat(2). Также он может вернуть:

EBUSY
    Аргумент new_root или put_old находится в текущей корневой файловой системе, или какая-то файловая система уже смонтирована в put_old.

EINVAL
    Значение new_root не является точкой монтирования.

EINVAL
    Аргумент put_old не находится в дереве каталогов new_root.

EINVAL
    Текущий корень расположен на файловой системе rootfs (начальная ramfs).

EINVAL
    Точка монтирования new_root и её родительское монтирование имеет тип распространения MS_SHARED.

EINVAL
    Значение put_old является точкой монтирования и имеет тип распространения MS_SHARED.

ENOTDIR
    Аргумент new_root или put_old не является каталогом.

EPERM
    Вызывающий процесс не имеет мандата CAP_SYS_ADMIN.

ВЕРСИИ
Вызов pivot_root() появился в Linux 2.3.41.

СООТВЕТСТВИЕ СТАНДАРТАМ
Вызов pivot_root() есть только в Linux и поэтому его использование не переносимо.

ЗАМЕЧАНИЯ
В glibc нет обёртки для данного системного вызова; запускайте его с помощью syscall(2).

Для rootfs (начальная ramfs) нельзя вызвать pivot_root(). Рекомендуемым методом изменения корневой файловой системы в этом случае является удаление всего в rootfs, перемонтирование в rootfs нового корня, присоединение stdin/stdout/stderr к новой /dev/console и запуск нового init(1). Для этого существуют вспомогательные программы; смотрите switch_root(8).

ДЕФЕКТЫ
Вызов pivot_root() не должен изменять корневой и рабочий каталоги других процессов в системе.

Некорректное использование pivot_root() может привести к непредсказуемым последствиям.

СМОТРИТЕ ТАКЖЕ
chdir(2), chroot(2), mount(2), stat(2), initrd(4), pivot_root(8), switch_root(8)