Skip to content

Commit 72bf418

Browse files
Merge pull request #2034 from andfasano/fix-root-partition-copy-cmd
OCPBUGS-76382: Fix root partition before copying IRI registry data
2 parents e5e1022 + 9a9222e commit 72bf418

File tree

2 files changed

+64
-36
lines changed

2 files changed

+64
-36
lines changed

src/ops/ops.go

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,22 +1263,29 @@ func (o *ops) CopyRegistryData(liveLogger io.Writer, device string) error {
12631263
return err
12641264
}
12651265

1266-
// Calculate the target free percent of the device
1267-
freePercent, err := o.calculateFreePercent(device, &registryDataSize)
1266+
// Calculate the target free percent of the device. Reserve at least 2.5 times
1267+
// the current data registry size.
1268+
requestedSize := registryDataSize * 5 / 2
1269+
freePercent, err := o.calculateFreePercent(device, &requestedSize)
12681270
if err != nil {
12691271
return err
12701272
}
1271-
if freePercent == 0 {
1272-
return errors.Errorf("device %s is not large enough to fit the registry data", device)
1273+
o.log.Infof("Requesting at least %d bytes for the root partition on device %s (current registry size: %d bytes)", requestedSize, device, registryDataSize)
1274+
// Ensure to have at least some minimum free space available otherwise coreos-gpt-setup.service may fail on the next reboot,
1275+
// since it requires at least some free blocks at the end of the disk.
1276+
minAllowedFreePercent := int64(1)
1277+
if freePercent < minAllowedFreePercent {
1278+
return errors.Errorf("device %s is not large enough to fit the registry data (%d bytes)", device, requestedSize)
12731279
}
12741280

1275-
// Generate command for growing root partition to fit the registry data
1276-
growPartCmd := makecmd(nil, "growpart", fmt.Sprintf("--free-percent=%d", freePercent), device, "4")
1281+
// Generate command for growing root partition to fit the requested size
1282+
partIndex := "4"
1283+
growPartCmd := makecmd(nil, "growpart", fmt.Sprintf("--free-percent=%d", freePercent), device, partIndex)
12771284

12781285
// Get root partition path
1279-
partition4, err := o.getPartitionPathFromLsblk(device, "4")
1286+
partition4, err := o.getPartitionPathFromLsblk(device, partIndex)
12801287
if err != nil {
1281-
return errors.Wrapf(err, "failed to find partition 4 for device %s", device)
1288+
return errors.Wrapf(err, "failed to find partition %s for device %s", partIndex, device)
12821289
}
12831290

12841291
// Generate the path to the registry data directory on the mounted root partitio
@@ -1289,18 +1296,43 @@ func (o *ops) CopyRegistryData(liveLogger io.Writer, device string) error {
12891296

12901297
// Generate the command for unfreezing the root partition (frozen by OverwriteOsImage func)
12911298
// Ignoring errors if the partition is already unfrozen
1292-
fsUnfreezeCmd := makecmd(nil, "sh", "-c", "fsfreeze --unfreeze /mnt/root || true")
1299+
mntTmpPath := "/mnt/root"
1300+
fsUnfreezeCmd := makecmd(nil, "sh", "-c", fmt.Sprintf("fsfreeze --unfreeze %s || true", mntTmpPath))
1301+
fsFreezeCmd := makecmd(nil, "fsfreeze", "--freeze", mntTmpPath)
1302+
mountCmd := makecmd(nil, "mount", partition4, mntTmpPath)
1303+
unmountCmd := makecmd(nil, "umount", mntTmpPath)
1304+
1305+
ignTransposeScript := "/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs.sh"
1306+
// The transposefs script does not have a way to apply unconditionally the autosave-xfs command
1307+
xfsForceAutosaveCmd := makecmd(nil, "bash", "-c", fmt.Sprintf(`sed 's/threshold=[0-9]*/threshold=0/' %s | bash -s autosave-xfs`, ignTransposeScript))
1308+
xfsRestoreCommand := makecmd(nil, "bash", "-c", fmt.Sprintf("%s restore", ignTransposeScript))
1309+
xfsCleanupCommand := makecmd(nil, "bash", "-c", fmt.Sprintf("%s cleanup", ignTransposeScript))
12931310

12941311
cmds := []*cmd{
1295-
makecmd(nil, "mkdir", "-p", "/mnt/root"),
1296-
makecmd(nil, "mount", partition4, "/mnt/root"),
1312+
makecmd(nil, "mkdir", "-p", mntTmpPath),
1313+
1314+
// Unfreeze
1315+
mountCmd,
12971316
fsUnfreezeCmd,
1317+
unmountCmd, // This is required before invoking the autosave-xfs
1318+
1319+
// Extend the root partition to allow the autosave-xfs command to recalculate the new AG size
1320+
// before copying the InternalReleaseImage registry data.
1321+
// See https://github.com/coreos/fedora-coreos-tracker/issues/1183 for more details.
12981322
growPartCmd,
1299-
makecmd(nil, "xfs_growfs", "/mnt/root"),
1323+
xfsForceAutosaveCmd,
1324+
xfsRestoreCommand,
1325+
xfsCleanupCommand,
1326+
1327+
// Copy registry data
1328+
mountCmd, // Re-mount before copying data
1329+
makecmd(nil, "xfs_growfs", mntTmpPath),
13001330
makecmd(nil, "mkdir", "-p", registryDataDirOnRoot),
13011331
copyCmd,
1302-
makecmd(nil, "fsfreeze", "--freeze", "/mnt/root"),
1303-
makecmd(nil, "umount", "/mnt/root"),
1332+
1333+
// Freeze
1334+
fsFreezeCmd,
1335+
unmountCmd,
13041336
}
13051337
for i := range cmds {
13061338
c := cmds[i]

src/ops/ops_test.go

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,7 @@ var _ = Describe("Copy registry data", func() {
12541254
"du",
12551255
"-sb",
12561256
dataDir)...).Return(strconv.FormatInt(int64(registryDataSize), 10), nil).Times(1)
1257-
// Mock lsblk calls for partition path discovery
1257+
// Mock lsblk calls for partition path discovery / calculateFreePercent function
12581258
execMock.EXPECT().ExecCommand(nil, "nsenter",
12591259
append([]interface{}{},
12601260
"--target",
@@ -1267,21 +1267,22 @@ var _ = Describe("Copy registry data", func() {
12671267
"lsblk",
12681268
"--bytes",
12691269
"--json",
1270-
device)...).Return(formatResult(device), nil).Times(1)
1271-
// Mock lsblk call for calculateFreePercent function
1272-
execMock.EXPECT().ExecCommand(nil, "nsenter",
1273-
append([]interface{}{},
1274-
"--target",
1275-
"1",
1276-
"--cgroup",
1277-
"--mount",
1278-
"--ipc",
1279-
"--pid",
1280-
"--",
1281-
"lsblk",
1282-
"--bytes",
1283-
"--json",
1284-
device)...).Return(formatResult(device), nil)
1270+
device)...).Return(formatResult(device), nil).Times(2)
1271+
1272+
mockPrivileged("mkdir", "-p", "/mnt/root")
1273+
mockPrivileged("mount", part4, "/mnt/root")
1274+
mockPrivileged("sh", "-c", "fsfreeze --unfreeze /mnt/root || true")
1275+
mockPrivileged("umount", "/mnt/root")
1276+
1277+
mockPrivileged("growpart", "--free-percent=42", device, "4")
1278+
mockPrivileged("bash", "-c", "sed 's/threshold=[0-9]*/threshold=0/' /usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs.sh | bash -s autosave-xfs")
1279+
mockPrivileged("bash", "-c", "/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs.sh restore")
1280+
mockPrivileged("bash", "-c", "/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs.sh cleanup")
1281+
1282+
mockPrivileged("mount", part4, "/mnt/root")
1283+
mockPrivileged("xfs_growfs", "/mnt/root")
1284+
mockPrivileged("mkdir", "-p", registryDataDirOnRoot)
1285+
12851286
// Mock rsync call
12861287
execMock.EXPECT().ExecCommand(io.Discard, "nsenter",
12871288
append([]interface{}{},
@@ -1296,14 +1297,9 @@ var _ = Describe("Copy registry data", func() {
12961297
"-c",
12971298
fmt.Sprintf("rsync -ah --info=progress2 %s/ %s/", dataDir, registryDataDirOnRoot))...).Return("", nil).Times(1)
12981299

1299-
mockPrivileged("mkdir", "-p", "/mnt/root")
1300-
mockPrivileged("mount", part4, "/mnt/root")
1301-
mockPrivileged("sh", "-c", "fsfreeze --unfreeze /mnt/root || true")
1302-
mockPrivileged("growpart", "--free-percent=74", device, "4")
1303-
mockPrivileged("xfs_growfs", "/mnt/root")
1304-
mockPrivileged("mkdir", "-p", registryDataDirOnRoot)
13051300
mockPrivileged("fsfreeze", "--freeze", "/mnt/root")
13061301
mockPrivileged("umount", "/mnt/root")
1302+
13071303
err := o.CopyRegistryData(io.Discard, device)
13081304
Expect(err).ToNot(HaveOccurred())
13091305
}

0 commit comments

Comments
 (0)