[InterNetNews/inn] 5e63cd: nnrpd: fast-path nnrpdcheckart via cancels.tombstone

Kevin Bowling noreply at github.com
Sun May 24 14:54:05 UTC 2026


  Branch: refs/heads/main
  Home:   https://github.com/InterNetNews/inn
  Commit: 5e63cd6783d217ac4ed192333deaa7c0caa96860
      https://github.com/InterNetNews/inn/commit/5e63cd6783d217ac4ed192333deaa7c0caa96860
  Author: Kevin Bowling <kevin.bowling at kev009.com>
  Date:   2026-05-24 (Sun, 24 May 2026)

  Changed paths:
    M doc/pod/inn.conf.pod
    M nnrpd/article.c

  Log Message:
  -----------
  nnrpd: fast-path nnrpdcheckart via cancels.tombstone

When both innconf->expiretombstone and PERMaccessconf->nnrpdcheckart
are true, ARTinstorebytoken now consults ${pathdb}/cancels.tombstone
before calling SMretrieve(RETR_STAT).  A token recorded in the log is
reported gone without a syscall; a token absent from the log is
trusted to still exist on storage methods that do not self-expire,
again without a syscall.  Self-expiring backends (CNFS) still go
through SMretrieve because cyclic-buffer wrap-around bypasses the
tombstone.

The same trade-off as the expire-side fast path applies: the
tombstone catches in-band cancellations (innd ARTcancel, sm -r) but
not out-of-band events (manual filesystem deletes, corruption).
Admins running nnrpdcheckart=true to catch the brief overview-vs-
storage race during innd cancel processing, or to catch sm -r
artifacts before the next expireover cleans overview, still get those
paths.  Loss is bounded to events the tombstone subsystem cannot
see, which is consistent with the contract documented for
expiretombstone.

Loading is lazy: the hashset is built on first call into
ARTinstorebytoken and the file is stat()ed on every subsequent call
to detect change, with reload only when mtime or size changes.
Statting a fixed path stays in the dentry cache and is trivially
cheap compared to the per-article SMretrieve syscalls the fast path
elides, so cancellations recorded by other processes become visible
to long-lived connections immediately.  Freshness is keyed on both
mtime and size: mtime alone has 1-second granularity, so a rename-
and-recreate within the same second can land a fresh inode with
the cached mtime; size is monotonic-append between rotations and
catches every modification.  Partial reads (mid-file ferror) leave
the cached freshness key untouched so the next call retries.

The SMprobe(SELFEXPIRE) probe is checked before the tombstone
refresh so pure-CNFS sites pay only that probe (a static per-method
attribute, no I/O) and skip both the hash lookup and the cache load
entirely.

Memory cost is dominated by the hashset (~50 bytes per cancel;
typical sites have hundreds of entries).  When the file is missing
entirely, expiretombstone is off, or nnrpdcheckart is off, the
original SMretrieve path is unchanged.

inn.conf.pod's nnrpdcheckart entry now describes the fast-path
gating, the mtime/size-driven reload model, the manual-rm caveat
on non-self-expiring backends, and the OVERartcheck counter
becoming an undercount when the fast path is active.

see #340



To unsubscribe from these emails, change your notification settings at https://github.com/InterNetNews/inn/settings/notifications


More information about the inn-committers mailing list