netatalk  4.5.0
Free and Open Source Apple Filing Protocol (AFP) Server
Loading...
Searching...
No Matches
dircache.c File Reference

Directory Cache. More...

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <bstrlib.h>
#include <atalk/cnid.h>
#include <atalk/directory.h>
#include <atalk/globals.h>
#include <atalk/logger.h>
#include <atalk/netatalk_conf.h>
#include <atalk/queue.h>
#include <atalk/server_ipc.h>
#include <atalk/util.h>
#include <atalk/volume.h>
#include "ad_cache.h"
#include "dircache.h"
#include "directory.h"
#include "hash.h"
#include "idle_worker.h"

Data Structures

struct  deferred_cleanup
struct  dircache_stat

Macros

#define MAX_DEFERRED_CLEANUPS   5120
#define get16bits(d)
#define MAX_HINTS_PER_CYCLE   32
#define HINT_READ_BUF_SIZE

Enumerations

enum  arc_list_t {
  ARC_NONE = 0 , ARC_T1 , ARC_T2 , ARC_B1 ,
  ARC_B2
}

Functions

static hnode_thash_chain_head (hash_t *hash, hashcount_t chain)
static hash_val_t hash_vid_did (const void *key)
static int hash_comp_vid_did (const void *key1, const void *key2)
static int arc_init (size_t cache_size)
 Initialize ARC cache structures.
static void arc_destroy (void)
 Destroy ARC cache structures.
static void arc_verify_invariants (void)
 Verify ARC invariants (debug mode).
static void arc_ensure_ghost_capacity (arc_list_t target_list)
 Ensure ghost directory has room for one more entry.
static struct dirarc_find_victim (q_t *queue, size_t queue_size)
 Find an evictable victim in a cache queue, skipping curdir.
static void arc_evict_to_ghost (struct dir *victim, q_t *src, q_t *dst, int dst_list, bool fallback)
 Evict a victim from a cache queue to the corresponding ghost list.
static int arc_replace (int in_b2)
 ARC REPLACE subroutine (from paper Figure 1).
static void arc_case_i (struct dir *dir)
 ARC Case I: Cache hit in T1 or T2.
static void arc_case_ii_adapt_and_replace (struct dir *ghost)
 ARC Case II: Ghost hit in B1.
static void arc_case_iii_adapt_and_replace (struct dir *ghost)
 ARC Case III: Ghost hit in B2.
static void arc_case_iv (struct dir *dir)
 ARC Case IV: Complete miss (not in any list).
static hash_val_t hash_didname (const void *p)
static int hash_comp_didname (const void *k1, const void *k2)
static int should_validate_cache_entry (void)
 Determine if cache entry should be validated against filesystem.
static void dircache_evict (void)
 Remove a fixed number of (oldest) entries from the cache and indexes.
struct dirdircache_search_by_did (const struct vol *vol, cnid_t cnid)
 Search the dircache via a CNID for a directory.
struct dirdircache_search_by_name (const struct vol *vol, const struct dir *dir, char *name, size_t len)
 Search the cache via did/name hashtable.
int dircache_add (const struct vol *vol, struct dir *dir)
 create struct dir from struct path
void dircache_remove (const struct vol *vol, struct dir *dir, int flags)
 Remove an entry from the dircache.
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.
int dircache_init (int reqsize)
 Initialize the dircache and indexes.
void log_dircache_stat (void)
 Log dircache statistics.
void dircache_rfork_shutdown (void)
 Shutdown the rfork cache — free remaining RFork LRU nodes and sentinel.
void dircache_dump (void)
 Dump dircache to /tmp/dircache.PID.
int dircache_set_validation_params (unsigned int freq)
 Set directory cache validation frequency.
void dircache_reset_validation_counter (void)
 Reset validation counter for consistent testing.
void process_cache_hints (AFPObj *obj)
 Process cross-process dircache invalidation hints.
void dircache_report_invalid_entry (struct dir *dir)
 Report that a cache entry was invalid when actually used.
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 hash chain from the current deferred cleanup job.

Variables

static hash_tdircache
static unsigned int dircache_maxsize
static struct deferred_cleanup deferred_queue [MAX_DEFERRED_CLEANUPS]
static int deferred_head = 0
static int deferred_tail = 0
static int deferred_count = 0
static unsigned long queue_count_max = 0
static unsigned int dircache_validation_freq = DEFAULT_DIRCACHE_VALIDATION_FREQ
static volatile uint64_t validation_counter = 0
static struct dircache_stat dircache_stat
unsigned long long rfork_stat_lookups = 0
unsigned long long rfork_stat_hits = 0
unsigned long long rfork_stat_misses = 0
unsigned long long rfork_stat_added = 0
unsigned long long rfork_stat_evicted = 0
unsigned long long rfork_stat_invalidated = 0
size_t rfork_stat_used_max = 0
size_t rfork_cache_used = 0
size_t rfork_cache_budget = 0
size_t rfork_max_entry_size = 0
unsigned int rfork_lru_count = 0
q_trfork_lru = NULL
struct { 
   unsigned long long   hints_received 
   unsigned long long   hints_acted_on 
   unsigned long long   hints_no_match 
cache_hint_stat
struct { 
   int   enabled 
   q_t *   t1 
   q_t *   t2 
   q_t *   b1 
   q_t *   b2 
   size_t   t1_size 
   size_t   t2_size 
   size_t   b1_size 
   size_t   b2_size 
   size_t   p 
   size_t   c 
   struct { 
      uint64_t   hits_t1 
      uint64_t   hits_t2 
      uint64_t   ghost_hits_b1 
      uint64_t   ghost_hits_b2 
      uint64_t   adaptations 
      uint64_t   evictions_t1 
      uint64_t   evictions_t2 
      uint64_t   promotions_t1_to_t2 
      size_t   p_min 
      size_t   p_max 
      uint64_t   p_increases 
      uint64_t   p_decreases 
   }   stats
arc_cache
static hash_tindex_didname
static q_tindex_queue
static unsigned long queue_count

Detailed Description

Directory Cache.

Cache files and directories in a LRU cache.

The directory cache caches directories and files(!). The main reason for having the cache is avoiding recursive walks up the path, querying the CNID database each time, when we have to calculate the location of e.g. directory with CNID 30, which is located in a dir with CNID 25, next CNID 20 and then CNID 2 (the volume root as per AFP spec). If all these dirs where in the cache, each database look up can be avoided. Additionally there's the element "fullpath" in struct dir, which is used to avoid the recursion in any case. Wheneveer a struct dir is initialized, the fullpath to the directory is stored there.

In order to speed up the CNID query for files too, which e.g. happens when a directory is enumerated, files are stored too in the dircache. In order to differentiate between files and dirs, we set the flag DIRF_ISFILE in struct dir.d_flags for files.

The most frequent codepatch that leads to caching is directory enumeration (cf enumerate.c):

  • if a element is a directory:
    1. the cache is searched by dircache_search_by_name()
    2. if it wasn't found a new struct dir is created and cached both from within dir_add()
  • for files the caching happens a little bit down the call chain:
    1. first getfilparams() is called, which calls
    2. getmetadata() where the cache is searched with dircache_search_by_name()
    3. if the element is not found
    4. get_id() queries the CNID from the database
    5. then a struct dir is initialized via dir_new() (note the fullpath arg is NULL)
    6. finally added to the cache with dircache_add() (2) of course does contain the steps 6,7 and 8.

The dircache is a LRU cache, whenever it fills up we call dircache_evict internally which removes DIRCACHE_FREE_QUANTUM elements from the cache.

There is only one cache for all volumes, so of course we use the volume id in hashing calculations.

In order to avoid cache poisoning, we store the cached entries st_ctime from stat in struct dir.ctime_dircache. Later when we search the cache we compare the stored value with the result of a fresh stat. If the times differ, we remove the cached entry and return "no entry found in cache". A elements ctime changes when

  1. the element is renamed (we lose the cached entry here, but it will expire when the cache fills)
  2. its a directory and an object has been created therein
  3. the element is deleted and recreated under the same name Using ctime leads to cache eviction in case 2) where it wouldn't be necessary, because the dir itself (name, CNID, ...) hasn't changed, but there's no other way.

Indexes

The maximum dircache size is: max(DEFAULT_DIRCACHE_SIZE, min(size, MAX_DIRCACHE_SIZE)). It is a hashtable which we use to store "struct dir"s in. If the cache get full, oldest entries are evicted in chunks of DIRCACHE_FREE.

We have/need two indexes:

  • a DID/name index on the main dircache, another hashtable
  • a queue index on the dircache, for evicting the oldest entries

Debugging

Sending SIGINT to a afpd child causes it to dump the dircache to a file "/tmp/dircache.PID".

Macro Definition Documentation

◆ get16bits

#define get16bits ( d)
Value:
((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
+(uint32_t)(((const uint8_t *)(d))[0]) )

◆ HINT_READ_BUF_SIZE

#define HINT_READ_BUF_SIZE
Value:
#define MAX_HINTS_PER_CYCLE
Definition dircache.c:2505
#define IPC_HEADERLEN
Definition server_ipc.h:12
Definition server_ipc.h:31

◆ MAX_DEFERRED_CLEANUPS

#define MAX_DEFERRED_CLEANUPS   5120

◆ MAX_HINTS_PER_CYCLE

#define MAX_HINTS_PER_CYCLE   32

Enumeration Type Documentation

◆ arc_list_t

enum arc_list_t

ARC list location for cache entries

Enumerator
ARC_NONE 

Not in any ARC list (matches calloc() zero init)

ARC_T1 

Recent entries

ARC_T2 

Frequent entries

ARC_B1 

Ghost entries evicted from T1

ARC_B2 

Ghost entries evicted from T2

Function Documentation

◆ arc_case_i()

void arc_case_i ( struct dir * dir)
static

ARC Case I: Cache hit in T1 or T2.

From paper: "Move x to MRU of T2"

Promotes entry from T1 to T2 (frequency list) on second+ access, or moves within T2 if already frequent.

Parameters
[in]dirDirectory entry in T1 or T2

◆ arc_case_ii_adapt_and_replace()

void arc_case_ii_adapt_and_replace ( struct dir * ghost)
static

ARC Case II: Ghost hit in B1.

From paper: "Adapt p = min(c, p + max(|B2|/|B1|, 1)) REPLACE(p) Move x to MRU of T2, load into cache"

B1 hit indicates we evicted this entry too soon from T1. Increase p to favor recency (grow T1 target size).

Ghost entries in this implementation are full struct dir with DIRF_ARC_GHOST flag. This function adapts p, calls REPLACE, and promotes ghost from B1 to T2 inline using queue_move_to_tail_of() for zero-allocation transition.

Parameters
[in]ghostGhost entry (struct dir with DIRF_ARC_GHOST) in B1

◆ arc_case_iii_adapt_and_replace()

void arc_case_iii_adapt_and_replace ( struct dir * ghost)
static

ARC Case III: Ghost hit in B2.

From paper: "Adapt p = max(0, p - max(|B1|/|B2|, 1)) REPLACE(p) Move x to MRU of T2, load into cache"

B2 hit indicates we evicted this entry too soon from T2. Decrease p to favor frequency (grow T2 target size).

Ghost entries in this implementation are full struct dir with DIRF_ARC_GHOST flag. This function adapts p, calls REPLACE, and promotes ghost from B2 to T2 inline using queue_move_to_tail_of() for zero-allocation transition.

Parameters
[in]ghostGhost entry (struct dir with DIRF_ARC_GHOST) in B2

◆ arc_case_iv()

void arc_case_iv ( struct dir * dir)
static

ARC Case IV: Complete miss (not in any list).

From paper: "case (i): |L1| = c if |T1| < c then delete LRU of B1, REPLACE(p) else delete LRU of T1, remove from cache case (ii): |L1| < c and |L1| + |L2| ≥ c if |L1| + |L2| = 2c then delete LRU of B2 REPLACE(p) Put x at MRU of T1, load into cache"

Adds new entry to T1 (recency list).

Parameters
[in]dirNew directory entry to insert

◆ arc_destroy()

void arc_destroy ( void )
static

Destroy ARC cache structures.

◆ arc_ensure_ghost_capacity()

void arc_ensure_ghost_capacity ( arc_list_t target_list)
static

Ensure ghost directory has room for one more entry.

Maintains the ARC invariant: B1 + B2 ≤ c

Called before operations that will add a ghost entry to B1 or B2. If ghost directory is at or over capacity, deletes the LRU ghost from the specified target list to make room.

This handles the edge case where entries are removed from the cache via dircache_remove() (bypassing ghost lists), causing the ghost directory to stay at capacity while the cache shrinks.

Parameters
[in]target_listWhich ghost list will receive new entry (ARC_B1 or ARC_B2)

◆ arc_evict_to_ghost()

void arc_evict_to_ghost ( struct dir * victim,
q_t * src,
q_t * dst,
int dst_list,
bool fallback )
static

Evict a victim from a cache queue to the corresponding ghost list.

Moves victim's queue node from src to dst, sets ghost flag, and updates all ARC size counters and stats.

Parameters
[in]victimDirectory entry to evict (must have valid qidx_node)
[in]srcSource cache queue (T1 or T2)
[in]dstDestination ghost queue (B1 or B2)
[in]dst_listARC_B1 or ARC_B2 (determines which counters to update)
[in]fallbacktrue if this is a cross-queue fallback eviction (for logging)

◆ arc_find_victim()

struct dir * arc_find_victim ( q_t * queue,
size_t queue_size )
static

Find an evictable victim in a cache queue, skipping curdir.

Only searches T1 and T2 (the real cache queues). B1/B2 are ghost lists with full data.

Tries the LRU entry first; if it's curdir, tries the second-LRU.

Parameters
[in]queueThe ARC queue to search (T1 or T2)
[in]queue_sizeNumber of entries in the queue
Returns
evictable dir entry, or NULL if queue is empty/only contains curdir

◆ arc_init()

int arc_init ( size_t cache_size)
static

Initialize ARC cache structures.

Parameters
[in]cache_sizeTotal cache size (c)
Returns
0 on success, -1 on error

◆ arc_replace()

int arc_replace ( int in_b2)
static

ARC REPLACE subroutine (from paper Figure 1).

Evicts one entry from T1 or T2 and moves it to the corresponding ghost list (B1 or B2). Decision based on:

  • Current size of T1 relative to target p
  • Whether the incoming request is in B2

If the preferred queue only contains curdir (which must never be evicted), falls back to the other queue. Returns -1 only when both queues are exhausted, allowing the caller to proceed with a temporarily over-capacity cache that self-heals on the next eviction cycle.

From paper: "if |T1| ≥ 1 and ((x ∈ B2 and |T1| = p) or |T1| > p): Move LRU of T1 to MRU of B1, remove from cache else: Move LRU of T2 to MRU of B2, remove from cache"

Parameters
[in]in_b21 if incoming request is in B2, 0 otherwise
Returns
0 on successful eviction, -1 if no entry could be evicted

◆ arc_verify_invariants()

void arc_verify_invariants ( void )
static

Verify ARC invariants (debug mode).

Checks that ARC list sizes satisfy all constraints from the paper. Called after each operation in debug builds.

◆ dircache_add()

int dircache_add ( const struct vol * vol,
struct dir * dir )

create struct dir from struct path

Add a struct dir to the cache and its indexes. Supports both LRU mode (legacy) and ARC mode.

Parameters
[in]volpointer to volume
[in]dirpointer to parent directory
Returns
0 on success, -1 on error which should result in an abort

◆ dircache_dump()

void dircache_dump ( void )

Dump dircache to /tmp/dircache.PID.

◆ dircache_evict()

void dircache_evict ( void )
static

Remove a fixed number of (oldest) entries from the cache and indexes.

The default is to remove the 256 oldest entries from the cache.

  1. Get the oldest entry
  2. If it's in use i.e. open forks reference it or it's curdir requeue it, don't remove it
  3. Remove the dir from the main cache and the didname index
  4. Free the struct dir structure and all its members

◆ dircache_flush_deferred_for_vol()

void dircache_flush_deferred_for_vol ( uint16_t vid)

Process deferred cleanup entries for a closing volume synchronously.

Precondition
: Worker is dormant (called during AFP command processing). Called from afp_closevol() before volume structures are freed.

◆ dircache_has_deferred_work()

int dircache_has_deferred_work ( void )

◆ dircache_init()

int dircache_init ( int reqsize)

Initialize the dircache and indexes.

This is called in child afpd initialization. The maximum cache size will be max(DEFAULT_DIRCACHE_SIZE, min(size, MAX_DIRCACHE_SIZE)). It initializes a hashtable which we use to store a directory cache in. It also initializes two indexes:

  • a DID/name index on the main dircache
  • a queue index on the dircache (LRU mode) or four queues (ARC mode)
Parameters
[in]reqsizerequested maximum size from afp.conf
Returns
0 on success, -1 on error

◆ dircache_process_deferred_chain()

int dircache_process_deferred_chain ( void )

Process one hash chain from the current deferred cleanup job.

Called by idle worker. Walks a single hash chain, collects up to DEFERRED_CHAIN_BATCH matching children, and removes+frees them via dir_remove_and_free(). Entries matching curdir are skipped.

Returns
1 if more work remains, 0 if all deferred work is complete

◆ dircache_promote()

void dircache_promote ( struct dir * dir)

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.

Parameters
[in,out]dirCache entry to promote (required)

◆ dircache_reindex_didname()

int dircache_reindex_didname ( const struct vol * vol,
struct dir * dir )

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.

Parameters
[in]volVolume (required)
[in]dirEntry with updated d_pdid / d_u_name (required)
Returns
0 on success, -1 on hash insert failure

◆ dircache_remove()

void dircache_remove ( const struct vol * vol,
struct dir * dir,
int flags )

Remove an entry from the dircache.

Callers outside of dircache.c should call this with flags = QUEUE_INDEX | DIDNAME_INDEX | DIRCACHE.

◆ dircache_remove_children()

int dircache_remove_children ( const struct vol * vol,
struct dir * dir )

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.

Parameters
[in]volvolume
[in]dirparent directory whose children should be removed
Returns
0 on success, -1 if curdir was removed and recovery failed

◆ dircache_remove_children_defer()

void dircache_remove_children_defer ( const struct vol * vol,
struct dir * dir )

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.

◆ dircache_report_invalid_entry()

void dircache_report_invalid_entry ( struct dir * dir)

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.

Parameters
[in]dirThe directory entry that was found to be invalid

◆ dircache_reset_validation_counter()

void dircache_reset_validation_counter ( void )

Reset validation counter for consistent testing.

Resets the global validation counter to ensure predictable validation patterns between test runs or configuration changes.

◆ dircache_rfork_shutdown()

void dircache_rfork_shutdown ( void )

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.

◆ dircache_search_by_did()

struct dir * dircache_search_by_did ( const struct vol * vol,
cnid_t cnid )

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

Parameters
[in]volpointer to struct vol
[in]cnidCNID of the directory to search
Returns
Pointer to struct dir if found, else NULL

◆ dircache_search_by_name()

struct dir * dircache_search_by_name ( const struct vol * vol,
const struct dir * dir,
char * name,
size_t len )

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.

Parameters
[in]volvolume
[in]dirdirectory
[in]namename (server side encoding)
[in]lenstrlen of name
Returns
pointer to struct dir if found in cache, else NULL

◆ dircache_set_validation_params()

int dircache_set_validation_params ( unsigned int freq)

Set directory cache validation frequency.

Allows runtime configuration of cache validation behavior for performance tuning. Lower validation frequency improves performance but may delay detection of external filesystem changes.

Parameters
[in]freqvalidation frequency (1 = validate every access, 100 = every 100th access)
Returns
0 on success, -1 on invalid parameters

◆ hash_chain_head()

hnode_t * hash_chain_head ( hash_t * hash,
hashcount_t chain )
inlinestatic

◆ hash_comp_didname()

int hash_comp_didname ( const void * k1,
const void * k2 )
inlinestatic

◆ hash_comp_vid_did()

int hash_comp_vid_did ( const void * key1,
const void * key2 )
inlinestatic

◆ hash_didname()

hash_val_t hash_didname ( const void * p)
inlinestatic

◆ hash_vid_did()

hash_val_t hash_vid_did ( const void * key)
inlinestatic

◆ log_dircache_stat()

void log_dircache_stat ( void )

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).

◆ process_cache_hints()

void process_cache_hints ( AFPObj * obj)

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:

◆ should_validate_cache_entry()

int should_validate_cache_entry ( void )
static

Determine if cache entry should be validated against filesystem.

Uses probabilistic validation to reduce filesystem calls while still detecting external changes. Internal netatalk operations use explicit cache invalidation via dir_remove() calls, so frequent validation is only needed to detect external filesystem changes.

Returns
1 if validation should be performed, 0 otherwise

Variable Documentation

◆ adaptations

uint64_t adaptations

Number of p adjustments

◆ [struct]

struct { ... } arc_cache
Initial value:
= {
.enabled = 0,
.t1 = NULL, .t2 = NULL, .b1 = NULL, .b2 = NULL,
.t1_size = 0, .t2_size = 0, .b1_size = 0, .b2_size = 0,
.p = 0, .c = 0,
.stats = {0}
}
#define NULL
Definition utf8util.c:47

ARC cache state

◆ b1

q_t* b1

Ghost entries from T1 (full struct dir with DIRF_ARC_GHOST)

◆ b1_size

size_t b1_size

◆ b2

q_t* b2

Ghost entries from T2 (full struct dir with DIRF_ARC_GHOST)

◆ b2_size

size_t b2_size

◆ c

size_t c

Total cache size

◆ [struct]

struct { ... } cache_hint_stat

Cache hint processing statistics — logged by log_dircache_stat()

◆ deferred_count

int deferred_count = 0
static

◆ deferred_head

int deferred_head = 0
static

◆ deferred_queue

struct deferred_cleanup deferred_queue[MAX_DEFERRED_CLEANUPS]
static

◆ deferred_tail

int deferred_tail = 0
static

◆ dircache

hash_t* dircache
static

◆ dircache_maxsize

unsigned int dircache_maxsize
static

◆ dircache_stat

struct dircache_stat dircache_stat
static

◆ dircache_validation_freq

unsigned int dircache_validation_freq = DEFAULT_DIRCACHE_VALIDATION_FREQ
static

◆ enabled

int enabled

0 = LRU mode, 1 = ARC mode

◆ evictions_t1

uint64_t evictions_t1

Evictions from T1

◆ evictions_t2

uint64_t evictions_t2

Evictions from T2

◆ ghost_hits_b1

uint64_t ghost_hits_b1

Ghost hits in B1

◆ ghost_hits_b2

uint64_t ghost_hits_b2

Ghost hits in B2

◆ hints_acted_on

unsigned long long hints_acted_on

Hints that matched a local cache entry

◆ hints_no_match

unsigned long long hints_no_match

Hints for entries not in local cache (zero cost)

◆ hints_received

unsigned long long hints_received

Total hints read from pipe

◆ hits_t1

uint64_t hits_t1

Hits in T1

◆ hits_t2

uint64_t hits_t2

Hits in T2

◆ index_didname

hash_t* index_didname
static

◆ index_queue

q_t* index_queue
static

◆ p

size_t p

Target size for T1

◆ p_decreases

uint64_t p_decreases

Times p decreased

◆ p_increases

uint64_t p_increases

Times p increased

◆ p_max

size_t p_max

Min/max p values seen

◆ p_min

size_t p_min

◆ promotions_t1_to_t2

uint64_t promotions_t1_to_t2

Promotions from T1 to T2

◆ queue_count

unsigned long queue_count
static

◆ queue_count_max

unsigned long queue_count_max = 0
static

Peak cached entries reached this session (shared by LRU and ARC)

◆ rfork_cache_budget

size_t rfork_cache_budget = 0

◆ rfork_cache_used

size_t rfork_cache_used = 0

◆ rfork_lru

q_t* rfork_lru = NULL

◆ rfork_lru_count

unsigned int rfork_lru_count = 0

◆ rfork_max_entry_size

size_t rfork_max_entry_size = 0

◆ rfork_stat_added

unsigned long long rfork_stat_added = 0

◆ rfork_stat_evicted

unsigned long long rfork_stat_evicted = 0

◆ rfork_stat_hits

unsigned long long rfork_stat_hits = 0

◆ rfork_stat_invalidated

unsigned long long rfork_stat_invalidated = 0

◆ rfork_stat_lookups

unsigned long long rfork_stat_lookups = 0

◆ rfork_stat_misses

unsigned long long rfork_stat_misses = 0

◆ rfork_stat_used_max

size_t rfork_stat_used_max = 0

◆ [struct]

struct { ... } stats

◆ t1

q_t* t1

Recent entries (cached)

◆ t1_size

size_t t1_size

◆ t2

q_t* t2

Frequent entries (cached)

◆ t2_size

size_t t2_size

◆ validation_counter

volatile uint64_t validation_counter = 0
static