5.6.2 Event Records

Events are read from the key fd with read(). A single call returns as many complete events as fit in the caller's buffer; an event is never split across two calls. If the buffer cannot hold even the first queued event, read() fails with EINVAL — the buffer is too small to make progress, and the caller has to try again with a larger one. On an armed fd with an empty queue, read() blocks, or returns EAGAIN under O_NONBLOCK.

Only events that were copied out in full are dequeued.

5.6.2.1 Layout #

Every record begins with the same four fields.

OffsetSizeField
04total_len
42event_type
62name_len
8name_lenname, UTF-8

All integers are little-endian. total_len is the whole record including this header; it is how a consumer advances to the next event, and it is the only safe way to do so.

A subtree watch's records carry additional fields after the name, locating the key the change happened on relative to the watched key:

SizeField
2path_depth
2 + n eachpath_components: len (u16) then that many UTF-8 bytes

path_depth is the number of components from the watched key down to the changed key; zero means the change was on the watched key itself. The components are length-prefixed rather than joined with a separator, because registry names can contain any Unicode character and value names can contain backslashes — a concatenated path string would be ambiguous.

The header offsets are ABI, named in uapi/pkm/lcs.h and listed in §5.A.

5.6.2.2 Not every record on a subtree watch has a path #

OVERFLOW records are emitted in the bare eight-byte form, on every watch, whether or not that watch is a subtree watch. KEY_DELETED is not: a subtree watcher receives it in the subtree form, with a path_depth of its own.

A consumer of a subtree watch therefore cannot assume the subtree fields are present on every record it reads. total_len is the cursor; path_depth is read only when the record is long enough to hold it.

5.6.2.3 Length limits #

name_len and each component length are 16-bit. If an event's name or one of its path components is too long to be represented, LCS does not emit a truncated or malformed record: it substitutes or preserves an OVERFLOW for that watcher instead, which is a statement the consumer already knows how to act on.

5.6.2.4 Forward compatibility #

Future versions may append fields after path_components. An existing consumer skips them, because it advances by total_len; a newer one compares total_len against what it has parsed to discover whether the optional fields are present. This is the whole extension mechanism, and it is why the length field comes first.

Edit this page