Skip to content

Commit be36ed8

Browse files
committed
sgdisk: Run partx after partition changes
The sgdisk tool does not update the kernel partition table with BLKPG in contrast to other similar tools but only uses BLKRRPART which fails as soon as one partition of the disk is mounted. Update the kernel partition table with partx when we know that a partition of the disk is in use.
1 parent 4b5d709 commit be36ed8

File tree

4 files changed

+40
-0
lines changed

4 files changed

+40
-0
lines changed

docs/release-notes.md

+3
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@ nav_order: 9
1111
### Features
1212

1313
- Support Akamai Connected Cloud (Linode)
14+
- Support partitioning disk with mounted partitions
1415

1516
### Changes
1617

18+
- The Dracut module now installs partx
19+
1720
### Bug fixes
1821

1922
## Ignition 2.18.0 (2024-03-01)

dracut/30ignition/module-setup.sh

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ install() {
3939
mkfs.fat \
4040
mkfs.xfs \
4141
mkswap \
42+
partx \
4243
sgdisk \
4344
useradd \
4445
userdel \

internal/distro/distro.go

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var (
3636
groupdelCmd = "groupdel"
3737
mdadmCmd = "mdadm"
3838
mountCmd = "mount"
39+
partxCmd = "partx"
3940
sgdiskCmd = "sgdisk"
4041
modprobeCmd = "modprobe"
4142
udevadmCmd = "udevadm"
@@ -89,6 +90,7 @@ func GroupaddCmd() string { return groupaddCmd }
8990
func GroupdelCmd() string { return groupdelCmd }
9091
func MdadmCmd() string { return mdadmCmd }
9192
func MountCmd() string { return mountCmd }
93+
func PartxCmd() string { return partxCmd }
9294
func SgdiskCmd() string { return sgdiskCmd }
9395
func ModprobeCmd() string { return modprobeCmd }
9496
func UdevadmCmd() string { return udevadmCmd }

internal/exec/stages/disks/partitions.go

+34
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"errors"
2424
"fmt"
2525
"os"
26+
"os/exec"
2627
"path/filepath"
2728
"regexp"
2829
"sort"
@@ -31,6 +32,7 @@ import (
3132

3233
cutil "github.com/coreos/ignition/v2/config/util"
3334
"github.com/coreos/ignition/v2/config/v3_5_experimental/types"
35+
"github.com/coreos/ignition/v2/internal/distro"
3436
"github.com/coreos/ignition/v2/internal/exec/util"
3537
"github.com/coreos/ignition/v2/internal/sgdisk"
3638
iutil "github.com/coreos/ignition/v2/internal/util"
@@ -472,6 +474,10 @@ func (s stage) partitionDisk(dev types.Disk, devAlias string) error {
472474
return err
473475
}
474476

477+
var partxAdd []uint64
478+
var partxDelete []uint64
479+
var partxUpdate []uint64
480+
475481
for _, part := range resolvedPartitions {
476482
shouldExist := partitionShouldExist(part)
477483
info, exists := diskInfo.GetPartition(part.Number)
@@ -492,11 +498,13 @@ func (s stage) partitionDisk(dev types.Disk, devAlias string) error {
492498
case !exists && shouldExist:
493499
op.CreatePartition(part)
494500
modification = true
501+
partxAdd = append(partxAdd, uint64(part.Number))
495502
case exists && !shouldExist && !wipeEntry:
496503
return fmt.Errorf("partition %d exists but is specified as nonexistant and wipePartitionEntry is false", part.Number)
497504
case exists && !shouldExist && wipeEntry:
498505
op.DeletePartition(part.Number)
499506
modification = true
507+
partxDelete = append(partxDelete, uint64(part.Number))
500508
case exists && shouldExist && matches:
501509
s.Logger.Info("partition %d found with correct specifications", part.Number)
502510
case exists && shouldExist && !wipeEntry && !matches:
@@ -510,6 +518,7 @@ func (s stage) partitionDisk(dev types.Disk, devAlias string) error {
510518
part.StartSector = &info.StartSector
511519
op.CreatePartition(part)
512520
modification = true
521+
partxUpdate = append(partxUpdate, uint64(part.Number))
513522
} else {
514523
return fmt.Errorf("Partition %d didn't match: %v", part.Number, matchErr)
515524
}
@@ -518,6 +527,7 @@ func (s stage) partitionDisk(dev types.Disk, devAlias string) error {
518527
op.DeletePartition(part.Number)
519528
op.CreatePartition(part)
520529
modification = true
530+
partxUpdate = append(partxUpdate, uint64(part.Number))
521531
default:
522532
// unfortunatey, golang doesn't check that all cases are handled exhaustively
523533
return fmt.Errorf("Unreachable code reached when processing partition %d. golang--", part.Number)
@@ -532,6 +542,30 @@ func (s stage) partitionDisk(dev types.Disk, devAlias string) error {
532542
return fmt.Errorf("commit failure: %v", err)
533543
}
534544

545+
// In contrast to similar tools, sgdisk does not trigger the update of the
546+
// kernel partition table with BLKPG but only uses BLKRRPART which fails
547+
// as soon as one partition of the disk is mounted
548+
if len(activeParts) > 0 {
549+
runPartxCommand := func(op string, partitions []uint64) error {
550+
for _, partNr := range partitions {
551+
cmd := exec.Command(distro.PartxCmd(), "--"+op, "--nr", strconv.FormatUint(partNr, 10), blockDevResolved)
552+
if _, err := s.Logger.LogCmd(cmd, "triggering partition %d %s on %q", partNr, op, devAlias); err != nil {
553+
return fmt.Errorf("partition %s failed: %v", op, err)
554+
}
555+
}
556+
return nil
557+
}
558+
if err := runPartxCommand("delete", partxDelete); err != nil {
559+
return err
560+
}
561+
if err := runPartxCommand("update", partxUpdate); err != nil {
562+
return err
563+
}
564+
if err := runPartxCommand("add", partxAdd); err != nil {
565+
return err
566+
}
567+
}
568+
535569
// It's best to wait here for the /dev/ABC entries to be
536570
// (re)created, not only for other parts of the initramfs but
537571
// also because s.waitOnDevices() can still race with udev's

0 commit comments

Comments
 (0)