Skip to content

Commit b320857

Browse files
poll device readiness before formatting sticky disk
After a Firecracker drive hot-swap (PATCH /drives), the guest kernel learns the new backing device size via an async virtio config-change interrupt. Fast consumers like mkfs.ext4 can observe a zero device size if they run before the interrupt is processed. Poll blockdev --getsize64 until the device reports non-zero (up to 5s, 50ms interval) before attempting blkid or mkfs. Co-Authored-By: Paul Bardea <paul@blacksmith.sh>
1 parent ab5c1da commit b320857

3 files changed

Lines changed: 35 additions & 2 deletions

File tree

dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/setup_builder.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,41 @@ const execAsync = promisify(exec);
1616
// Tailscale functions removed - not needed for setup-docker-builder
1717
// Multi-platform builds are handled differently in the new architecture
1818

19+
// deviceReadyTimeoutMs is the max time to wait for the guest kernel's virtio-blk
20+
// driver to expose a non-zero device size after a Firecracker drive hot-swap.
21+
const deviceReadyTimeoutMs = 5000;
22+
const deviceReadyPollIntervalMs = 50;
23+
24+
async function waitForDeviceReady(device: string): Promise<void> {
25+
const start = Date.now();
26+
while (Date.now() - start < deviceReadyTimeoutMs) {
27+
try {
28+
const { stdout } = await execAsync(`blockdev --getsize64 ${device}`);
29+
const size = parseInt(stdout.trim(), 10);
30+
if (size > 0) {
31+
const elapsed = Date.now() - start;
32+
core.info(
33+
`Device ${device} ready: ${size} bytes (waited ${elapsed}ms)`,
34+
);
35+
return;
36+
}
37+
} catch {
38+
// blockdev may fail transiently while the device is settling
39+
}
40+
await new Promise((r) => setTimeout(r, deviceReadyPollIntervalMs));
41+
}
42+
throw new Error(
43+
`Device ${device} still reports zero size after ${deviceReadyTimeoutMs}ms — virtio-blk driver may not have processed the config-change interrupt`,
44+
);
45+
}
46+
1947
async function maybeFormatBlockDevice(device: string): Promise<string> {
2048
try {
49+
// After a Firecracker drive hot-swap the guest kernel learns the new
50+
// backing device size via an async virtio config-change interrupt.
51+
// Wait until the device reports a non-zero size before touching it.
52+
await waitForDeviceReady(device);
53+
2154
// Check if device is formatted with ext4
2255
try {
2356
const { stdout } = await execAsync(

0 commit comments

Comments
 (0)