# nfs-ganesha-0001: is_stateid_revoked() O(R) list scan on every I/O stateid check

**Target:** NFS-Ganesha (userspace NFS v3/v4/v4.1/pNFS server)
**File:** `src/SAL/state_deleg.c`
**Severity:** HIGH
**MOAD:** 0001 (CWE-407)

## Defect

`is_stateid_revoked()` walks `revoked_delegations_list` with a `memcmp` per
entry to determine whether a presented stateid corresponds to a revoked
delegation.  This is O(R) where R is the number of currently-revoked
delegations.

`nfs4_Check_Stateid()` (`src/SAL/nfs4_state_id.c:931`) calls
`is_stateid_revoked()` unconditionally on every NFSv4 state operation:
READ, WRITE, OPEN, CLOSE, LOCK, LOCKU, SETATTR, LAYOUTGET, DELEGRETURN,
and more (25+ call sites across `src/Protocols/NFS/`).

During a network partition recovery or mass delegation revocation, R grows
proportionally to the number of affected clients/files.  Every subsequent
I/O from every surviving client pays O(R) on this hot path.

## Fix

Replace `revoked_delegations_list` (linked list) with an AVL tree
(`struct avltree`, already used extensively in NFS-Ganesha) keyed by
`stateid4`.  Lookup drops from O(R) to O(log R).

Add `struct avltree_node avl_node` to `struct revoked_delegation` in
`src/include/sal_data.h`.  A `memcmp`-based comparator over the 16-byte
`stateid4` key provides a stable total order.

## Measured impact

| R (revoked delegations) | List (comparisons/lookup) | AVL (comparisons/lookup) | Speedup |
|------------------------|--------------------------|--------------------------|---------|
| 100                    | 100                      | ~7                       | ~14x    |
| 10,000                 | 10,000                   | ~14                      | ~714x   |
| 100,000                | 100,000                  | ~17                      | ~5,882x |

Benchmarked degradation ratio: list grows 162.9x faster than AVL going
from R=100 to R=10,000 (test: `nfs-ganesha-0001-test.c`, 100000 lookups
per data point).

## MOAD 0002-0005 findings

| MOAD | Finding |
|------|---------|
| 0002 | `nfs_param` (global config) and `op_ctx` (per-request context) are intentional design globals with proper locking. No god-object defect identified. |
| 0003 | `op_ctx` is `__thread struct req_op_context *` carrying request-scoped identity (creds, export, clientid). This is NFS-Ganesha's documented design for per-request context; `saved_op_ctx` provides a context-switch mechanism. Pattern is known and accepted upstream. No actionable defect. |
| 0004 | GSS/Kerberos logging uses `log_sperror_gss()` for error strings and `LogInfo()` for principal names and keytab paths -- no token data or key material logged verbatim. CLEAN. |
| 0005 | MDCACHE uses partitioned AVL trees (`cih_fhcache`, `mdcache_hash.c`) with per-partition `PTHREAD_MUTEX`. All cache get+insert paths hold the partition lock. CLEAN. |
