Skip to content

Commit

Permalink
Better handle filesystem optional features. (#66)
Browse files Browse the repository at this point in the history
Filesystems (e.g. ext4, xfs) sometimes receive new features. When these
features are enabled, anything that loads the filesystem (e.g. kernel,
grub, etc.) must support the new feature or it will refuse to load it.

When formatting a new partition, there are a few considerations for if a
filesystem feature should be enabled:

- Does the version of mkfs support that feature?
- Does the build host kernel support that feature?
- Does the target OS support that feature?

This change ensure that all these considerations are handled correctly
for the ext4 and xfs filesystem types.
  • Loading branch information
cwize1 authored and elainezhao1 committed Jan 23, 2025
1 parent 57740ac commit 656a422
Show file tree
Hide file tree
Showing 12 changed files with 676 additions and 33 deletions.
31 changes: 14 additions & 17 deletions toolkit/tools/imagegen/diskutils/diskutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,11 @@ import (
"github.com/microsoft/azurelinux/toolkit/tools/internal/logger"
"github.com/microsoft/azurelinux/toolkit/tools/internal/retry"
"github.com/microsoft/azurelinux/toolkit/tools/internal/shell"
"github.com/microsoft/azurelinux/toolkit/tools/internal/targetos"
"github.com/sirupsen/logrus"
)

var (
// When calling mkfs, the default options change depending on the host OS you are running on and typically match
// what the distro has decided is best for their OS. For example, for ext2/3/4, the defaults are stored in
// /etc/mke2fs.conf.
// However, when building Azure Linux images, the defaults should be as consistent as possible and should only contain
// features that are supported on Azure Linux.
DefaultMkfsOptions = map[string][]string{
"ext2": {"-b", "4096", "-O", "none,sparse_super,large_file,filetype,resize_inode,dir_index,ext_attr"},
"ext3": {"-b", "4096", "-O", "none,sparse_super,large_file,filetype,resize_inode,dir_index,ext_attr,has_journal"},
"ext4": {"-b", "4096", "-O", "none,sparse_super,large_file,filetype,resize_inode,dir_index,ext_attr,has_journal,extent,huge_file,flex_bg,metadata_csum,64bit,dir_nlink,extra_isize"},
}

partedVersionRegex = regexp.MustCompile(`^parted \(GNU parted\) (\d+)\.(\d+)`)

// The default partition name used when the version of `parted` is too old (<3.5).
Expand Down Expand Up @@ -433,7 +423,7 @@ func WaitForDevicesToSettle() error {
}

// CreatePartitions creates partitions on the specified disk according to the disk config
func CreatePartitions(diskDevPath string, disk configuration.Disk, rootEncryption configuration.RootEncryption,
func CreatePartitions(targetOs targetos.TargetOs, diskDevPath string, disk configuration.Disk, rootEncryption configuration.RootEncryption,
diskKnownToBeEmpty bool,
) (partDevPathMap map[string]string, partIDToFsTypeMap map[string]string, encryptedRoot EncryptedRootDevice, err error) {
const timeoutInSeconds = "5"
Expand Down Expand Up @@ -492,7 +482,7 @@ func CreatePartitions(diskDevPath string, disk configuration.Disk, rootEncryptio
return partDevPathMap, partIDToFsTypeMap, encryptedRoot, err
}

partFsType, err := FormatSinglePartition(partDevPath, partition)
partFsType, err := formatSinglePartition(targetOs, partDevPath, partition)
if err != nil {
err = fmt.Errorf("failed to format partition:\n%w", err)
return partDevPathMap, partIDToFsTypeMap, encryptedRoot, err
Expand Down Expand Up @@ -789,8 +779,8 @@ func setGptPartitionType(partition configuration.Partition, timeoutInSeconds, di
return
}

// FormatSinglePartition formats the given partition to the type specified in the partition configuration
func FormatSinglePartition(partDevPath string, partition configuration.Partition,
// formatSinglePartition formats the given partition to the type specified in the partition configuration
func formatSinglePartition(targetOs targetos.TargetOs, partDevPath string, partition configuration.Partition,
) (fsType string, err error) {
const (
totalAttempts = 5
Expand All @@ -804,12 +794,17 @@ func FormatSinglePartition(partDevPath string, partition configuration.Partition
// To handle such cases, we can retry the command.
switch fsType {
case "fat32", "fat16", "vfat", "ext2", "ext3", "ext4", "xfs":
mkfsOptions := DefaultMkfsOptions[fsType]

if fsType == "fat32" || fsType == "fat16" {
fsType = "vfat"
}

mkfsOptions, err := getFileSystemOptions(targetOs, fsType)
if err != nil {
err = fmt.Errorf("failed to get mkfs args for filesystem type (%s) and target os (%s):\n%w", fsType,
targetOs, err)
return fsType, err
}

mkfsArgs := []string{"-t", fsType}
mkfsArgs = append(mkfsArgs, mkfsOptions...)
mkfsArgs = append(mkfsArgs, partDevPath)
Expand All @@ -825,6 +820,7 @@ func FormatSinglePartition(partDevPath string, partition configuration.Partition
}, totalAttempts, retryDuration)
if err != nil {
err = fmt.Errorf("could not format partition with type %v after %v retries", fsType, totalAttempts)
return "", err
}
case "linux-swap":
err = retry.Run(func() error {
Expand All @@ -837,6 +833,7 @@ func FormatSinglePartition(partDevPath string, partition configuration.Partition
}, totalAttempts, retryDuration)
if err != nil {
err = fmt.Errorf("could not format partition with type %v after %v retries", fsType, totalAttempts)
return "", err
}

_, stderr, err := shell.Execute("swapon", partDevPath)
Expand Down
Loading

0 comments on commit 656a422

Please sign in to comment.