Почему невозможно изменить размер / переместить смонтированные (нелогичные) разделы во время выполнения?

2651
Senkaku

При поиске причин, по которым невозможно изменить размер смонтированного раздела, я в основном нашел ответы вроде этого:

  • Это зависит от файловой системы и раздела, разные файловые системы и разделы будут использовать разные методы. - Хавьер Ривера

  • Сначала вы должны расширить базовое блочное устройство. Если вы используете обычный раздел на одном жестком диске, это невозможно. LVM и mdadm могут расширить блочное устройство, затем вы можете запустить resize2fs, чтобы расширить fs (предполагая, что это ext [234]). - по psui

  • Это действительно зависит от файловой системы, которую вы используете [...], но настоятельно НЕ рекомендуется изменять размер смонтированного, используемого раздела. - Луис Альварадо

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


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

3
+1. Но ОС не знает, какие данные могут понадобиться выполняющимся процессам, и многим программам не очень нравится, когда целая пара разделов с соответствующими файловыми системами выдергивается из-под их ног. И ядро ​​Linux не может на самом деле запрашивать ввод данных у пользователя; если не считать того факта, что многие Linux-системы, в основном однопользовательские, работают под управлением X, и любое приглашение ядра в лучшем случае не будет видно, что если это удаленно используемая система? Само ядро ​​ни при каких обстоятельствах не должно напрямую взаимодействовать с пользователем; ПО пользовательского режима должно взаимодействовать с ядром. a CVn 10 лет назад 1

2 ответа на вопрос

3
Rod Smith

Actually, it is possible to resize many modern filesystems while they're mounted (although usually only when increasing their size). For instance:

  • From man resize2fs: "The resize2fs program... can be used to enlarge or shrink an unmounted file system... If the filesystem is mounted, it can be used to expand the size of the mounted filesystem...."
  • From man xfs_growfs: "The filesystem must be mounted to be grown."
  • From man mount: "Mount options for jfs... resize=value... Resize the volume to value blocks. JFS only supports growing a volume, not shrinking it."
  • From BTRFS Fun: "And yes, it is an on-line resize, there is no need to umount/shrink/mount. So no downtimes!"

AFAIK, ReiserFS can't be resized when it's mounted.

The ability to resize a volume without unmounting it is extremely important for mission-critical servers and the like -- a Web hosting provider (for example) can't afford the downtime required to take a filesystem offline in order to resize it after adding a new disk to a RAID array. That's why so many modern filesystems support this feature.

That said, GParted can't resize partitions without unmounting them. I'm not positive, but I suspect that has more to do with the partition side of the equation than with the filesystem side; or it could be that the GParted developers were being conservative and setting lowest-common-denominator requirements (namely, for ReiserFS).

It's definitely easier to handle resizing of filesystems when they're stored in an LVM setup. This type of configuration means that you'll never have to move the start point of a filesystem, so you can grow a logical volume and the filesystem it contains dozens of times, if necessary, even into space occupied by filesystems that used to be present but that you've deleted. LVM was also designed with dynamic changes to logical volumes in mind, whereas the kernel's handling of partitions is more static. If you frequently adjust your filesystems, you should definitely look into LVM. There is a bit of a learning curve to LVM, but it's worth the hassle for anybody who does advanced or frequent filesystem manipulations.

2
Shi

File systems implement some kernel API. So they need to provide functions to open a file by name, to write to a file, to read from a file, and to close a file again (just stick to these basic operations).

The kernel provides functions to read a sector and to write a sector.

The magic in-between is done by the file system "driver". So if a program wants to open a file, the kernel passes that request to the file system driver. The driver then reads the file system meta data and finds the entry for the file. The entry contains file system information, like user and group ownership, permissions, access time and more, and of course information about the sector the file is located on the disk (let's ignore fragmentation here).

So if you take the whole partition and move it to another place on the disk, all stored sector numbers now have an offset, but the file system does not know this offset. So if a program then tries to open a file, the file system will use the sector number as stored in the file system meta data to read the file contents. But as the whole file system is moved several sectors further, the data read will not correspond to the file content and the file is corrupt. Same goes for everything else in the file system as well.

The kernel does not know anything about this. A driver asks to read a sector. The kernel does not know if the sector number should have an offset or not. So this is something that has to be implemented in all file system drivers.

Now imagine a (legacy) file system which uses 16 bits to address sectors. Let's assume a sector is 512 bytes. So the maximum size of the file system can be 32 MiB. If you want to further expand the file system, it has to change the size of an addressable sector from 512 bytes to 1024 bytes. But even now, the file system is full, because all sector numbers are used. So the file system expansion program needs to scan all files, and copy two sectors, which are 1024 bytes in size but only 512 bytes are used, into one sector so that one sector is full (again) and the other one can be freed.

Now imagine this has to be done while the file system is mounted and programs are happily reading and writing from and to the disk. This adds quite some complexity to the file system driver which is only required for this special use case. So it is easier to simply only resize a file system when it is not mounted.

Furthermore, there is more magic under the hood. You can, for example, create a file, open it and remove it. The file does not have a representation in the file system anymore (it has no file name), but as an open descriptor still exists, the file can still be read from and written to. If the program holding the descriptor forks, even the children can access that file as they inherit the descriptor. As soon as all open descriptors to that file are closed, the file system will mark the sectors as unused, ready to be used for new files.

So if you unmount the file system and then mount it again, those files are gone. And the program is stuck.

Ваш ответ великолепен, он отвечает на многие вопросы, которые у меня были, не только на тот, который я задавал выше, но в вашем примере есть одна деталь, которую я не понимаю. «[...] он должен изменить размер адресуемого сектора с 512 байт до 1024 байт». Не будет ли это перезаписывать каждый второй сектор или, по крайней мере, информацию о том, что изначально было два сектора размером 512 байт а не один с 1024 байтами на каждые два? Senkaku 10 лет назад 0

Похожие вопросы