4

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

Но как это работает при использовании файловой системы, которая не использует inode, например FAT32, с Linux?

Некоторые эксперименты предполагают, что удаление открытых файлов все еще возможно (в отличие от Windows, где вызов unlink не будет успешным), но что происходит, когда файловая система нечисто демонтируется?

Как Linux помечает файлы как несвязанные, если сама файловая система не поддерживает такую операцию? Является ли запись каталога только что удаленной, но сохраненной в памяти (это гарантировало бы удаление после размонтирования в любом случае, но оставило бы файловую систему в несовместимом состоянии), или удаление будет отмечено только в памяти и записано во время последний дескриптор файла закрыт, чтобы избежать возможного повреждения, но восстановить удаленные файлы после нечистого размонтирования?

1 ответ1

2

Вы правы в своем предположении, что, хотя все записи каталога удаляются сразу после вызова unlink(), фактические блоки, которые физически составляют файл, очищаются на диске только тогда, когда ничто больше не использует inode. (Я говорю « записи каталога », потому что в vfat файл может иметь несколько таких файлов, потому что реализована поддержка длинных имен файлов в vfat.)

В этом контексте под индексом я подразумеваю структуру в памяти, которую ядро Linux использует для обработки файлов. Он используется даже тогда, когда файловая система не "основана на inode". В случае vfat, inode просто поддерживается некоторыми блоками на диске.

Взглянув на исходный код ядра Linux, мы видим, что vfat_unlink , который реализует системный вызов unlink() для vfat, делает примерно следующее (чрезвычайно упрощено для иллюстрации):

static int vfat_unlink(struct inode *dir, struct dentry *dentry)
{
        fat_remove_entries(dir, &sinfo);
        clear_nlink(inode);
}

Итак, что происходит:

  1. fat_remove_entries просто удаляет запись для файла в своем каталоге.
  2. clear_nlink устанавливает счетчик ссылок для индекса на 0 , что означает, что ни один файл (то есть, нет записи в каталоге) больше не указывает на этот индекс.

Обратите внимание, что на этом этапе ни inode, ни его физическое представление никак не затрагиваются (за исключением уменьшенного количества ссылок), поэтому он все еще счастливо существует в памяти и на диске, как будто ничего не произошло!

(Кстати, также интересно отметить, что vfat_unlink всегда устанавливает счетчик ссылок на 0 а не просто уменьшает его с помощью drop_link . Это должно предупредить вас, что файловые системы FAT не поддерживают жесткие ссылки! И еще одно указание на то, что FAT сама не знает какой-либо отдельной концепции inode.)

Теперь давайте посмотрим, что происходит, когда инод выселяется. evict_inode вызывается, когда нам больше не нужен индекс в памяти. В самом начале, это, конечно, может произойти только тогда, когда ни один процесс больше не удерживает дескриптор открытого файла для этого inode (но теоретически может произойти и позже). Реализация FAT для evict_inode выглядит (опять же, упрощенно) так:

static void fat_evict_inode(struct inode *inode)
{
        truncate_inode_pages(&inode->i_data, 0);
        if (!inode->i_nlink) {
                inode->i_size = 0;
                fat_truncate_blocks(inode, 0);
        }
        invalidate_inode_buffers(inode);
        clear_inode(inode);
}

Магия происходит именно в if -clause: если счетчик ссылок inode был равен 0, это означает, что ни одна запись каталога не указывает на него. Таким образом, мы устанавливаем его размер равным 0 и фактически усекаем его до 0 байт, что фактически удаляет его с диска путем очистки блоков, из которых он был сделан.

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

Кстати, CHKDSK не только очистит эти блоки, пометив их как свободные, но и создаст новые файлы в корневом каталоге, указывающие на первый блок в каждой цепочке, с такими именами, как FILE0001.CHK .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .