containerd/containerd · error
failed to get block device size: %s: %w
Error message
failed to get block device size: %s: %w
What it means
makeThinPoolMapping builds the thin-pool table and must know the data device's byte size, which it obtains via BlockDeviceSize (an lseek to end of file). This error wraps whatever failure occurred while sizing the data file/device, aborting pool creation or reload.
Source
Thrown at plugins/snapshots/devmapper/dmsetup/dmsetup.go:103
thinPool, err := makeThinPoolMapping(dataFile, metaFile, blockSizeSectors)
if err != nil {
return err
}
_, err = dmsetup("reload", deviceName, "--table", thinPool)
return err
}
const (
lowWaterMark = 32768 // Picked arbitrary, might need tuning
skipZeroing = "skip_block_zeroing" // Skipping zeroing to reduce latency for device creation
)
// makeThinPoolMapping makes thin-pool table entry
func makeThinPoolMapping(dataFile, metaFile string, blockSizeSectors uint32) (string, error) {
dataDeviceSizeBytes, err := BlockDeviceSize(dataFile)
if err != nil {
return "", fmt.Errorf("failed to get block device size: %s: %w", dataFile, err)
}
// Thin-pool mapping target has the following format:
// start - starting block in virtual device
// length - length of this segment
// metadata_dev - the metadata device
// data_dev - the data device
// data_block_size - the data block size in sectors
// low_water_mark - the low water mark, expressed in blocks of size data_block_size
// feature_args - the number of feature arguments
// args
lengthSectors := dataDeviceSizeBytes / SectorSize
target := fmt.Sprintf("0 %d thin-pool %s %s %d %d 1 %s",
lengthSectors,
metaFile,
dataFile,
blockSizeSectors,
lowWaterMark,View on GitHub (pinned to 4246446a2b)
Solutions
- Check the wrapped cause (%w) in the error — it names the underlying open/seek failure.
- Verify the data file/device path exists and is readable/writable by the process.
- Recreate the pool: ensure the sparse data file is created with correct size before makeThinPoolMapping runs.
- Check host disk health/space and that the loopback device is attached (losetup).
Example fix
// before
err := pool.CreatePool() // data file never created
// after
if err := createSparseFile(dataFile, sizeBytes); err != nil { return err }
if err := pool.CreatePool(); err != nil { return fmt.Errorf("pool create: %w", err) } Defensive patterns
Strategy: try-catch
Validate before calling
func checkDataDevice(path string) error {
fi, err := os.Stat(path)
if err != nil { return fmt.Errorf("data device missing: %w", err) }
if !fi.Mode().IsRegular() && fi.Mode()&os.ModeDevice == 0 {
return fmt.Errorf("%s is not a seekable file/device", path)
}
return nil
} Try / catch
table, err := CreatePool(...)
if err != nil {
var sizeErr error
if strings.Contains(err.Error(), "failed to get block device size") {
sizeErr = checkDataDevice(dataFile)
}
return fmt.Errorf("pool create failed: %w (device check: %v)", err, sizeErr)
} Prevention
- Create and verify the sparse data file before CreatePool
- Check disk space and permissions on the pool directory
- Monitor host storage health (dmesg, smartctl)
- Log the wrapped cause (%w) to distinguish open vs seek failures
When it happens
Trigger: CreatePool or ReloadPool -> makeThinPoolMapping -> BlockDeviceSize fails: the data file/device path is wrong, cannot be opened, or the seek to SEEK_END fails.
Common situations: The loopback data file was not created before pool setup; permission problems on /dev or the data dir; the underlying block device disappeared (VM disk detach); filesystem errors on the host.
Related errors
- failed to seek on %q: %w
- dmsetup %s error: %s : %w
- failed to parse line %q: %w
- failed to parse output: %q
- failed to parse offset: %q: %w
AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02).
Data as JSON: /api/errors/689e520d2cd4498f.
Report an issue: GitHub.