Hey there!
as part of our hackweek, we are trying to move the Kairos installer (https://github.com/kairos-io/kairos-agent) to use pure go instead of shelling out and having to depend on external binaries.
Diskfs works wonderfully, it was so easy to create and partition a disk! great work there.
My main issue came when trying to create a partition in ext4 format.
It looks like some of the blockgroups calculation is wrong as you get an error dividing by zero.
Minimum reproducible case:
package main
import (
"github.com/diskfs/go-diskfs"
"github.com/diskfs/go-diskfs/disk"
"github.com/diskfs/go-diskfs/filesystem"
"github.com/diskfs/go-diskfs/partition/gpt"
)
func main() {
d, err := diskfs.Open("/dev/vda", diskfs.WithSectorSize(512))
if err != nil {
panic(err)
}
sizeFirst := uint64(10 * 1024 * 1024)
startFirst := 1024 * 1024 / uint64(diskfs.SectorSize512)
endFirst := sizeFirst/uint64(diskfs.SectorSize512) + startFirst - 1
sizeSecond := uint64(20 * 1024 * 1024)
startSecond := endFirst + 1
endSecond := sizeSecond/uint64(diskfs.SectorSize512) + startSecond - 1
table := &gpt.Table{
LogicalSectorSize: int(diskfs.SectorSize512),
PhysicalSectorSize: int(diskfs.SectorSize512),
ProtectiveMBR: true,
Partitions: []*gpt.Partition{
{
Start: startFirst,
End: endFirst,
Size: sizeFirst,
Type: gpt.EFISystemPartition,
Name: "part1",
},
{
Start: startSecond,
End: endSecond,
Size: sizeSecond,
Type: gpt.LinuxFilesystem,
Name: "part2",
},
},
}
err = d.Partition(table)
if err != nil {
panic(err)
}
_, err = d.CreateFilesystem(disk.FilesystemSpec{
Partition: 0,
FSType: filesystem.TypeFat32,
VolumeLabel: "part1",
})
if err != nil {
panic(err)
}
_, err = d.CreateFilesystem(disk.FilesystemSpec{
Partition: 1,
FSType: filesystem.TypeExt4,
VolumeLabel: "part1",
})
if err != nil {
panic(err)
}
}
This is a very simple reproducible case, you open /dev/vda, create a table with 2 partitions, and then create the filesystem. Disk and partition creation goes correctly with zero issues and fat32 filesystem creation as well, but ext4 creation fails.
panic: invalid sectors per block 0, must be between 2 and 128 sectors
goroutine 1 [running]:
main.main()
/home/itxaka/projects/kairos-agent/main.go:124 +0x26a
Looks like because the disk.CreateFilesystem method calls the ext4.Create with no Params, the check on https://github.com/diskfs/go-diskfs/blob/master/filesystem/ext4/ext4.go#L158 will always fail, because the Params.SectorsPerBlock is gonna be always zero
Okay, no problem thats fixable, we can manually call the ext4.Create ourselves with proper params :)
so we substitute in our example this
_, err = d.CreateFilesystem(disk.FilesystemSpec{
Partition: 1,
FSType: filesystem.TypeExt4,
VolumeLabel: "part1",
})
for this
params := ext4.Params{SectorsPerBlock: 16}
_, err = ext4.Create(d.File, d.Table.GetPartitions()[1].GetSize(), d.Table.GetPartitions()[1].GetStart(), d.LogicalBlocksize, ¶ms)
But that results in a panic as well:
panic: runtime error: integer divide by zero
goroutine 1 [running]:
github.com/diskfs/go-diskfs/filesystem/ext4.Create({0x5530f8, 0xc000052008}, 0x1400000, 0xb00000, 0x200?, 0x0?)
/home/itxaka/projects/go-diskfs/filesystem/ext4/ext4.go:230 +0x188a
main.main()
/home/itxaka/projects/kairos-agent/main.go:120 +0x305
This seems to point to https://github.com/diskfs/go-diskfs/blob/master/filesystem/ext4/ext4.go#L226 being the issue. I added some logging around and it kind of makes sense as at that point the values are:
// inodecount: 2560
// blockgroups: 0
inodesPerGroup := int64(inodeCount) / blockGroups
Which points to https://github.com/diskfs/go-diskfs/blob/master/filesystem/ext4/ext4.go#L194 in which the values are:
// numblocks: 2560
// blocksPerGroup: 65536
blockGroups := numblocks / int64(blocksPerGroup)
Which points to blocksPerGroup being too big to divide numblocks onto it. Again this comes from the Params having an empty value for BlocksPerGroup and it defaulting to blocksize * 8 at https://github.com/diskfs/go-diskfs/blob/master/filesystem/ext4/ext4.go#L184
so lets add those to params
params := ext4.Params{SectorsPerBlock: 2, BlocksPerGroup: 256}
Which causes another panic :D
panic: runtime error: integer divide by zero
goroutine 1 [running]:
github.com/diskfs/go-diskfs/filesystem/ext4.Create({0x5530f8, 0xc000052040}, 0x1400000, 0xb00000, 0x200?, 0x0?)
/home/itxaka/projects/go-diskfs/filesystem/ext4/ext4.go:412 +0x189a
main.main()
/home/itxaka/projects/kairos-agent/main.go:120 +0x305
This time its the https://github.com/diskfs/go-diskfs/blob/master/filesystem/ext4/ext4.go#L398 check as maxBlockGroups is 0. This is due to maxFilesystemSize64Bit resolving to 62 so the operation ends up being zero
// blocksize 1024
// blocksPerGroup 256
// maxFilesystemSize64Bit 62
maxBlockGroups = maxFilesystemSize64Bit / (uint64(blocksPerGroup) * uint64(blocksize))
Now here I have no idea how to continue troubleshooting this as I dont know what maxFilesystemSize64Bit refers to. Is this the maximum size of a filesystem in ext4 in bytes? is that missing a transformation to bytes or something? https://github.com/diskfs/go-diskfs/blob/master/filesystem/ext4/ext4.go#L59
Sorry about the big wall of text. I know enough to troubleshoot but not enough about ext4 to tackle this, otherwise I would have send a PR to try to fix it, but that maxFilesystemSize64Bit got me stumped :D
Running version v1.4.1
Hey there!
as part of our hackweek, we are trying to move the Kairos installer (https://github.com/kairos-io/kairos-agent) to use pure go instead of shelling out and having to depend on external binaries.
Diskfs works wonderfully, it was so easy to create and partition a disk! great work there.
My main issue came when trying to create a partition in ext4 format.
It looks like some of the blockgroups calculation is wrong as you get an error dividing by zero.
Minimum reproducible case:
This is a very simple reproducible case, you open
/dev/vda, create a table with 2 partitions, and then create the filesystem. Disk and partition creation goes correctly with zero issues and fat32 filesystem creation as well, but ext4 creation fails.Looks like because the
disk.CreateFilesystemmethod calls theext4.Createwith noParams, the check on https://github.com/diskfs/go-diskfs/blob/master/filesystem/ext4/ext4.go#L158 will always fail, because the Params.SectorsPerBlock is gonna be always zeroOkay, no problem thats fixable, we can manually call the ext4.Create ourselves with proper params :)
so we substitute in our example this
for this
But that results in a panic as well:
This seems to point to https://github.com/diskfs/go-diskfs/blob/master/filesystem/ext4/ext4.go#L226 being the issue. I added some logging around and it kind of makes sense as at that point the values are:
Which points to https://github.com/diskfs/go-diskfs/blob/master/filesystem/ext4/ext4.go#L194 in which the values are:
Which points to
blocksPerGroupbeing too big to dividenumblocksonto it. Again this comes from theParamshaving an empty value forBlocksPerGroupand it defaulting toblocksize * 8at https://github.com/diskfs/go-diskfs/blob/master/filesystem/ext4/ext4.go#L184so lets add those to params
Which causes another panic :D
This time its the https://github.com/diskfs/go-diskfs/blob/master/filesystem/ext4/ext4.go#L398 check as
maxBlockGroupsis 0. This is due tomaxFilesystemSize64Bitresolving to 62 so the operation ends up being zeroNow here I have no idea how to continue troubleshooting this as I dont know what
maxFilesystemSize64Bitrefers to. Is this the maximum size of a filesystem in ext4 in bytes? is that missing a transformation to bytes or something? https://github.com/diskfs/go-diskfs/blob/master/filesystem/ext4/ext4.go#L59Sorry about the big wall of text. I know enough to troubleshoot but not enough about ext4 to tackle this, otherwise I would have send a PR to try to fix it, but that
maxFilesystemSize64Bitgot me stumped :DRunning version v1.4.1