Overview

The writeonce platform is a single Rust binary that replaces PostgreSQL, AWS Lambda, S3, and a separate API server with direct Linux kernel syscalls. Every I/O operation — file watching, network serving, event signaling, storage reads — runs on one epoll event loop using kernel primitives. No tokio, no async-std, no external runtime.

This article documents every kernel syscall used in the project and where it fits in the architecture.

inotify — File Watching

The content directory is watched using inotify. When an article's .json or .md file is created, modified, or deleted, inotify delivers an event to the event loop. This replaces the old S3 + Lambda sync pipeline entirely.

// wo-watch crate
let fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
inotify_add_watch(fd, content_dir, IN_CREATE | IN_MODIFY | IN_DELETE);

The watcher maps file changes to ContentChange::Created, Modified, or Deleted events. Each event triggers a store rebuild and subscriber notification — all within the same process.

epoll — The Event Loop

Every file descriptor in the system registers on a single epoll instance. The main loop calls epoll_wait and dispatches based on which fd is ready.

// wo-event crate
let epoll_fd = epoll_create1(EPOLL_CLOEXEC);
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, inotify_fd, EPOLLIN);
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, signal_fd, EPOLLIN);
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, timer_fd, EPOLLIN);
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, http_listener_fd, EPOLLIN);

Registered fds and their tokens:

  • Token 1 — inotify (content file watcher)
  • Token 2 — signalfd (SIGINT/SIGTERM)
  • Token 3 — timerfd (periodic tasks)
  • Token 4 — eventfd (subscription notifications)
  • Token 5 — HTTP listener socket
  • 10000+ — HTTP client connections
  • 20000+ — subscribed browser connections

One process, one thread, one epoll_wait call driving everything.

eventfd — Lightweight Signaling

The subscription manager uses eventfd to signal the event loop when notifications have been delivered to subscriber fds. It is a counter-based fd — write increments, read resets.

// wo-event crate
let efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
// signal: write(efd, 1)
// consume: read(efd) -> returns accumulated count

Used between the content watcher and the subscription manager: when inotify detects a change, the watcher processes it, updates the store, calls notify() on subscribers, and signals the event loop via eventfd.

timerfd — Periodic Tasks

Timers are file descriptors. The runtime creates a timerfd that fires every 60 seconds for periodic tasks like index compaction and subscriber keepalive.

// wo-event crate
let tfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
timerfd_settime(tfd, 0, &itimerspec { interval: 60s, value: 60s });

Because the timer is an fd, it sits on the same epoll instance as everything else — no separate timer thread needed.

signalfd — Graceful Shutdown

SIGINT and SIGTERM are blocked in the process signal mask and delivered as readable events on a signalfd instead. This means the event loop handles shutdown the same way it handles any other fd event.

// wo-event crate
sigaddset(&mut mask, SIGINT);
sigaddset(&mut mask, SIGTERM);
pthread_sigmask(SIG_BLOCK, &mask, null);
let sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);

When epoll_wait returns the signalfd as readable, the runtime sets running = false and the loop exits cleanly.

pread / pwrite — Positional I/O

The .seg storage files use positional reads and writes. pread reads a record at a specific byte offset without modifying the file descriptor's seek position. pwrite appends new records.

// wo-seg crate
pread(fd, buf, offset);   // read article record at byte offset
pwrite(fd, record, pos);  // append new record

This enables concurrent reads from different offsets in the same file without locking.

fallocate — Pre-allocation

When a new .seg file is created, fallocate pre-allocates 1 MB of disk space. This reduces filesystem fragmentation and prevents write failures mid-operation due to disk pressure.

// wo-seg crate
fallocate(fd, 0, HEADER_SIZE, 1024 * 1024);

socket / bind / listen / accept4 — HTTP Server

The HTTP server uses raw socket syscalls instead of a framework. accept4 with SOCK_NONBLOCK returns non-blocking client fds that register directly on epoll.

// wo-http crate
let fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 1);
bind(fd, addr);
listen(fd, 128);
let client = accept4(fd, SOCK_NONBLOCK | SOCK_CLOEXEC);

Each accepted connection gets a token in the 10000+ range and follows the state machine: ReadingRequest -> WritingResponse -> Done.

sendfile — Zero-Copy Static Serving

Static assets (CSS, images) can be served using sendfile, which transfers bytes directly from the file's page cache to the socket buffer without copying through userspace.

// wo-serve crate
sendfile(socket_fd, file_fd, &mut offset, file_size);

pipe2 — Subscription Testing

Pipe pairs are used in tests to simulate subscriber connections. The write end registers as a subscriber fd; the read end verifies that notifications arrive correctly.

// wo-sub tests
pipe2(fds, O_NONBLOCK);
subscribe(write_fd, ByTitle("article"));
// after notify: read(read_fd) -> notification payload

Summary

| Syscall | Crate | Purpose | |---------|-------|---------| | inotify_init1 / inotify_add_watch | wo-watch | Content directory file change detection | | epoll_create1 / epoll_ctl / epoll_wait | wo-event | Single event loop multiplexing all fds | | eventfd | wo-event, wo-sub | Lightweight signaling between watcher and subscriptions | | timerfd_create / timerfd_settime | wo-event | Periodic tasks as file descriptors | | signalfd | wo-event | SIGINT/SIGTERM as fd events for graceful shutdown | | pread / pwrite | wo-seg | Positional read/write for .seg storage records | | fallocate | wo-seg | Pre-allocate .seg file space | | socket / bind / listen / accept4 | wo-http | Raw TCP HTTP server | | sendfile | wo-serve | Zero-copy static file serving | | pipe2 | wo-sub (tests) | Mock subscriber fd pairs |

No external runtime. No framework. The Linux kernel is the runtime.