diff --git a/doc/20-advanced/20-bootc/05-sources-of-configuration.md b/doc/20-advanced/20-bootc/05-sources-of-configuration.md index 54ced64b09..a5379f15a7 100644 --- a/doc/20-advanced/20-bootc/05-sources-of-configuration.md +++ b/doc/20-advanced/20-bootc/05-sources-of-configuration.md @@ -99,6 +99,12 @@ For a `payload_type: filesystem` the `payload` has the following properties: - `fstab_options` - `fstab_freq` - `fstab_passno` +- `mkfs_options`, an *optional* object containing filesystem-specific mkfs options. Currently supported properties: + - `verity`, an *optional* `boolean` to enable fs-verity (ext4 only). + - `geometry`, an *optional* object for drive geometry (vfat only), with the following properties: + - `heads`, an `integer` setting the number of heads. + - `sectors_per_track`, an `integer` setting the number of sectors per track. + - `agcount`, an *optional* `integer` setting the number of allocation groups (xfs only). Here's an example defining a few partition with XFS filesystem(s): @@ -134,6 +140,32 @@ partition_table: mountpoint: "/" ``` +To pass custom mkfs options, use the `mkfs_options` field. For example, to set the XFS allocation group count: + +```yaml + - payload_type: "filesystem" + payload: + type: "xfs" + label: "root" + mountpoint: "/" + mkfs_options: + agcount: 4 +``` + +Or to set custom drive geometry on a vfat partition: + +```yaml + - payload_type: "filesystem" + payload: + type: "vfat" + mountpoint: "/boot/efi" + label: "ESP" + mkfs_options: + geometry: + heads: 64 + sectors_per_track: 32 +``` + ###### LVM > [!WARNING] diff --git a/pkg/disk/filesystem.go b/pkg/disk/filesystem.go index 31a966943c..aee5022abe 100644 --- a/pkg/disk/filesystem.go +++ b/pkg/disk/filesystem.go @@ -15,6 +15,7 @@ type MkfsOptionGeometry struct { type MkfsOptions struct { Verity bool `json:"verity,omitempty" yaml:"verity,omitempty"` Geometry *MkfsOptionGeometry `json:"geometry,omitempty" yaml:"geometry,omitempty"` + AGCount int `json:"agcount,omitempty" yaml:"agcount,omitempty"` } func (opts MkfsOptions) Clone() MkfsOptions { diff --git a/pkg/disk/filesystem_test.go b/pkg/disk/filesystem_test.go index a8677fd27e..67c6a59129 100644 --- a/pkg/disk/filesystem_test.go +++ b/pkg/disk/filesystem_test.go @@ -23,9 +23,9 @@ func TestMkfsOptionsClone(t *testing.T) { orig := disk.MkfsOptions{ Verity: true, Geometry: &Geometry, + AGCount: 4, } clone := orig.Clone() assert.Equal(t, orig, clone) assert.False(t, reflect.ValueOf(orig.Geometry).Pointer() == reflect.ValueOf(clone.Geometry).Pointer()) - } diff --git a/pkg/osbuild/mkfs_stage.go b/pkg/osbuild/mkfs_stage.go index a1446e5fbd..bc6fd26138 100644 --- a/pkg/osbuild/mkfs_stage.go +++ b/pkg/osbuild/mkfs_stage.go @@ -45,6 +45,10 @@ func GenFsStages(pt *disk.PartitionTable, filename string, soucePipeline string) UUID: e.UUID, Label: e.Label, } + if mkfsOptions.AGCount != 0 { + options.AGCount = mkfsOptions.AGCount + mkfsOptions.AGCount = 0 // Handled + } stages = append(stages, NewMkfsXfsStage(options, stageDevices)) case "vfat": options := &MkfsFATStageOptions{ @@ -81,6 +85,9 @@ func GenFsStages(pt *disk.PartitionTable, filename string, soucePipeline string) if mkfsOptions.Verity { panic(fmt.Sprintf("fs type: %s does not support verity option", e.GetFSType())) } + if mkfsOptions.AGCount != 0 { + panic(fmt.Sprintf("fs type: %s does not support agcount option", e.GetFSType())) + } case *disk.Btrfs: stageDevices := getDevicesForFsStage(path, filename) diff --git a/pkg/osbuild/mkfs_stages_test.go b/pkg/osbuild/mkfs_stages_test.go index 56b3c402c1..8049481b3d 100644 --- a/pkg/osbuild/mkfs_stages_test.go +++ b/pkg/osbuild/mkfs_stages_test.go @@ -509,6 +509,33 @@ func TestGenFsStagesUnitVfatGeometry(t *testing.T) { }, stages) } +func TestGenFsStagesUnitXfsAGCount(t *testing.T) { + pt := &disk.PartitionTable{ + Type: disk.PT_GPT, + Partitions: []disk.Partition{ + { + Payload: &disk.Filesystem{ + Type: "xfs", + Mountpoint: "/", + MkfsOptions: disk.MkfsOptions{ + AGCount: 4, + }, + }, + }, + }, + } + stages := GenFsStages(pt, "file.img", "build") + assert.Equal(t, []*Stage{ + { + Type: "org.osbuild.mkfs.xfs", + Options: &MkfsXfsStageOptions{ + AGCount: 4, + }, + Devices: defaultStageDevices, + }, + }, stages) +} + func TestGenFsStagesUnhappy(t *testing.T) { pt := &disk.PartitionTable{ Type: disk.PT_GPT, @@ -547,6 +574,26 @@ func TestGenFsStagesUnhappyWrongOptionsVerity(t *testing.T) { }) } +func TestGenFsStagesUnhappyWrongOptionsAGCount(t *testing.T) { + pt := &disk.PartitionTable{ + Type: disk.PT_GPT, + Partitions: []disk.Partition{ + { + Payload: &disk.Filesystem{ + Type: "ext4", + MkfsOptions: disk.MkfsOptions{ + AGCount: 4, + }, + }, + }, + }, + } + + assert.PanicsWithValue(t, "fs type: ext4 does not support agcount option", func() { + GenFsStages(pt, "file.img", "build") + }) +} + func TestGenFsStagesUnhappyWrongOptionsGeometry(t *testing.T) { pt := &disk.PartitionTable{ Type: disk.PT_GPT, diff --git a/pkg/osbuild/mkfs_xfs_stage.go b/pkg/osbuild/mkfs_xfs_stage.go index 7637893ca5..9a612f885a 100644 --- a/pkg/osbuild/mkfs_xfs_stage.go +++ b/pkg/osbuild/mkfs_xfs_stage.go @@ -1,8 +1,9 @@ package osbuild type MkfsXfsStageOptions struct { - UUID string `json:"uuid"` - Label string `json:"label,omitempty"` + UUID string `json:"uuid"` + Label string `json:"label,omitempty"` + AGCount int `json:"agcount,omitempty"` } func (MkfsXfsStageOptions) isStageOptions() {}