Skip to content

vllm.v1.kv_offload.tiering.fs.io

Functions:

  • batch_load_block

    Load a batch of KV blocks from disk into a shared buffer in one call.

  • batch_store_block

    Store a batch of KV blocks from a shared buffer to disk in one call.

  • probe_o_direct

    Return whether O_DIRECT I/O works in directory.

_ensure_dirs(path)

Create parent directories of path if they don't exist.

Source code in vllm/v1/kv_offload/tiering/fs/io.py
def _ensure_dirs(path: str) -> None:
    """Create parent directories of *path* if they don't exist."""
    os.makedirs(os.path.dirname(path), exist_ok=True)

_get_tmp_suffix()

Generate a thread-local unique suffix for temporary files.

Source code in vllm/v1/kv_offload/tiering/fs/io.py
def _get_tmp_suffix() -> str:
    """Generate a thread-local unique suffix for temporary files."""
    try:
        return _thread_local.tmp_suffix
    except AttributeError:
        _thread_local.tmp_suffix = f"_{random.randint(0, 2**63 - 1)}.tmp"
        return _thread_local.tmp_suffix

_load_block(source_path, view, offset, block_size, use_o_direct=True)

Load callback: read one KV block from disk. Remove the file on failure.

Source code in vllm/v1/kv_offload/tiering/fs/io.py
def _load_block(
    source_path: str,
    view: memoryview,
    offset: int,
    block_size: int,
    use_o_direct: bool = True,
) -> None:
    """
    Load callback: read one KV block from disk. Remove the file on failure.
    """
    fd: int | None = None
    view_slice = view.cast("B")[offset : offset + block_size]
    o_direct = O_DIRECT if use_o_direct else 0

    try:
        fd = os.open(source_path, os.O_RDONLY | o_direct)
        bytes_read = os.readv(fd, [view_slice])
        if bytes_read < block_size:
            raise OSError(f"Short read: expected {block_size} bytes, read {bytes_read}")
    except Exception:
        try:
            os.remove(source_path)
        except OSError as cleanup_exc:
            logger.warning(
                "Failed to remove unreadable file %s: %s", source_path, cleanup_exc
            )
        raise
    finally:
        if fd is not None:
            os.close(fd)

_store_block(dest_path, buffer, offset, block_size, use_o_direct=True)

Store callback: Writes to a temp file then atomically replaces the destination.

Source code in vllm/v1/kv_offload/tiering/fs/io.py
def _store_block(
    dest_path: str,
    buffer: memoryview,
    offset: int,
    block_size: int,
    use_o_direct: bool = True,
) -> None:
    """
    Store callback: Writes to a temp file then atomically replaces the destination.
    """
    # Check if block already exists to avoid redundant writes
    if os.path.exists(dest_path):
        return

    tmp_path = dest_path + _get_tmp_suffix()
    # Ensure parent directories exist
    _ensure_dirs(dest_path)

    # Write block atomically. Cast to a flat byte view so the slice uses byte
    # indices; the raw memoryview may be multi-dimensional with itemsize > 1.
    view_slice = buffer.cast("B")[offset : offset + block_size]
    o_direct = O_DIRECT if use_o_direct else 0
    try:
        fd = os.open(
            tmp_path,
            os.O_CREAT | os.O_EXCL | os.O_WRONLY | os.O_TRUNC | o_direct,
            0o644,
        )
        try:
            written = os.write(fd, view_slice)
            if written < len(view_slice):
                raise OSError(
                    f"Short write: expected {len(view_slice)} bytes, wrote {written}"
                )
        finally:
            os.close(fd)
        os.replace(tmp_path, dest_path)
    except Exception:
        try:
            os.remove(tmp_path)
        except OSError as cleanup_exc:
            logger.warning("Failed to remove temp file %s: %s", tmp_path, cleanup_exc)
        raise

_validate_offsets(view, offsets, block_size)

Raise if any block would read/write past the bounds of view.

Without this, an out-of-range offset silently clips to a shorter (or empty) slice instead of failing, since memoryview slicing follows Python's slice-clamping semantics rather than raising.

Source code in vllm/v1/kv_offload/tiering/fs/io.py
def _validate_offsets(view: memoryview, offsets: list[int], block_size: int) -> None:
    """Raise if any block would read/write past the bounds of `view`.

    Without this, an out-of-range offset silently clips to a shorter (or
    empty) slice instead of failing, since memoryview slicing follows
    Python's slice-clamping semantics rather than raising.
    """
    total_len = len(view.cast("B"))
    for offset in offsets:
        if offset < 0 or offset + block_size > total_len:
            raise ValueError(
                f"block offset {offset} (block_size {block_size}) is out of "
                f"bounds for a buffer of size {total_len}"
            )

batch_load_block(paths, view, offsets, block_size, use_o_direct=True)

Load a batch of KV blocks from disk into a shared buffer in one call.

Block i is read from source_paths[i] into view[offsets[i] : offsets[i]+block_size]. Raises on first error and removes the offending file.

Source code in vllm/v1/kv_offload/tiering/fs/io.py
def batch_load_block(
    paths: list[str],
    view: memoryview,
    offsets: list[int],
    block_size: int,
    use_o_direct: bool = True,
) -> None:
    """
    Load a batch of KV blocks from disk into a shared buffer in one call.

    Block i is read from source_paths[i] into view[offsets[i] : offsets[i]+block_size].
    Raises on first error and removes the offending file.
    """
    _validate_offsets(view, offsets, block_size)

    if _HAS_FSIO_C:
        view_B = view.cast("B")
        view_slices = [view_B[x : x + block_size] for x in offsets]
        return batch_load_block_C(paths, view_slices, use_o_direct)
    else:
        for path, offset in zip(paths, offsets):
            _load_block(path, view, offset, block_size, use_o_direct)

batch_store_block(paths, view, offsets, block_size, use_o_direct=True)

Store a batch of KV blocks from a shared buffer to disk in one call.

Each block buffer[offsets[i] : offsets[i]+block_size] is written atomically to dest_paths[i] via a temp-file rename. Raises on first error.

Source code in vllm/v1/kv_offload/tiering/fs/io.py
def batch_store_block(
    paths: list[str],
    view: memoryview,
    offsets: list[int],
    block_size: int,
    use_o_direct: bool = True,
) -> None:
    """
    Store a batch of KV blocks from a shared buffer to disk in one call.

    Each block buffer[offsets[i] : offsets[i]+block_size] is written atomically
    to dest_paths[i] via a temp-file rename.  Raises on first error.
    """
    _validate_offsets(view, offsets, block_size)

    if _HAS_FSIO_C:
        view_B = view.cast("B")
        view_slices = [view_B[x : x + block_size] for x in offsets]
        tmp_paths = [p + _get_tmp_suffix() for p in paths]
        return batch_store_block_C(tmp_paths, paths, view_slices, use_o_direct)
    else:
        for path, offset in zip(paths, offsets):
            _store_block(path, view, offset, block_size, use_o_direct)

probe_o_direct(directory)

Return whether O_DIRECT I/O works in directory.

O_DIRECT is unsupported on some filesystems (e.g. the overlayfs backing a container /tmp, older tmpfs, or some NFS mounts), where opening or writing a file with it fails with EINVAL. Probe once with an aligned single-page write so callers can fall back to buffered I/O instead of failing on every block.

Source code in vllm/v1/kv_offload/tiering/fs/io.py
def probe_o_direct(directory: str) -> bool:
    """Return whether ``O_DIRECT`` I/O works in *directory*.

    ``O_DIRECT`` is unsupported on some filesystems (e.g. the overlayfs backing
    a container ``/tmp``, older tmpfs, or some NFS mounts), where opening or
    writing a file with it fails with ``EINVAL``. Probe once with an aligned
    single-page write so callers can fall back to buffered I/O instead of
    failing on every block.
    """
    if not O_DIRECT:
        return False
    path = os.path.join(directory, f".o_direct_probe{_get_tmp_suffix()}")
    page = mmap.mmap(-1, mmap.PAGESIZE)
    try:
        fd = os.open(path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC | O_DIRECT, 0o644)
        try:
            os.write(fd, page)
        finally:
            os.close(fd)
        return True
    except OSError:
        return False
    finally:
        page.close()
        with contextlib.suppress(OSError):
            os.remove(path)