Referencia Zigconduit-zig (SDK consumido)

zig/storage.zig

Declaraciones públicas de zig/storage.zig (conduit-zig (SDK consumido)).

ImplementadoSin versión del tren todavía· generada desde apps/docs/generated/zig/conduit.json

Página generada desde conduit@conduit-0.1.0-f7J_7zg5DwCsHBHItwdOz9ZVq8cvH7ceFsk7-m3-T61t (zig/root.zig). No se edita a mano: bun run docs:gen la regenera y bun run docs:check falla si difiere.

Staging storage of the receiving side: space reservation, direct I/O and durability (spec/wire-v2.md §8). No wire change: it applies to v1 sessions too.

  • reserve: real blocks for the whole file at create. Linux fallocate mode 0, macOS F_PREALLOCATE (contiguous, then any) + ftruncate, elsewhere nothing. Never the posix_fallocate emulation (it writes zeros). ENOSPC/EDQUOT are error.NoSpace (→ 507); a filesystem without the call is .unsupported and the upload goes on unreserved.
  • openDirect: a second descriptor on the staging file that bypasses the page cache. Linux: O_DIRECT set with F_SETFL (the kernel refuses it with EINVAL where the filesystem has no direct I/O) and the alignment from statx(STATX_DIOALIGN); macOS: F_NOCACHE, no alignment.
  • Pool + DirectWriter: one chunk streamed through two aligned buffers; a full buffer goes out while the other fills, through io_uring on Linux. Fallbacks, chosen at runtime and counted in Stats: ring refused (ENOSYS, EPERM under seccomp, kernel.io_uring_disabled) or switched off → pwrite on the direct descriptor; a direct write refused (EINVAL) → buffered pwrite of the same bytes; short write → the rest buffered; no buffer free or chunk not eligible → the whole chunk buffered.
  • syncData: fdatasync (Linux), F_FULLFSYNC (macOS), fsync elsewhere — called once, at commit.

Every path that fails returns an error; nothing here panics on I/O. The writer always drains what it submitted before returning, so a buffer is never reused (or a descriptor closed) while the kernel may still read it.

storage.is_linux

const · línea 38

pub const is_linux = builtin.os.tag == .linux

Sin ///.

storage.is_darwin

const · línea 39

pub const is_darwin = builtin.os.tag.isDarwin()

Sin ///.

storage.page_align

const · línea 45

pub const page_align = 4096

Alignment of the direct buffers and lower bound of the offset alignment used (a page: a direct region never shares a page with a buffered tail).

storage.Inject

type · línea 49

pub const Inject = if (builtin.is_test) struct else void

Faults a test can force on each fallback; void outside tests.

storage.Options

type · línea 69

pub const Options = struct

Sin ///.

storage.Options.valid

fn · línea 94

pub fn valid(o: Options) bool

Sin ///.

storage.Options.max_direct_writers

const · línea 99

pub const max_direct_writers = 256

Sin ///.

storage.Stats

type · línea 103

pub const Stats = struct

What the storage layer did, for operators and tests (monotonic counters).

storage.ReserveError

const · línea 141

pub const ReserveError = error{ /// ENOSPC / EDQUOT: there is not room for the whole file. NoSpace, /// Larger than the filesystem allows for one file. FileTooBig, Io, }

Sin ///.

storage.Reserved

type · línea 149

pub const Reserved = enum

Sin ///.

storage.reserve

fn · línea 152

pub fn reserve(f: zfs.File, len: u64, o: *const Options) ReserveError!Reserved

Real blocks for [0, len) of f, file size set to len.

storage.discard

fn · línea 211

pub fn discard(f: zfs.File) void

Give back the blocks of an abandoned staging file: truncate it to 0. A reservation (fallocate, F_PREALLOCATE) belongs to the inode, not the name, so unlinking alone keeps it while any descriptor is open — and a pinned writer keeps one until it lets go. After this, a late pwrite of that writer only re-extends the file sparsely, by what it writes.

Only an inode no name links any more is truncated: call it after the unlink. A file some finalizer moved or linked elsewhere before failing keeps its bytes. Best effort: a failure is logged and the blocks go with the last close.

storage.SyncError

const · línea 260

pub const SyncError = error{ NoSpace, Io }

Sin ///.

storage.syncData

fn · línea 263

pub fn syncData(f: zfs.File) SyncError!void

Data (and the metadata needed to read it back) on stable storage.

storage.Direct

type · línea 284

pub const Direct = struct

Sin ///.

storage.Direct.close

fn · línea 292

pub fn close(d: Direct) void

Sin ///.

storage.openDirect

fn · línea 300

pub fn openDirect(root: *const Root, name: []const u8, main: zfs.File, o: *const Options, stats: *Counters) ?Direct

A page-cache-bypassing descriptor on the staging entry name of root, which must be the file main is open on; null when the platform or the filesystem has no direct I/O (the session then writes buffered).

storage.WriteError

const · línea 353

pub const WriteError = error{ NoSpace, Io }

Sin ///.

storage.Slot

type · línea 357

pub const Slot = struct

Buffers (and ring) of one direct writer; owned by the pool, lent to one chunk at a time.

storage.Pool

type · línea 366

pub const Pool = struct

Up to Options.direct_writers slots. acquire/release are called under the caller's lock (the server mutex); the counters are atomic.

storage.Pool.init

fn · línea 378

pub fn init(gpa: Allocator, o: *const Options) Allocator.Error!Pool

Sin ///.

storage.Pool.deinit

fn · línea 388

pub fn deinit(p: *Pool, gpa: Allocator) void

Sin ///.

storage.Pool.stats

fn · línea 397

pub fn stats(p: *const Pool) Stats

Sin ///.

storage.Pool.acquire

fn · línea 403

pub fn acquire(p: *Pool, gpa: Allocator) ?*Slot

A slot with its buffers, or null (none free, or no memory for the buffers): the chunk is then written buffered.

storage.Pool.release

fn · línea 421

pub fn release(p: *Pool, s: *Slot) void

Sin ///.

storage.DirectWriter

type · línea 430

pub const DirectWriter = struct

Writes one chunk [offset, offset + len) of the staging file. Built by the server only for eligible chunks (direct descriptor, len >= direct_min, offset a multiple of offset_align, a slot).

storage.DirectWriter.init

fn · línea 447

pub fn init(pool: *Pool, slot: *Slot, direct: Direct, buffered: zfs.File, offset: u64) DirectWriter

Sin ///.

storage.DirectWriter.eligible

fn · línea 454

pub fn eligible(o: *const Options, d: ?Direct, offset: u64, len: u64) bool

Whether a chunk can go direct (the server also needs a free slot).

storage.DirectWriter.write

fn · línea 459

pub fn write(w: *DirectWriter, bytes: []const u8) WriteError!void

Sin ///.

storage.DirectWriter.finish

fn · línea 473

pub fn finish(w: *DirectWriter) WriteError!void

End of the body: the aligned part of what is buffered goes direct, the tail buffered; returns once every byte is written (or failed).

storage.DirectWriter.abandon

fn · línea 487

pub fn abandon(w: *DirectWriter) void

Give up: waits for whatever the kernel still holds, ignores results. Idempotent; after it no buffer is in use.

storage.writeAllAt

fn · línea 656

pub fn writeAllAt(f: zfs.File, bytes: []const u8, offset: u64, o: *const Options) WriteError!void

Buffered pwrite of the whole of bytes, errors folded to WriteError.

storage.countBuffered

fn · línea 664

pub fn countBuffered(p: *Pool) void

Sin ///.

storage.countReserve

fn · línea 668

pub fn countReserve(p: *Pool, r: Reserved) void

Sin ///.