Summary: | sfdisk не переносит таблицу разделов установленной штатным образом ОС | ||
---|---|---|---|
Product: | Sisyphus | Reporter: | Белаш Константин <bk> |
Component: | libevms | Assignee: | Slava Aseev <ptrnine> |
Status: | CLOSED FIXED | QA Contact: | qa-sisyphus |
Severity: | normal | ||
Priority: | P5 | CC: | klark, legion, mcpain, mike, rider, zerg |
Version: | unstable | ||
Hardware: | x86_64 | ||
OS: | Linux |
Возник ещё один вопрос, прямо не связанный с этим багом к legion@: Судя по коду sfdisk (util-linux/libfdisk/src/gpt.c#612), данное предупреждение через несколько возвратов -ERANGE превращается в необрабатываему никем фатальную ошибку в случае, если посчитанное значение отличается от умолчального. Получается, что спецификация GUID/GPT допускает значения, отличные от дефолта, но такую разметку не сможет перетащить sfdisk. Алексей, как думаешь, авторы просто забыли обработать -ERANGE или же это верный ход превращать warnx() в фатальную ошибку? (In reply to Белаш Константин from comment #0) > Если в файле дампа (sda.sfdisk) поменять значения: > first-lba: 32 на first-lba: 34 и table-length: 120 на table-length: 128 > то sfdisk отрабатывает нормально. Константин, а можешь показать hexdump второго сектора исходного диска или приложить к багу в бинарном виде? Чтобы знать наверняка, что ошибка в инсталляторе, а не в sfdisk. (Ответ для Leonid Krivoshein на комментарий #1) > Возник ещё один вопрос, прямо не связанный с этим багом к legion@: > > Судя по коду sfdisk (util-linux/libfdisk/src/gpt.c#612), данное > предупреждение через несколько возвратов -ERANGE превращается в > необрабатываему никем фатальную ошибку в случае, если посчитанное значение > отличается от умолчального. Насколько я вижу умолчание это минимальное и максимальное значение. А -ERANGE для first возвращается если он за границами минимального и максимального значений. > Получается, что спецификация GUID/GPT допускает значения, отличные от > дефолта, но такую разметку не сможет перетащить sfdisk. Нет. Тебе нужно, чтобы first-lba и last-lba были в пределах: esz = sizeof(struct gpt_entry) * GPT_NPARTITIONS / cxt->sector_size; llba = cxt->total_sectors - 2ULL - esz; flba = esz + 2ULL; > Алексей, как > думаешь, авторы просто забыли обработать -ERANGE или же это верный ход > превращать warnx() в фатальную ошибку? Я не очень понял вопроса. -ERANGE не обрабатывается только в gpt_reset_alignment и в этом случае first и last будут нулями, что скорее всего приведёт к тому, что cxt->first_lba и cxt->last_lba не будут изменены. В gpt_mknew_header же выход за границы фатален поскольку в хэдере first_usable_lba и last_usable_lba будут нулями оба или же только один из них. (In reply to Alexey Gladkov from comment #3) > (Ответ для Leonid Krivoshein на комментарий #1) > > Получается, что спецификация GUID/GPT допускает значения, отличные от > > дефолта, но такую разметку не сможет перетащить sfdisk. > > Нет. Тебе нужно, чтобы first-lba и last-lba были в пределах: $ git grep -A2 -B1 'First LBA specified by script is out of range' |cut -c9- if (rc == 0 && (*first < flba || *first > llba)) { fdisk_warnx(cxt, _("First LBA specified by script is out of range.")); return -ERANGE; } В данном случае *first = 32, а не 34, значение должно быть в пределах минимума и максимума, определённого умолчанием. То есть, если (32 < 34 || ...), по логике libfdisk означает ошибку. > > Алексей, как > > думаешь, авторы просто забыли обработать -ERANGE или же это верный ход > > превращать warnx() в фатальную ошибку? > > Я не очень понял вопроса. -ERANGE не обрабатывается только в > gpt_reset_alignment и в этом случае first и last будут нулями Вроде бы такой здесь получается стек обработки: libfdisk/src/gpt.c#613 count_first_last_lba() libfdisk/src/gpt.c#675 gpt_mknew_header() libfdisk/src/gpt.c#2457 gpt_create_disklabel() libfdisk/src/script.c#1751 fdisk_create_disklabel() libfdisk/src/script.c#1546 fdisk_apply_script_headers() disk-utils/sfdisk#1855 , #1895, #1912. Отсюда и мой вопрос. Возможно я неправ в том, что спецификация допускает и меньшее значение, надо это проверить. (In reply to Leonid Krivoshein from comment #4) > Возможно я неправ в том, что спецификация допускает и > меньшее значение, надо это проверить. The UEFI specification stipulates that a minimum of 16,384 bytes, regardless of sector size, are allocated for the Partition Entry Array. Thus, on a disk with 512-byte sectors, at least 32 sectors are used for the Partition Entry Array, and the first usable block is LBA 34 or higher. While on a 4,096-byte sectors disk, at least 4 sectors are used for the Partition Entry Array, and the first usable block is LBA 6 or higher. То есть, first_lba действительно должен быть >= 34, но для дисков 4K >= 6. Алексей, здесь нет ошибки в sfdisk, выше я на свой вопрос сам же и ответил. Для дисков 4K учитывается sector_size, так что sfdisk правильно делает, что не даёт восстановить разметку с first_lba = 32. Осталось понять, кто создаёт такой кривой GPT-заголовок. (Ответ для Leonid Krivoshein на комментарий #2) > (In reply to Белаш Константин from comment #0) > > Если в файле дампа (sda.sfdisk) поменять значения: > > first-lba: 32 на first-lba: 34 и table-length: 120 на table-length: 128 > > то sfdisk отрабатывает нормально. > > Константин, а можешь показать hexdump второго сектора исходного диска или > приложить к багу в бинарном виде? Чтобы знать наверняка, что ошибка в > инсталляторе, а не в sfdisk. # dd if=/dev/sda bs=512 count=2 | hexdump -C 2+0 записей получено 2+0 записей отправлено 1024 байт (1,0 kB, 1,0 KiB) скопирован, 0,000133948 s, 7,6 MB/s 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000001c0 02 00 ee 3f e0 ff 01 00 00 00 ff ff bf 03 00 00 |...?............| 000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 |................| 000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.| 00000200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...| 00000210 9d fb 8f f8 00 00 00 00 01 00 00 00 00 00 00 00 |................| 00000220 ff ff bf 03 00 00 00 00 20 00 00 00 00 00 00 00 |........ .......| 00000230 e0 ff bf 03 00 00 00 00 f9 83 ce e6 27 73 41 13 |............'sA.| 00000240 80 cd ec 00 5e bc 8b f1 02 00 00 00 00 00 00 00 |....^...........| 00000250 78 00 00 00 80 00 00 00 a3 88 a8 46 00 00 00 00 |x..........F....| 00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000400 Это нужно? (In reply to Белаш Константин from comment #7) > Это нужно? Да, оно. Видно, что разметка испорчена инсталлятором: > 00000220 ff ff bf 03 00 00 00 00 20 00 00 00 00 00 00 00 Здесь "20 00 00 00 00 00 00 00" -- это и есть first_lba=32, а д.б. 34. Нашел вроде бы то самое. В plugins/gpt/gptsegmgr.c есть вот такая штука: pt_lba1 = 2; pt_size = ld->geometry.sectors_per_track - 2; pt_entry_size = sizeof(gpt_partition); pt_count = (pt_size*EVMS_VSECTOR_SIZE) / pt_entry_size; // Locate the start of useable area immediately after the partition table start_useable = pt_lba1 + pt_size; start_useable это как раз first-lba, а pt_count - table-length если pt_size равен 30, то start_useable будет 32 sizeof(gpt_partition) равен 128, значит pt_count в данном случае равен 120 (30 * 512 / 128) Выходит, с вот этой двойкой какая-то фигня: pt_size = ld->geometry.sectors_per_track - 2; Если ее убрать, то должно получиться start_useable 34 и pt_count 128 (In reply to Slava Aseev from comment #9) > Нашел вроде бы то самое. > В plugins/gpt/gptsegmgr.c есть вот такая штука: > pt_size = ld->geometry.sectors_per_track - 2; Тут только один момент. Строка датируется 2006 годом и пришла в Альт с первой сборкой evms-2.5.5-alt2. Текущая версия сборки alt47. А поломка возникла недавно, уже на p9. На p8 там всё правильно проставлялось. Вот пример с моей машины: label: gpt label-id: <removed> device: /dev/nvme0n1 unit: sectors first-lba: 34 last-lba: 488397134 (Ответ для Leonid Krivoshein на комментарий #10) > (In reply to Slava Aseev from comment #9) > > Нашел вроде бы то самое. > > В plugins/gpt/gptsegmgr.c есть вот такая штука: > > pt_size = ld->geometry.sectors_per_track - 2; > Тут только один момент. Строка датируется 2006 годом и пришла в Альт с > первой сборкой evms-2.5.5-alt2. Текущая версия сборки alt47. А поломка > возникла недавно, уже на p9. На p8 там всё правильно проставлялось. Вот > пример с моей машины: > > label: gpt > label-id: <removed> > device: /dev/nvme0n1 > unit: sectors > first-lba: 34 > last-lba: 488397134 У меня на диске, который я размечал средствами инсталлятора год назад, вот такие цифры: label: gpt label-id: C6E76728-F50E-4A4A-A53F-7A38A5469290 device: /dev/nvme0n1 unit: sectors first-lba: 32 last-lba: 250069648 table-length: 120 Проверил на виртуалке с первым попавшимся образом c7 (evms-2.5.5-alt30) там то же самое: label: gpt label-id: 547D4CF0-8887-6543-82F3-374B96872F1C device: /dev/sda unit: sectors first-lba: 32 last-lba: 83886048 table-length: 120 Возможно, я делал разметку не инсталлятором, а обычными средствами. По крайней мере, раньше эта ошибка не встречалась. В заголовке GPT firts_lba определено как uint64_t, в evms это lba_t, а то, из чего он считает по этой формуле -- sector_count_t pt_size, причём ld->geometry опциональный член структуры, судя по описанию LOGICALDISK. Сложно догадаться, что находится в ld->geometry.sectors_per_track, т.к. GPT/GUID не рассчитана на C/H/S коррдинацию, а ориентирована на lba. Возникает вопрос, почему там изначально была эта -2 в формуле. Тут какая-то совсем жесть происходит. Пробую на маленьком 10 мегабайтном диске делать GPT средствами evms. Создал на чистом диске: label: gpt label-id: 6E8EE2E2-6BE4-EE4D-B5AA-39D0B7D40502 device: /dev/sda unit: sectors first-lba: 23 last-lba: 20951 table-length: 84 Потом пересоздал: label: gpt label-id: 7B6A60BB-17EC-CE45-819D-3D10EF73FDD8 device: /dev/sda unit: sectors first-lba: 18 last-lba: 20956 table-length: 64 Потом создал с помощью fdisk и пересоздал опять средствами evms: label: gpt label-id: 40CDBE9D-AF1D-E44F-B449-4417095CC278 device: /dev/sda unit: sectors first-lba: 65 last-lba: 20909 table-length: 252 И затем пересоздал еще раз: label: gpt label-id: 809BED2C-E345-B046-8AB2-A6F9325FC246 device: /dev/sda unit: sectors first-lba: 60 last-lba: 20914 table-length: 232 Т.е. это все дело либо зависит от исходного состояния диска, либо в ld->geometry.sectors_per_track оказывается вообще что попало. Поэтому просто убрать двойку оттуда явно недостаточно. (Ответ для Leonid Krivoshein на комментарий #12) > Возможно, я делал разметку не инсталлятором, а обычными средствами. По > крайней мере, раньше эта ошибка не встречалась. Т.е. вполне возможно, что вы также размечали инсталлятором. Просто карты сложились чуть по-другому. В общем, сделал как в fdisk: http://git.altlinux.org/people/ptrnine/packages/?p=evms.git;a=blobdiff;f=plugins/gpt/gptsegmgr.c;h=cf31c71a611a481ba10f86547317b2bf8c0d8f5e;hp=de218b8329be77e5f64850eff572a68f375f1405;hb=87be2780bebe017bfc7841677f6e951f4745d578;hpb=e26550e96225a01d6bb63aba8a4413216b4911f2 Я еще чуть потестирую и, если нет возражений, отправлю. (In reply to Slava Aseev from comment #15) > Я еще чуть потестирую и, если нет возражений, отправлю. Константа GPT_NPARTITIONS в исходниках не определена, Вы задали её в заголовочном файле? Константа EVMS_VSECTOR_SIZE определена лишь в одном месте как 512 байт, а это значит, что проект вряд ли поддерживает настоящие "Blue 4Kn" диски и в структуру ld.geometry может приезжать совсем неправильное значение bytes_per_sector. Собственно, варианта всего два: 512 и 4096 и оба лежат в /sys/dev/block/$major:$minor/queue/logical_block_size либо его можно получить через ioctl() как в $(blockdev --getss /dev/$NAME). Вы правильно делаете, что отвязываете формулу от данных в ld.geometry, но это нужно делать до конца либо иметь понимание, что в неё попадают правильные данные. Вообще правильная формула должна исходить из спецификации, тогда всё просто -- pt_size=16384 скорее константа и она же возможный минимум. При делении этого числа на bytes_per_sector всегда получим либо 32 (для 512-байтных секторов), либо 4 (для "Blue 4Kn" дисков). А значит и first_lba всегда зависит по сути от единственного флага blue4kn. Но я боюсь, что тестирование на дисках 4K покажет несовместимость libevms и по другим структурам. Актуализировать же код начала 2000-х придётся долго и мучительно. :-) (Ответ для Leonid Krivoshein на комментарий #16) > (In reply to Slava Aseev from comment #15) > > Я еще чуть потестирую и, если нет возражений, отправлю. > Константа GPT_NPARTITIONS в исходниках не определена, Вы задали её в > заголовочном файле? Константа EVMS_VSECTOR_SIZE определена лишь в одном > месте как 512 байт, а это значит, что проект вряд ли поддерживает настоящие > "Blue 4Kn" диски и в структуру ld.geometry может приезжать совсем > неправильное значение bytes_per_sector. Собственно, варианта всего два: 512 > и 4096 и оба лежат в /sys/dev/block/$major:$minor/queue/logical_block_size > либо его можно получить через ioctl() как в $(blockdev --getss /dev/$NAME). > > Вы правильно делаете, что отвязываете формулу от данных в ld.geometry, но > это нужно делать до конца либо иметь понимание, что в неё попадают > правильные данные. Вообще правильная формула должна исходить из > спецификации, тогда всё просто -- pt_size=16384 скорее константа и она же > возможный минимум. При делении этого числа на bytes_per_sector всегда > получим либо 32 (для 512-байтных секторов), либо 4 (для "Blue 4Kn" дисков). > А значит и first_lba всегда зависит по сути от единственного флага blue4kn. > > Но я боюсь, что тестирование на дисках 4K покажет несовместимость libevms и > по другим структурам. Актуализировать же код начала 2000-х придётся долго и > мучительно. :-) GPT_NPARTITIONS определяется в gpt.h В ld->geometry.bytes_per_sector теоретически должен попадать результат вот этой функции http://git.altlinux.org/people/ptrnine/packages/?p=evms.git;a=blob;f=plugins/disk/localdskmgr.c;h=d38631c24b251e8d0ae877d1145e99117a111bf0;hb=HEAD#l1649 Но вы правы, сейчас в коде куча мест, где используется просто константа EVMS_VSECTOR_SIZE или даже сдвиг на EVMS_VSECTOR_SIZE_SHIFT вместо умножения/деления (экономим на спичках?). И поэтому стоит либо править все эти места, либо наоборот заменить здесь bytes_per_sector на EVMS_VSECTOR_SIZE (уже хотя бы для консистентности). evms-2.5.5-alt49 -> sisyphus: Mon Jan 18 2021 Slava Aseev <ptrnine@altlinux> 2.5.5-alt49 - plugins/gpt: fix start_useable and pt_count calculation (closes: #39385) - plugins/md: fix bitwise inversions |
Воспроизводится при установке с alt-workstation-9.1-x86_64.iso. При инсталляции, на шаге 4/12 установки, выбрал "Использовать неразмеченное пространство", эта опция по-умолчанию. После установки: host-79 ~ # lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 30G 0 disk ├─sda1 8:1 0 255M 0 part /boot/efi ├─sda2 8:2 0 128M 0 part [SWAP] └─sda3 8:3 0 29.6G 0 part / sr0 11:0 1 1024M 0 rom sr1 11:1 1 4.7G 0 rom /run/media/user/ALT Workstation 9.1 x86_64 host-79 ~ # sfdisk -d /dev/sda > sda.sfdisk host-79 ~ # cat sda.sfdisk label: gpt label-id: E6CE83F9-7327-1341-80CD-EC005EBC8BF1 device: /dev/sda unit: sectors first-lba: 32 last-lba: 62914528 table-length: 120 /dev/sda1 : start= 2048, size= 522240, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=E7687235-280B-D747-A66F-87CBFB8B6BD1 /dev/sda2 : start= 524288, size= 262144, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=D4CF5C91-E654-5B44-AEE6-9444A491907F /dev/sda3 : start= 786432, size= 62126080, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=899A97C0-E0C6-4244-AC1B-3BF3D19710E2 host-79 ~ # Добавляю диск и переношу разметку: host-79 ~ # lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 30G 0 disk ├─sda1 8:1 0 255M 0 part /boot/efi ├─sda2 8:2 0 128M 0 part [SWAP] └─sda3 8:3 0 29.6G 0 part / sdb 8:16 0 32G 0 disk sr0 11:0 1 1024M 0 rom sr1 11:1 1 4.7G 0 rom /run/media/user/ALT Workstation 9.1 x86_64 host-79 ~ # sfdisk /dev/sdb < sda.sfdisk Checking that no-one is using this disk right now ... OK Disk /dev/sdb: 32 GiB, 34359738368 bytes, 67108864 sectors Disk model: QEMU HARDDISK Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes >>> Script header accepted. >>> Script header accepted. >>> Script header accepted. >>> Script header accepted. >>> Script header accepted. >>> Script header accepted. >>> Script header accepted. >>> First LBA specified by script is out of range. First LBA specified by script is out of range. Failed to apply script headers, disk label not created. Leaving. Если в файле дампа (sda.sfdisk) поменять значения: first-lba: 32 на first-lba: 34 и table-length: 120 на table-length: 128 то sfdisk отрабатывает нормально.