@@ -23,6 +23,7 @@ import (
23
23
"errors"
24
24
"fmt"
25
25
"os"
26
+ "os/exec"
26
27
"path/filepath"
27
28
"regexp"
28
29
"sort"
@@ -31,6 +32,7 @@ import (
31
32
32
33
cutil "github.com/coreos/ignition/v2/config/util"
33
34
"github.com/coreos/ignition/v2/config/v3_5_experimental/types"
35
+ "github.com/coreos/ignition/v2/internal/distro"
34
36
"github.com/coreos/ignition/v2/internal/exec/util"
35
37
"github.com/coreos/ignition/v2/internal/sgdisk"
36
38
iutil "github.com/coreos/ignition/v2/internal/util"
@@ -472,6 +474,10 @@ func (s stage) partitionDisk(dev types.Disk, devAlias string) error {
472
474
return err
473
475
}
474
476
477
+ var partxAdd []uint64
478
+ var partxDelete []uint64
479
+ var partxUpdate []uint64
480
+
475
481
for _ , part := range resolvedPartitions {
476
482
shouldExist := partitionShouldExist (part )
477
483
info , exists := diskInfo .GetPartition (part .Number )
@@ -492,11 +498,13 @@ func (s stage) partitionDisk(dev types.Disk, devAlias string) error {
492
498
case ! exists && shouldExist :
493
499
op .CreatePartition (part )
494
500
modification = true
501
+ partxAdd = append (partxAdd , uint64 (part .Number ))
495
502
case exists && ! shouldExist && ! wipeEntry :
496
503
return fmt .Errorf ("partition %d exists but is specified as nonexistant and wipePartitionEntry is false" , part .Number )
497
504
case exists && ! shouldExist && wipeEntry :
498
505
op .DeletePartition (part .Number )
499
506
modification = true
507
+ partxDelete = append (partxDelete , uint64 (part .Number ))
500
508
case exists && shouldExist && matches :
501
509
s .Logger .Info ("partition %d found with correct specifications" , part .Number )
502
510
case exists && shouldExist && ! wipeEntry && ! matches :
@@ -510,6 +518,7 @@ func (s stage) partitionDisk(dev types.Disk, devAlias string) error {
510
518
part .StartSector = & info .StartSector
511
519
op .CreatePartition (part )
512
520
modification = true
521
+ partxUpdate = append (partxUpdate , uint64 (part .Number ))
513
522
} else {
514
523
return fmt .Errorf ("Partition %d didn't match: %v" , part .Number , matchErr )
515
524
}
@@ -518,6 +527,7 @@ func (s stage) partitionDisk(dev types.Disk, devAlias string) error {
518
527
op .DeletePartition (part .Number )
519
528
op .CreatePartition (part )
520
529
modification = true
530
+ partxUpdate = append (partxUpdate , uint64 (part .Number ))
521
531
default :
522
532
// unfortunatey, golang doesn't check that all cases are handled exhaustively
523
533
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 {
532
542
return fmt .Errorf ("commit failure: %v" , err )
533
543
}
534
544
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
+
535
569
// It's best to wait here for the /dev/ABC entries to be
536
570
// (re)created, not only for other parts of the initramfs but
537
571
// also because s.waitOnDevices() can still race with udev's
0 commit comments