Что такое «идентификаторы проектов» в Linux, как указано в руководстве chattr?

Что такое «идентификаторы проектов» в Linux, как указано в руководстве chattr?

Я читал руководство по использованию chattrна моей машине Linux ( kali4-amd64), когда увидел это в списке определений атрибутов файлов:

A directory with the 'P' attribute set will enforce a hierarchical
structure for project id's.  This means that files and directory created in
the directory will inherit the project id of the directory, rename
operations are constrained so when a file or directory is moved into
another directory, that the project id's much match.  In addition, a hard
link to file can only be created when the project id for the file and the
destination directory match.

Я лично не знаю, что такое «идентификатор проекта» в Linux/UNIX, и многократные поиски в Google тоже не дали результатов, поэтому я надеюсь, что кто-нибудь здесь сможет мне помочь.

решение1

То, о чем вы спрашиваете, является частью концепции проектных квот. Проектные квоты — это способ управлениядисковая квота. Конкретный тип файловой системы может поддерживать или не поддерживать идентификаторы проекта. Давайте сосредоточимся на ext4 и начнем с man 8 tune2fs:

-O [^]feature[,...]
Установить или очистить указанные функции (опции) файловой системы в файловой системе. […]

[…]

project
Включить отслеживание идентификатора проекта. Используется для отслеживания квоты проекта.

quota Включить внутреннюю квоту файловой системы inodes.

[…]

-Q quota-options
Устанавливает функцию 'quota' на суперблоке и работает с файлами квот для заданного типа квоты. Параметры квот могут быть одним или несколькими из следующих:

[^]usrquota
Устанавливает/очищает inode квоты пользователя в суперблоке.

[^]grpquota
Устанавливает/очищает групповую квоту inode в суперблоке.

[^]prjquota Устанавливает/очищает inode квоты проекта в суперблоке.

Вы можете включить эти параметры в существующей файловой системе:

tune2fs -O project,quota /your/device

(или укажите их mke2fsпри создании новой файловой системы). Затем включите квоту проекта (возможно, с квотой пользователя и/или квотой группы, если хотите):

tune2fs -Q prjquota /your/device

Смонтируйте его:

mount /your/device /the/mountpoint

Теперь вы можете управлять квотами с помощью таких инструментов, как setquotaи quota(обратите внимание, что в старых (-ish) версиях инструментов может отсутствовать опция -P, которая обрабатывает квоты проекта). Традиционно вы бы ограничили объем дискового пространства, который может использовать пользователь или группа. С квотой проекта вы можете сделать это для «проектов», независимо от пользователей и групп, которые участвуют.

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

cd /the/mountpoint
mkdir foo bar baz

Включить для них иерархию проектов:

chattr +P foo bar baz

Назначьте их на два разных проекта:

chattr -p 123 foo       # 123 is an arbitrary number, project id
chattr -p 5 bar baz     # so is 5, the point is they are different

Создавайте файлы в:

echo "lorem ipsum" > foo/file1
echo "lorem ipsum" > bar/file2
echo "lorem ipsum" > baz/file3

Теперь вызовите:

lsattr -pR .

и вы увидите (среди прочих) такие строки:

  123 --------------e---P ./foo/file1
    5 --------------e---P ./bar/file2
    5 --------------e---P ./baz/file3

что означает file1принадлежит проекту с id 123, file2и file3принадлежит проекту с id 5. Если вы определяете квоты для этих проектов (т.е. ограничиваете объем дискового пространства, которое могут использовать проекты), каждый файл будет влиять на потребление квоты соответствующего ему проекта.

Теперь то, что вы процитировали, имеет большой смысл:

файлы и каталоги, созданные в каталоге, унаследуют идентификатор проекта каталога

В нашем примере file1унаследовал идентификатор проекта от foo. Если вы создадите больше файлов/каталогов в , fooто они также унаследуют идентификатор. Это позволяет вам (и другим пользователям) работать над проектом в его назначенном каталоге, в то время как файлы, которые вы создаете, автоматически учитываются в соответствующей квоте.

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

ln ./baz/file3 ./foo/потерпит неудачу (попробуйте), но ln ./baz/file3 ./bar/получится. ОС не позволит вам легко «встроить» файл, который принадлежит одному проекту (и должен оставаться таким, поскольку исходный путь не отсоединен) в другой каталог проекта. Связывание файла внутри его проекта разрешено.

когда файл или каталог перемещается в другой каталог, идентификаторы проекта должны совпадать

Я думаю, что это довольно обманчиво. mvбудет делать свою работу, даже если идентификаторы не совпадают. Дело в том, что если вы вызываете

mv baz/file3 foo/

инструмент сначала попытается переместить rename(2)файл по новому пути, но это не удастся (как и lnвыше). Обычно или в пределах того же проекта это будет успешно, и исходное имя исчезнет. Видимо, это поведение и есть то, о чем говорит "идентификаторы проекта должны совпадать".

Но mvпока не выходит. Это как перемещение между файловыми системами: после mvнеудачного переименования он возвращается в режим копирования+удаления. По сути, он создаеткопия(с новым номером inode) в целевом каталоге. В нашем случае копия наследует идентификатор проекта foo(как и любой новый файл в этом каталоге), поэтому она влияет на потребление квоты project 123. Исходный путь затем отсоединяется. Это может повлиять на потребление квоты project 5; а может и нет: жесткие ссылки или открытые файловые дескрипторы приведут к тому, что исходный inode и данные сохранятся.

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

Есть способ сделать mvпереименование вместо копирования+удаления. Если вручную назначить исходный файл целевому проекту

chattr -p 123 baz/file3

тогда mv baz/file3 foo/действительно переместит его без копирования, не нарушая жесткие ссылки (если таковые имеются). Но учтите, что номер проекта принадлежит inode (не пути, не имени, не записи каталога), поэтому chattr -pвлияет на все жесткие ссылки.

Поэтому, если вам нужно переместить большой файл (т. е. данные, хранящиеся в каком-то inode, а не просто в одной из многих жестких ссылок) в другой проект, изменение проекта и последующее перемещение избавит вас от ненужного копирования.

Связанный контент