Skip to content

Commit c2cc56c

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 8916185 commit c2cc56c

File tree

4 files changed

+41
-0
lines changed

4 files changed

+41
-0
lines changed

docs/release-notes.md

+4
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ nav_order: 9
1010

1111
### Features
1212

13+
- Support partitioning disk with mounted partitions
14+
1315
### Changes
1416

17+
- The Dracut module now installs partx
18+
1519
### Bug fixes
1620

1721
- Fix Akamai Ignition base64 decoding on padded payloads

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"
@@ -92,6 +93,7 @@ func GroupaddCmd() string { return groupaddCmd }
9293
func GroupdelCmd() string { return groupdelCmd }
9394
func MdadmCmd() string { return mdadmCmd }
9495
func MountCmd() string { return mountCmd }
96+
func PartxCmd() string { return partxCmd }
9597
func SgdiskCmd() string { return sgdiskCmd }
9698
func ModprobeCmd() string { return modprobeCmd }
9799
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)