]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - include/cache.h
xfs: automatic dfops buffer relogging
[thirdparty/xfsprogs-dev.git] / include / cache.h
index 85dce63a608db0c8cf5122c62ce6f083e2fbb018..552b92489e4699443b4fb64c3397899d3f78188a 100644 (file)
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2006 Silicon Graphics, Inc.
  * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #ifndef __CACHE_H__
 #define __CACHE_H__
 
+/*
+ * initialisation flags
+ */
+/*
+ * xfs_db always writes changes immediately, and so we need to purge buffers
+ * when we get a buffer lookup mismatch due to reading the same block with a
+ * different buffer configuration.
+ */
+#define CACHE_MISCOMPARE_PURGE (1 << 0)
+
+/*
+ * cache object campare return values
+ */
+enum {
+       CACHE_HIT,
+       CACHE_MISS,
+       CACHE_PURGE,
+};
+
+#define        HASH_CACHE_RATIO        8
+
+/*
+ * Cache priorities range from BASE to MAX.
+ *
+ * For prefetch support, the top half of the range starts at
+ * CACHE_PREFETCH_PRIORITY and everytime the buffer is fetched and is at or
+ * above this priority level, it is reduced to below this level (refer to
+ * libxfs_getbuf).
+ *
+ * If we have dirty nodes, we can't recycle them until they've been cleaned. To
+ * keep these out of the reclaimable lists (as there can be lots of them) give
+ * them their own priority that the shaker doesn't attempt to walk.
+ */
+
+#define CACHE_BASE_PRIORITY    0
+#define CACHE_PREFETCH_PRIORITY        8
+#define CACHE_MAX_PRIORITY     15
+#define CACHE_DIRTY_PRIORITY   (CACHE_MAX_PRIORITY + 1)
+#define CACHE_NR_PRIORITIES    CACHE_DIRTY_PRIORITY
+
 /*
  * Simple, generic implementation of a cache (arbitrary data).
  * Provides a hash table with a capped number of cache entries.
  */
 
 struct cache;
-struct cache_hash;
 struct cache_node;
 
 typedef void *cache_key_t;
+
 typedef void (*cache_walk_t)(struct cache_node *);
-typedef struct cache_node * (*cache_node_alloc_t)(void);
+typedef struct cache_node * (*cache_node_alloc_t)(cache_key_t);
+typedef int (*cache_node_flush_t)(struct cache_node *);
 typedef void (*cache_node_relse_t)(struct cache_node *);
-typedef unsigned int (*cache_node_hash_t)(cache_key_t, unsigned int);
+typedef unsigned int (*cache_node_hash_t)(cache_key_t, unsigned int,
+                                         unsigned int);
 typedef int (*cache_node_compare_t)(struct cache_node *, cache_key_t);
+typedef unsigned int (*cache_bulk_relse_t)(struct cache *, struct list_head *);
 
 struct cache_operations {
        cache_node_hash_t       hash;
        cache_node_alloc_t      alloc;
+       cache_node_flush_t      flush;
        cache_node_relse_t      relse;
        cache_node_compare_t    compare;
+       cache_bulk_relse_t      bulkrelse;      /* optional */
+};
+
+struct cache_hash {
+       struct list_head        ch_list;        /* hash chain head */
+       unsigned int            ch_count;       /* hash chain length */
+       pthread_mutex_t         ch_mutex;       /* hash chain mutex */
+};
+
+struct cache_mru {
+       struct list_head        cm_list;        /* MRU head */
+       unsigned int            cm_count;       /* MRU length */
+       pthread_mutex_t         cm_mutex;       /* MRU lock */
+};
+
+struct cache_node {
+       struct list_head        cn_hash;        /* hash chain */
+       struct list_head        cn_mru;         /* MRU chain */
+       unsigned int            cn_count;       /* reference count */
+       unsigned int            cn_hashidx;     /* hash chain index */
+       int                     cn_priority;    /* priority, -1 = free list */
+       int                     cn_old_priority;/* saved pre-dirty prio */
+       pthread_mutex_t         cn_mutex;       /* node mutex */
 };
 
 struct cache {
+       int                     c_flags;        /* behavioural flags */
        unsigned int            c_maxcount;     /* max cache nodes */
        unsigned int            c_count;        /* count of nodes */
        pthread_mutex_t         c_mutex;        /* node count mutex */
        cache_node_hash_t       hash;           /* node hash function */
        cache_node_alloc_t      alloc;          /* allocation function */
+       cache_node_flush_t      flush;          /* flush dirty data function */
        cache_node_relse_t      relse;          /* memory free function */
        cache_node_compare_t    compare;        /* comparison routine */
+       cache_bulk_relse_t      bulkrelse;      /* bulk release routine */
        unsigned int            c_hashsize;     /* hash bucket count */
+       unsigned int            c_hashshift;    /* hash key shift */
        struct cache_hash       *c_hash;        /* hash table buckets */
+       struct cache_mru        c_mrus[CACHE_DIRTY_PRIORITY + 1];
+       unsigned long long      c_misses;       /* cache misses */
+       unsigned long long      c_hits;         /* cache hits */
+       unsigned int            c_max;          /* max nodes ever used */
 };
 
-struct cache_hash {
-       struct list_head        ch_list;        /* hash chain head */
-       pthread_mutex_t         ch_mutex;       /* hash chain mutex */
-};
-
-struct cache_node {
-       struct list_head        cn_list;        /* hash chain */
-       unsigned int            cn_count;       /* reference count */
-       pthread_mutex_t         cn_mutex;       /* refcount mutex */
-};
-
-struct cache *cache_init(unsigned int, struct cache_operations *);
+struct cache *cache_init(int, unsigned int, struct cache_operations *);
 void cache_destroy(struct cache *);
 void cache_walk(struct cache *, cache_walk_t);
 void cache_purge(struct cache *);
+void cache_flush(struct cache *);
 
 int cache_node_get(struct cache *, cache_key_t, struct cache_node **);
-void cache_node_put(struct cache_node *);
+void cache_node_put(struct cache *, struct cache_node *);
+void cache_node_set_priority(struct cache *, struct cache_node *, int);
+int cache_node_get_priority(struct cache_node *);
 int cache_node_purge(struct cache *, cache_key_t, struct cache_node *);
+void cache_report(FILE *fp, const char *, struct cache *);
+int cache_overflowed(struct cache *);
 
 #endif /* __CACHE_H__ */