Bug 37366

Summary: Некорректно отображаются свободный размер ранее созданных ФС в инсталляторе
Product: Branch p9 Reporter: Egor Zotov <gorini41995>
Component: alterator-vmAssignee: Slava Aseev <ptrnine>
Status: CLOSED FIXED QA Contact: qa-p9 <qa-p9>
Severity: normal    
Priority: P3 CC: mike, nickel, ptrnine, rider, sbolshakov, zerg
Version: не указана   
Hardware: all   
OS: Linux   
Attachments:
Description Flags
Некорректное отображение свободного места раздела vfat none

Description Egor Zotov 2019-10-21 17:12:31 MSK
При подключении ранее созданных файловых систем в инсталлятор было замечено странное поведение.
Инсталлятор некорректно отображает свободное место раздела:

fat32, который создавался размером 200 MB в инсталляторе отображается с размером 199 MB, а свободное место равно -313 MB (отрицательное значение)

fat32, который создавался размером 512 MB в инсталляторе отображается сводное место равное 0.

Скриншот, на котором наглядно видно такое поведение во вложении.

xfs - на созданных ранее разделах показывает свободное место равное 0.
fat16 - показывает свободное место равное размеру раздела минус 32 MB.

Как воспроизвести:

1. Создать на устройстве (например usb флеш-накопитель) разделы fat32 и fat16 разных размеров. 
2. Подключить устройство к машине и загрузиться в инсталлятор.

Либо с помощью инсталлятора на внутреннем накопителе:

1. Запустить инсталлятор
2. Дойти до шага "4/12: Подготовка диска"
3. Разбить жесткий диск вручную на разделы:
Создать раздел vfat размером 512 MB
Создать раздел vfat размером 256 MB
Создать раздел vfat размером 768 MB
4. Нажать кнопку назад в правом нижнем углу экрана
5. Нажать "ОК" на запрос о применении изменений
6. Перезагрузить инсталлятор и дойти до шага "Подготовка диска"
7. Выбрать "Подготовить разделы вручную" и нажать кнопку "Далее"

Результат: 
В первом случае у раздела vfat 512 MB значение свободного размера - 0 MB
Во втором случае у раздела vfat 256 MB значение свободного размера - -256 MB
В третьем случае у раздела vfat 768 MB значение свободного размера - 256 MB
Comment 1 Egor Zotov 2019-10-21 17:21:09 MSK
Created attachment 8348 [details]
Некорректное отображение свободного места раздела vfat
Comment 2 Slava Aseev 2019-11-08 12:19:12 MSK
Как выяснилось - причина в немного некорректном поведении утилиты fatresize, которая вызывается в плагине fat в libevms. 

fatresize считает, что минимальный размер fat32 партиции - 512 МиБ. Из readme к fatresize, я понял, что это сделано в угоду совместимости с Windows, потому что он якобы не умеет правильно работать с fat32 партициями размером меньше 512 МиБ. 

Что странно - это ограничение затрагивает не только задание размера fat32-партиции, но и вывод информации об уже созданной. Отсюда и неверное поведение. 

Например, для партиции размером 256 МиБ fatresize покажет "Min size: 536870912" (512 МиБ), а потом в alterator-vm от 256 отнимется 512. И в итоге мы имеем -256 МиБ свободного места.

В общем, я напишу разработчикам fatresize и отпишусь по результатам.
Comment 3 Michael Shigorin 2019-11-08 13:03:03 MSK
Спасибо за раскопки!

2 nickel: к теме UEFI это имеет прямое отношение в том смысле, что обычно alterator-vm делает FAT32 для /boot/efi/ -- может иметь смысл провентилировать вопрос да проверить фактическую совместимость ровно по этой части.
Comment 4 Sergey V Turchin 2019-11-08 13:57:44 MSK
(В ответ на комментарий №2)
> В общем, я напишу разработчикам fatresize
Дело в том, что это ты. ;-) mouse@ у нас давно не работает, а led@ разработкой не занимался.
Comment 5 Slava Aseev 2019-11-08 14:47:24 MSK
(В ответ на комментарий №4)
> (В ответ на комментарий №2)
> > В общем, я напишу разработчикам fatresize
> Дело в том, что это ты. ;-) mouse@ у нас давно не работает, а led@ разработкой
> не занимался.

Тогда, сделаю так: добавлю в fatresize дополнительную опцию, при появлении которой он работает без ограничения в 512 МиБ
Comment 6 Anton Farygin 2019-11-08 14:51:59 MSK
(В ответ на комментарий №5)
> (В ответ на комментарий №4)
> > (В ответ на комментарий №2)
> > > В общем, я напишу разработчикам fatresize
> > Дело в том, что это ты. ;-) mouse@ у нас давно не работает, а led@ разработкой
> > не занимался.
> 
> Тогда, сделаю так: добавлю в fatresize дополнительную опцию, при появлении
> которой он работает без ограничения в 512 МиБ

Да уберите это ограничение вообще и не мучайтесь.
Comment 7 Slava Aseev 2019-11-12 14:43:33 MSK
Убрал ограничение. Все заработало нормально для разделов > 260 MиБ. Для разделов меньше 260 МиБ теперь новый прикол - в качестве заполненного места возвращается размер раздела + 64 сектора (что не соответствует действительности).

Как я понял, дело тут в том, что libparted не умеет нормально работать с fat32 разделами, если количество секторов на кластер у них меньше 4. mkfs.fat -F32 для разделов < 260 МиБ как раз устанавливает 1 сектор на кластер (если > 260 то 8). Ограничение связано с самим fat'ом - fat32 не может быть меньше 65,527 кластеров.

В libparted есть ограничения на минимальное количество секторов на кластер. Если для fat32 установить его в 1, то все заработает нормально, но я пока не знаю, не сломается ли от этого что-то еще. Вот тут есть и один странный момент - fat32 в libparted ограничивают восьмью секторами на кластер, но все прекрасно работает с разделами, где 4 сектора на кластер. Это надо проверить, но мне кажется, что libparted в данном случае работает с fat32 разделами как с fat16 (?!).

В общем, я пока не придумал нормальное решение этой проблемы. Самое простое ненормальное - это сделать так, чтобы mkfs.fat устанавливал 4 сектора на кластер для разделов больших 130 МиБ и меньших 260 МиБ. Ну и никогда не создавать fat32 разделы меньше 130 МиБ :)

И есть еще одно. Почти нормальное. В GParted данная проблема не проявляется, т.к. для получения информации о fat разделе он использует свою внутреннюю реализацию. По сути это вызов fsck.fat -n -v, и вышеописанных проблем у него нет. Отсюда второй вариант - для получения размера раздела использовать fsck.fat -n -v прям из плагина fat для evms вместо fatresize.
Comment 8 Anton Farygin 2019-11-12 15:00:26 MSK
последний вариант мне нравится больше всего. Но fatresize вероятно используется ещё для чего-то помимо получения размера (например для его изменения). И что будет с этим функционалом ?
Comment 9 Slava Aseev 2019-11-12 15:13:15 MSK
(В ответ на комментарий №8)
> последний вариант мне нравится больше всего. Но fatresize вероятно используется
> ещё для чего-то помимо получения размера (например для его изменения). И что
> будет с этим функционалом ?

Никаких проблем быть не должно. Изменение размера останется с помощью fatresize (а под ним - вызовы libparted), получение размера будет с помощью fsck.fat.

В GParted аналогичный подход, только libparted используется напрямую. Возможно, как раз таки из-за вышеописанных проблем.
Comment 10 Anton Farygin 2019-11-12 16:20:19 MSK
Думаю, что надо реализовать и потестировать.
Comment 11 Slava Aseev 2019-11-27 15:57:02 MSK
В общем, проблема устранена.
Убрал ограничение в 512 МиБ в fatresize: http://git.altlinux.org/people/ptrnine/packages/?p=fatresize.git;a=commit;h=421dd52d9b2aac7a96b1954499cf8d5282812ce6

Плагин fat в evms претерпел более серьезные изменения: http://git.altlinux.org/people/ptrnine/packages/?p=evms.git;a=commit;h=1887dc9008acbf817c930e84020530a6a30d354f

Вместо fatresize для нахождения допустимых пределов изменения размера fat-партиций теперь изпользуются утилиты fdisk, lsblk и fsck.fat

Для нахождения нижнего предела используется "fsck.fat -n". Из вывода данной утилиты выдергиваются кол-во занятых и свободных кластеров.

C верхним пределом получилось немного сложнее. libparted в качестве него возвращал просто размер устройства, на котором находится партиция. Теперь все работает так:
1. Вызывается 'lsblk -anprs -o NAME /dev/*'для нахождения устройства, на котором находится партиция. В выводе оно оказывается на последней строчке (например, для /dev/sda4 родителем будет /dev/sda, для /dev/nvme0n1p2 - /dev/nvme0n1)
2. Далее для устройства-родителя вызывается 'fdisk -o Device,Start -l' который выводит таблицу разделов. Из этой таблицы сначала выдергивается начальный сектор нашей fat-партиции, затем выполняется поиск ближайшей следующей партиции на устройстве. В итоге верхний предел находится как "Начальный сектор партиции" минус "Начальный сектор следующей партиции". Если следующей партиции не существует - то просто используется размер устройства.

В процессе проверки об
Comment 12 Slava Aseev 2019-11-27 16:02:46 MSK
Не дописал :)

В процессе тестирования обнаружились новые проблемы. Во-первых - не работает изменение размера для fat lvm-партиций. Тут дело не в исправлении, раньше оно тоже не работало.
Во-вторых - libparted не может изменять размер у больших партиций.
Что делать со второй проблемой - я не знаю, над lvm пока думаю.
Comment 13 Slava Aseev 2019-11-28 18:51:36 MSK
Обнаружил в чем проблема с lvm.

evms для /dev/mapper/* устройств устанавливает имена с вертикальными слэшами, например: "lvm2|vg-test|lv-test"

У lvm2 есть механизм, который заменяет недопустимые символы на их шестнадцатеричное значение.
Вертикальный слэш в список допустимых не входит, отсюда вот такая ошибка:

The name " should be mangled but it contains blacklisted characters.

И тут два варианта, либо добавлять вертикальный слэш вот сюда: 
http://git.altlinux.org/gears/l/lvm2.git?p=lvm2.git;a=blob;f=libdm/libdm-common.c;h=1cb29f1e895e6d3cdf33dfb375fe1bcfd7aa9dc5;hb=HEAD#l390
что не очень хорошо

Либо менять вертикальный слэш в evms на что-нибудь еще:
http://git.altlinux.org/gears/e/evms.git?p=evms.git;a=blob;f=engine/dm-ioctl4.c;h=36e3167701e7134a4212817e1d637fb22bbc020e;hb=HEAD#l40

Второй вариант правильнее, потому как именно evms и виноват.
Также неизвестно, какие проблемы могут всплыть после этой замены. Поэтому нужно тщательно протестировать.

И кстати, сама проблема уже не нова, и встречалась вот в этом баге #28020
Comment 14 Anton Farygin 2019-11-28 18:55:59 MSK
2sbolshakov: есть мысли по этому поводу ?
Comment 15 Sergey Bolshakov 2019-11-28 19:06:22 MSK
(In reply to comment #13)
> Обнаружил в чем проблема с lvm.
> 
> evms для /dev/mapper/* устройств устанавливает имена с вертикальными слэшами,
> например: "lvm2|vg-test|lv-test"
> 
> У lvm2 есть механизм, который заменяет недопустимые символы на их
> шестнадцатеричное значение.
> Вертикальный слэш в список допустимых не входит, отсюда вот такая ошибка:
> 
> The name " should be mangled but it contains blacklisted characters.
> 
> И тут два варианта, либо добавлять вертикальный слэш вот сюда: 
> http://git.altlinux.org/gears/l/lvm2.git?p=lvm2.git;a=blob;f=libdm/libdm-common.c;h=1cb29f1e895e6d3cdf33dfb375fe1bcfd7aa9dc5;hb=HEAD#l390
> что не очень хорошо
> 
> Либо менять вертикальный слэш в evms на что-нибудь еще:
> http://git.altlinux.org/gears/e/evms.git?p=evms.git;a=blob;f=engine/dm-ioctl4.c;h=36e3167701e7134a4212817e1d637fb22bbc020e;hb=HEAD#l40
> 
> Второй вариант правильнее, потому как именно evms и виноват.
> Также неизвестно, какие проблемы могут всплыть после этой замены. Поэтому нужно
> тщательно протестировать.
> 
> И кстати, сама проблема уже не нова, и встречалась вот в этом баге #28020

прошу объяснить, каким образом тут lvm2 появился ?
Comment 16 Slava Aseev 2019-11-29 15:56:40 MSK
(В ответ на комментарий №15)
> (In reply to comment #13)
> > Обнаружил в чем проблема с lvm.
> > 
> > evms для /dev/mapper/* устройств устанавливает имена с вертикальными слэшами,
> > например: "lvm2|vg-test|lv-test"
> > 
> > У lvm2 есть механизм, который заменяет недопустимые символы на их
> > шестнадцатеричное значение.
> > Вертикальный слэш в список допустимых не входит, отсюда вот такая ошибка:
> > 
> > The name " should be mangled but it contains blacklisted characters.
> > 
> > И тут два варианта, либо добавлять вертикальный слэш вот сюда: 
> > http://git.altlinux.org/gears/l/lvm2.git?p=lvm2.git;a=blob;f=libdm/libdm-common.c;h=1cb29f1e895e6d3cdf33dfb375fe1bcfd7aa9dc5;hb=HEAD#l390
> > что не очень хорошо
> > 
> > Либо менять вертикальный слэш в evms на что-нибудь еще:
> > http://git.altlinux.org/gears/e/evms.git?p=evms.git;a=blob;f=engine/dm-ioctl4.c;h=36e3167701e7134a4212817e1d637fb22bbc020e;hb=HEAD#l40
> > 
> > Второй вариант правильнее, потому как именно evms и виноват.
> > Также неизвестно, какие проблемы могут всплыть после этой замены. Поэтому нужно
> > тщательно протестировать.
> > 
> > И кстати, сама проблема уже не нова, и встречалась вот в этом баге #28020
> 
> прошу объяснить, каким образом тут lvm2 появился ?

Именно по этой причине не работает (и не работал) ресайз, если fat-партиция на lvm'е.
А еще, как оказалось, fat-партиции на lvm'e вообще не определяются как fat.

К сабжу это отношения не имеет, поэтому мне стоит создать отдельный баг.
Comment 17 Anton Farygin 2019-11-29 20:55:57 MSK
в evms своя реализация lvm.
Comment 18 Slava Aseev 2019-12-02 18:13:28 MSK
(В ответ на комментарий №17)
> в evms своя реализация lvm.

Да, но изменение размера fat-партиций все равно происходит через fatresize, который в свою очередь уже вызывает libparted, а потом дело доходит и до самого lvm2.

Ошибка воспроизводится, если на стадии разметки дисков, на любой lvm2 раздел в /dev/mapper/ или /dev/evms/lvm2/ вызывать команду fatresize -i или parted:
fatresize -i /dev/mapper/lvm2_vg_root_lv_vol
или
parted /dev/mapper/lvm2_vg_root_lv_vol

Вот что получаем:
The name "/dev/mapper/lvm2|vg_root|lv_vol" should be mangled but it contains blacklisted characters.
Comment 19 Slava Aseev 2019-12-09 12:10:17 MSK
task #242568