Skip to content

fix(core): add O_DIRECT for NFS#2029

Merged
nevermarine merged 33 commits intomainfrom
fix/cdi/add-direct-flag-for-scratch-pvc
Mar 5, 2026
Merged

fix(core): add O_DIRECT for NFS#2029
nevermarine merged 33 commits intomainfrom
fix/cdi/add-direct-flag-for-scratch-pvc

Conversation

@nevermarine
Copy link
Collaborator

@nevermarine nevermarine commented Feb 26, 2026

Description

NFS: use O_DIRECT and qemu-img cache=none with fallback

  • NFS detection
    Added util.IsPathOnNFS(path) (Linux: statfs + NFS_SUPER_MAGIC; other OS: always false) so we can detect when the destination is on NFS.

  • Importer write path (io.Copy)
    In streamDataToFile (pkg/importer/util.go), when the destination is on NFS we first open the file with O_DIRECT (util.OpenFileOrBlockDeviceWithDirectIO on Linux) and use io.Copy. If opening with O_DIRECT fails, we fall back to a normal open and copy. Added OpenFileOrBlockDeviceWithDirectIO in pkg/util (Linux implementation + stub on other platforms).

  • qemu-img convert
    For NFS destinations, ConvertToFormatStream now runs qemu-img with -t none -T none. If that fails, it retries with -t writeback -T writeback. The internal helper is convertTo(format, src, dest, preallocate, cacheMode); the public API is a single ConvertToFormatStream(..., useDirectIO bool).

  • Where it’s used
    Data processor convert phase and uploadserver clone flow call IsPathOnNFS on the destination and pass the result as useDirectIO into ConvertToFormatStream. NFS is checked once per flow; O_DIRECT and cache=none are tried first, with fallback only when open or convert fails.

  • Logging
    NFS detection, O_DIRECT usage, and fallbacks are logged at klog.V(1).

Why do we need it, and what problem does it solve?

When CDI imports or clones disk images onto NFS-backed PVCs, the importer writes through the page cache (normal io.Copy and qemu-img with default cache mode). On NFS this can lead to high memory use and OOMs because data is buffered in the client’s page cache before being sent over the network, and qemu-img also uses the page cache when writing the converted image. To reduce memory pressure and improve behaviour on NFS, we should bypass the page cache where the filesystem allows it: use O_DIRECT for the importer’s file writes and qemu-img convert -t none -T none so that both source and target use direct I/O. This PR adds NFS detection (via statfs and NFS_SUPER_MAGIC) and, when the destination is on NFS, tries O_DIRECT for io.Copy and cache=none for qemu-img convert, with an automatic fallback to the previous behaviour if either fails (e.g. if the NFS server or mount does not support direct I/O). After merging, imports and clones to NFS volumes use less memory and are less likely to hit OOM, while non-NFS and unsupported NFS setups keep working as before.

What is the expected result?

  • NFS destination

    1. Create a PVC backed by NFS (or use an existing NFS PVC).
    2. Import or clone a disk image into that PVC (e.g. HTTP import, registry, or clone from another PVC).
    3. In importer logs at -v=1 you should see messages such as: destination on NFS, attempt to write with O_DIRECT; and for convert: “Destination on NFS, running qemu-img convert with -t none -T none”.
    4. Import/clone completes successfully and the VM can use the disk. No OOM from the importer pod during the write/convert phase.
  • Fallback when direct I/O is not supported

    1. Use an NFS mount (or other filesystem) that does not support O_DIRECT / cache=none for the target file.
    2. Run the same import or clone.
    3. Logs at -v=1 should show fallback messages (e.g. “O_DIRECT open failed … falling back to normal write” and/or “qemu-img convert with -t none -T none failed … falling back to writeback”).
    4. Import/clone still completes using the fallback path (normal write and/or writeback cache).
  • Non-NFS destination

    1. Import or clone to a non-NFS volume (e.g. local storage, block, or other non-NFS filesystem).
    2. Behaviour is unchanged: no NFS-specific messages, no O_DIRECT or cache=none for the importer; existing logic (including existing cache-mode handling) applies.
    3. Import/clone completes as before.

Checklist

  • The code is covered by unit tests.
  • e2e tests passed.
  • Documentation updated according to the changes.
  • Changes were tested in the Kubernetes cluster manually.

Changelog entries

section: core
type: fix
summary: "Fixed a potential `OOMKill` during virtual disk creation on NFS."

Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
@nevermarine nevermarine added this to the v1.7.0 milestone Feb 26, 2026
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
@nevermarine nevermarine added build/github/ubuntu Run jobs on github runners and removed build/github/ubuntu Run jobs on github runners labels Feb 26, 2026
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
2
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
3
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
4
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
2
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
4
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
@nevermarine nevermarine marked this pull request as ready for review March 5, 2026 14:17
@nevermarine nevermarine requested a review from Isteb4k as a code owner March 5, 2026 14:17
@nevermarine nevermarine changed the title fix(cdi): add direct flag for scratch pvc fix(core): add O_DIRECT for NFS Mar 5, 2026
@Isteb4k Isteb4k modified the milestones: v1.7.0, v1.5.2 Mar 5, 2026
@nevermarine nevermarine merged commit 82246e3 into main Mar 5, 2026
40 of 43 checks passed
@nevermarine nevermarine deleted the fix/cdi/add-direct-flag-for-scratch-pvc branch March 5, 2026 14:22
@nevermarine
Copy link
Collaborator Author

/backport v1.5.2

@deckhouse-BOaTswain
Copy link
Contributor

Failure: cherry-pick commit 82246e3 to the branch release-1.5 failed. See Job for details.

nevermarine added a commit that referenced this pull request Mar 5, 2026
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
This was referenced Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants