#include <sys/types.h>#include <atalk/directory.h>#include <atalk/globals.h>#include <atalk/volume.h>Go to the source code of this file.
Macros | |
| #define | MIN_DIRCACHE_SIZE 1024 |
| #define | MAX_DIRCACHE_SIZE 1048576 |
| #define | DIRCACHE_FREE_QUANTUM 256 |
| #define | DEFERRED_CHAIN_BATCH 16 |
| #define | DIRCACHE (1 << 0) |
| #define | DIDNAME_INDEX (1 << 1) |
| #define | QUEUE_INDEX (1 << 2) |
| #define | DIRCACHE_NOSHRINK (1 << 3) |
| #define | DIRCACHE_ALL (DIRCACHE|DIDNAME_INDEX|QUEUE_INDEX) |
Functions | |
| qnode_t * | arc_ghost_trim_candidate (q_t *q, const struct dir *skip) |
| Pick the ghost to release from a list at capacity. | |
| void | dircache_purge_vol (const struct vol *vol) |
| Release every cache entry belonging to a closing volume. | |
| int | dircache_init (int reqsize) |
| Initialize the dircache and indexes. | |
| int | dircache_add (const struct vol *, struct dir *) |
| create struct dir from struct path | |
| void | dircache_remove (const struct vol *, struct dir *, int flag) |
| Remove an entry from the dircache. | |
| struct dir * | dircache_search_by_did (const struct vol *vol, cnid_t did) |
| Search the dircache via a CNID for a directory. | |
| struct dir * | dircache_lookup_parent (const struct vol *vol, cnid_t did) |
| Plain index probe for pfd_cache parent resolution. | |
| struct dir * | dircache_search_by_name (const struct vol *, const struct dir *dir, char *name, size_t len) |
| Search the cache via did/name hashtable. | |
| void | dircache_dump (void) |
| Dump dircache to /tmp/dircache.PID. | |
| void | log_dircache_stat (void) |
| Log dircache statistics. | |
| unsigned int | dircache_resolve_size (int reqsize) |
| Resolve a requested dircache size to the effective maximum. | |
| void | dircache_reset_validation_counter (void) |
| Reset validation counter for consistent testing. | |
| void | dircache_report_invalid_entry (struct dir *dir) |
| Report that a cache entry was invalid when actually used. | |
| int | dircache_remove_children (const struct vol *vol, struct dir *dir) |
| Remove all child entries of a directory from the dircache. | |
| int | dircache_reindex_didname (const struct vol *vol, struct dir *dir) |
| Re-insert entry into DID/name index after key change. | |
| void | dircache_promote (struct dir *dir) |
| Promote a cache entry to signal recency. | |
| void | process_cache_hints (AFPObj *obj) |
| Process cross-process dircache invalidation hints. | |
| void | dircache_remove_children_defer (const struct vol *vol, struct dir *dir) |
| Enqueue a deferred dircache_remove_children operation. | |
| void | dircache_flush_deferred_for_vol (uint16_t vid) |
| Process deferred cleanup entries for a closing volume synchronously. | |
| int | dircache_has_deferred_work (void) |
| int | dircache_process_deferred_chain (void) |
| Process one unit of deferred cleanup. | |
| void | dircache_rfork_shutdown (void) |
| Shutdown the rfork cache — free remaining RFork LRU nodes and sentinel. | |
Variables | |
| size_t | rfork_cache_used |
| size_t | rfork_cache_budget |
| size_t | rfork_max_entry_size |
| unsigned int | rfork_lru_count |
| q_t * | rfork_lru |
| unsigned long long | rfork_stat_lookups |
| unsigned long long | rfork_stat_hits |
| unsigned long long | rfork_stat_misses |
| unsigned long long | rfork_stat_added |
| unsigned long long | rfork_stat_evicted |
| unsigned long long | rfork_stat_invalidated |
| size_t | rfork_stat_used_max |
| #define DEFERRED_CHAIN_BATCH 16 |
| #define DIDNAME_INDEX (1 << 1) |
| #define DIRCACHE (1 << 0) |
| #define DIRCACHE_ALL (DIRCACHE|DIDNAME_INDEX|QUEUE_INDEX) |
| #define DIRCACHE_FREE_QUANTUM 256 |
| #define DIRCACHE_NOSHRINK (1 << 3) |
| #define MAX_DIRCACHE_SIZE 1048576 |
| #define MIN_DIRCACHE_SIZE 1024 |
| #define QUEUE_INDEX (1 << 2) |
Pick the ghost to release from a list at capacity.
Non-static so the unit tests can drive selection directly
LRU first, skipping the excluded entry; a single-node list is both MRU and LRU, so MRU ordering alone cannot exclude it.
| [in] | q | Ghost queue (B1 or B2) |
| [in] | skip | Entry that must not be selected (ghost mid-promotion), or NULL |
create struct dir from struct path
Add a struct dir to the cache and its indexes. Supports both LRU mode (legacy) and ARC mode.
| [in] | vol | pointer to volume |
| [in] | dir | pointer to parent directory |
|
extern |
Dump dircache to /tmp/dircache.PID.
|
extern |
Process deferred cleanup entries for a closing volume synchronously.
|
extern |
|
extern |
Initialize the dircache and indexes.
This is called in child afpd initialization. Unset or below-minimum sizes use DEFAULT_DIRCACHE_SIZE, in-range sizes round up to the next power of two, oversize requests clamp to MAX_DIRCACHE_SIZE. It initializes a hashtable which we use to store a directory cache in. It also initializes two indexes:
| [in] | reqsize | requested maximum size from afp.conf |
Plain index probe for pfd_cache parent resolution.
Never validates, never mutates, never promotes. Filters ARC ghosts (their identity fields are frozen and unvalidated — treating one as a live parent would let the pfd sync-check pass against stale identity) and file entries (a parent must be a directory).
|
extern |
Process one unit of deferred cleanup.
Called by idle worker under a validated grant. Jobs are consumed LIFO: AFP deletes bottom-up, so a tree's covering root-most job arrives last and its single scan purges the whole subtree; the covering memo then drops the tree's remaining jobs in O(1) as they pop. When every pending job sits at one depth, one merged batch scan serves all of them. Every removal re-checks iw_can_work; scans resume via their chain cursors across granted cycles.
|
extern |
Promote a cache entry to signal recency.
Dispatches based on cache mode:
ARC mode (arc_list membership): T1/T2: arc_case_i() — move to MRU of T2 B1: arc_case_ii_adapt_and_replace() — promote ghost to T2 B2: arc_case_iii_adapt_and_replace() — promote ghost to T2
LRU mode: Move entry to MRU position of the LRU queue, so recently accessed entries are evicted last. Prevents actively-used entries from being evicted.
| [in,out] | dir | Cache entry to promote (required) |
|
extern |
Release every cache entry belonging to a closing volume.
Nothing else reclaims by volume, so entries left behind are found as valid when the vid is reused. DIRCACHE_NOSHRINK keeps the scan valid: each entry deletes only its own just-returned node and the table never rehashes mid-scan.
Nothing is exempt: closevol() frees v_root next, so an entry kept back would outlive its volume under a reusable vid. A curdir still inside the volume is dropped to rootParent rather than left cached.
| [in] | vol | Volume being closed (required) |
Re-insert entry into DID/name index after key change.
Called by dir_modify() after updating d_pdid / d_u_name. The caller MUST have already removed the entry from the DIDNAME_INDEX via dircache_remove(vol, dir, DIDNAME_INDEX) before calling this.
| [in] | vol | Volume (required) |
| [in] | dir | Entry with updated d_pdid / d_u_name (required) |
Remove an entry from the dircache.
Deletes the entry's own stored nodes, so removal can never cost another entry its node. A NULL node means the entry is not in that index and it is skipped; a node naming a different entry panics before anything is mutated or followed.
Callers outside of dircache.c should call this with flags = QUEUE_INDEX | DIDNAME_INDEX | DIRCACHE.
Remove all child entries of a directory from the dircache.
When a directory is renamed or moved, the full paths stored in the dircache become invalid for all child entries of the renamed dir. This function prunes orphaned child dircache entries of given dir. CNID entries use parent DIDs and name, and requre recursion to get the full path, therefore parent changes do not invalidate the CNIDs.
Removes as it scans: DIRCACHE_NOSHRINK deletes the entry's own just-returned node without rehashing the table, and the free is deferred, so nothing the scan is walking moves. dir_remove() cannot be used here — its curdir recovery calls dirlookup(), and an insert mid-scan can grow the table. A removed curdir is re-resolved once the scan is over instead: a rename keeps the CNID, so the lookup rebuilds the entry on the new path.
| [in] | vol | volume |
| [in] | dir | parent directory whose children should be removed |
Enqueue a deferred dircache_remove_children operation.
O(1) enqueue — the idle worker performs the actual hash scan during poll() idle periods. Falls back to synchronous removal if the worker is not active or the queue is full.
|
extern |
Report that a cache entry was invalid when actually used.
This function should be called when a cached directory entry that was returned without validation (for performance) turns out to be invalid when actually accessed (e.g., file doesn't exist, has been modified, etc). This helps track the effectiveness of the validation frequency setting.
| [in] | dir | The directory entry that was found to be invalid |
|
extern |
Reset validation counter for consistent testing.
Resets the global validation counter to ensure predictable validation patterns between test runs or configuration changes.
|
extern |
Resolve a requested dircache size to the effective maximum.
Unset or below-minimum sizes use DEFAULT_DIRCACHE_SIZE, in-range sizes round up to the next power of two, oversize requests clamp to MAX_DIRCACHE_SIZE.
| [in] | reqsize | requested maximum size from afp.conf |
|
extern |
Shutdown the rfork cache — free remaining RFork LRU nodes and sentinel.
Called from the child shutdown path after log_dircache_stat(). Frees the qnodes (rfork data buffers are reclaimed by exit()) and the LRU sentinel.
Search the dircache via a CNID for a directory.
Found cache entries are expunged if both the parent directory st_ctime and the objects st_ctime are modified. This func builds on the fact, that all our code only ever needs to and does search the dircache by CNID expecting directories to be returned, but not files. Thus (1) if we find a file for a given CNID we (1a) remove it from the cache (1b) return NULL indicating nothing found (2) we can then use d_fullpath to stat the directory
| [in] | vol | pointer to struct vol |
| [in] | cnid | CNID of the directory to search |
|
extern |
Search the cache via did/name hashtable.
Found cache entries are expunged if both the parent directory st_ctime and the objects st_ctime are modified.
| [in] | vol | volume |
| [in] | dir | directory |
| [in] | name | name (server side encoding) |
| [in] | len | strlen of name |
|
extern |
Log dircache statistics.
Includes hit ratio percentage for monitoring cache effectiveness, validation-specific metrics to monitor performance impact of the optimization changes, and username for tracking per-user stats. Shows both expunged (caught by validation) and invalid_on_use (missed by validation).
|
extern |
Process cross-process dircache invalidation hints.
Called from the DSI command loop after each AFP command completes. Uses direct hash_lookup() on the CNID hash table to support BOTH files (DIRF_ISFILE) and directories — dircache_search_by_did() is unsuitable because it actively removes file entries.
Dispatches on hint type:
|
extern |
|
extern |
|
extern |
|
extern |
|
extern |
|
extern |
|
extern |
|
extern |
|
extern |
|
extern |
|
extern |
|
extern |