]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Change the libxfs cache MRU to only store unreferenced blocks
authorBarry Naujok <bnaujok@sgi.com>
Fri, 5 Sep 2008 04:10:01 +0000 (04:10 +0000)
committerBarry Naujok <bnaujok@sgi.com>
Fri, 5 Sep 2008 04:10:01 +0000 (04:10 +0000)
so the searching doesn't scan through referenced blocks.
Merge of master-melb:xfs-cmds:32049a by kenmcd.

  Improve libxfs cache RU

include/cache.h
libxfs/cache.c
libxfs/rdwr.c
repair/prefetch.c

index 317ff738d41f14e13dc8795505e81e8904ec04e9..0c0a1c500fd060cb159230aaeb77cc5a7db8f631 100644 (file)
 
 #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).
+ */
+
+#define CACHE_BASE_PRIORITY    0
+#define CACHE_PREFETCH_PRIORITY        8
 #define CACHE_MAX_PRIORITY     15
 
 /*
@@ -95,7 +106,7 @@ 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 *);
index 4e0831fd5aa721916aa5182265e91eb884783a3e..48f91d7c94f1c6e473bccbfe6e6e3dedbb7c32e1 100644 (file)
@@ -201,11 +201,11 @@ cache_shake(
                        continue;
 
                hash = cache->c_hash + node->cn_hashidx;
-               if (node->cn_count > 0 ||
-                               pthread_mutex_trylock(&hash->ch_mutex) != 0) {
+               if (pthread_mutex_trylock(&hash->ch_mutex) != 0) {
                        pthread_mutex_unlock(&node->cn_mutex);
                        continue;
                }
+               ASSERT(node->cn_count == 0);
                ASSERT(node->cn_priority == priority);
                node->cn_priority = -1;
 
@@ -264,6 +264,7 @@ cache_node_allocate(
                return NULL;
        }
        pthread_mutex_init(&node->cn_mutex, NULL);
+       list_head_init(&node->cn_mru);
        node->cn_count = 1;
        node->cn_priority = 0;
        return node;
@@ -309,16 +310,21 @@ cache_node_get(
                        if (!cache->compare(node, key))
                                continue;
                        /*
-                       * node found, bump node's reference count, move it to the
-                       * top of its MRU list, and update stats.
-                       */
+                        * node found, bump node's reference count, remove it
+                        * from its MRU list, and update stats.
+                        */
                        pthread_mutex_lock(&node->cn_mutex);
-                       node->cn_count++;
 
-                       mru = &cache->c_mrus[node->cn_priority];
-                       pthread_mutex_lock(&mru->cm_mutex);
-                       list_move(&node->cn_mru, &mru->cm_list);
-                       pthread_mutex_unlock(&mru->cm_mutex);
+                       if (node->cn_count == 0) {
+                               ASSERT(node->cn_priority >= 0);
+                               ASSERT(!list_empty(&node->cn_mru));
+                               mru = &cache->c_mrus[node->cn_priority];
+                               pthread_mutex_lock(&mru->cm_mutex);
+                               mru->cm_count--;
+                               list_del_init(&node->cn_mru);
+                               pthread_mutex_unlock(&mru->cm_mutex);
+                       }
+                       node->cn_count++;
 
                        pthread_mutex_unlock(&node->cn_mutex);
                        pthread_mutex_unlock(&hash->ch_mutex);
@@ -342,16 +348,11 @@ cache_node_get(
 
        node->cn_hashidx = hashidx;
 
-       /* add new node to appropriate hash and lowest priority MRU */
-       mru = &cache->c_mrus[0];
-       pthread_mutex_lock(&mru->cm_mutex);
+       /* add new node to appropriate hash */
        pthread_mutex_lock(&hash->ch_mutex);
        hash->ch_count++;
-       mru->cm_count++;
        list_add(&node->cn_hash, &hash->ch_list);
-       list_add(&node->cn_mru, &mru->cm_list);
        pthread_mutex_unlock(&hash->ch_mutex);
-       pthread_mutex_unlock(&mru->cm_mutex);
 
        *nodep = node;
        return 1;
@@ -359,8 +360,11 @@ cache_node_get(
 
 void
 cache_node_put(
+       struct cache *          cache,
        struct cache_node *     node)
 {
+       struct cache_mru *      mru;
+
        pthread_mutex_lock(&node->cn_mutex);
 #ifdef CACHE_DEBUG
        if (node->cn_count < 1) {
@@ -368,8 +372,23 @@ cache_node_put(
                                __FUNCTION__, node->cn_count, node);
                cache_abort();
        }
+       if (!list_empty(&node->cn_mru)) {
+               fprintf(stderr, "%s: node put on node (%p) in MRU list\n",
+                               __FUNCTION__, node);
+               cache_abort();
+       }
 #endif
        node->cn_count--;
+
+       if (node->cn_count == 0) {
+               /* add unreferenced node to appropriate MRU for shaker */
+               mru = &cache->c_mrus[node->cn_priority];
+               pthread_mutex_lock(&mru->cm_mutex);
+               mru->cm_count++;
+               list_add(&node->cn_mru, &mru->cm_list);
+               pthread_mutex_unlock(&mru->cm_mutex);
+       }
+
        pthread_mutex_unlock(&node->cn_mutex);
 }
 
@@ -379,33 +398,14 @@ cache_node_set_priority(
        struct cache_node *     node,
        int                     priority)
 {
-       struct cache_mru *      mru;
-
        if (priority < 0)
                priority = 0;
        else if (priority > CACHE_MAX_PRIORITY)
                priority = CACHE_MAX_PRIORITY;
 
        pthread_mutex_lock(&node->cn_mutex);
-
        ASSERT(node->cn_count > 0);
-       if (priority == node->cn_priority) {
-               pthread_mutex_unlock(&node->cn_mutex);
-               return;
-       }
-       mru = &cache->c_mrus[node->cn_priority];
-       pthread_mutex_lock(&mru->cm_mutex);
-       list_del_init(&node->cn_mru);
-       mru->cm_count--;
-       pthread_mutex_unlock(&mru->cm_mutex);
-
-       mru = &cache->c_mrus[priority];
-       pthread_mutex_lock(&mru->cm_mutex);
-       list_add(&node->cn_mru, &mru->cm_list);
        node->cn_priority = priority;
-       mru->cm_count++;
-       pthread_mutex_unlock(&mru->cm_mutex);
-
        pthread_mutex_unlock(&node->cn_mutex);
 }
 
index 8d84cd3f1deb142c593fe6da835de1e9bf25314d..3fe0fc3a5c7cafb6871baf5491c89cfbac602607 100644 (file)
@@ -393,7 +393,8 @@ libxfs_getbuf(dev_t device, xfs_daddr_t blkno, int len)
                if (use_xfs_buf_lock)
                        pthread_mutex_lock(&bp->b_lock);
                cache_node_set_priority(libxfs_bcache, (struct cache_node *)bp,
-                       cache_node_get_priority((struct cache_node *)bp) - 4);
+                       cache_node_get_priority((struct cache_node *)bp) -
+                                               CACHE_PREFETCH_PRIORITY);
 #ifdef XFS_BUF_TRACING
                pthread_mutex_lock(&libxfs_bcache->c_mutex);
                lock_buf_count++;
@@ -422,7 +423,7 @@ libxfs_putbuf(xfs_buf_t *bp)
 #endif
        if (use_xfs_buf_lock)
                pthread_mutex_unlock(&bp->b_lock);
-       cache_node_put((struct cache_node *)bp);
+       cache_node_put(libxfs_bcache, (struct cache_node *)bp);
 }
 
 void
@@ -794,7 +795,7 @@ libxfs_iget(xfs_mount_t *mp, xfs_trans_t *tp, xfs_ino_t ino, uint lock_flags,
 void
 libxfs_iput(xfs_inode_t *ip, uint lock_flags)
 {
-       cache_node_put((struct cache_node *)ip);
+       cache_node_put(libxfs_icache, (struct cache_node *)ip);
 }
 
 static struct cache_node *
index 2128ce5ba179c26fb1d9b95aef172e5c0312d644..e8a492fa68c5ff778dd5cd8beed35d1f9e755d59 100644 (file)
@@ -35,19 +35,36 @@ static int          pf_batch_fsbs;
 
 static void            pf_read_inode_dirs(prefetch_args_t *, xfs_buf_t *);
 
-/* buffer priorities for the libxfs cache */
-
-#define B_DIR_BMAP     15
-#define B_DIR_META_2   13      /* metadata in secondary queue */
-#define B_DIR_META_H   11      /* metadata fetched for PF_META_ONLY */
-#define B_DIR_META_S   9       /* single block of metadata */
-#define B_DIR_META     7
-#define B_DIR_INODE    6
-#define B_BMAP         5
-#define B_INODE                4
-
-#define B_IS_INODE(b)  (((b) & 1) == 0)
-#define B_IS_META(b)   (((b) & 1) != 0)
+/*
+ * Buffer priorities for the libxfs cache
+ *
+ * Directory metadata is ranked higher than other metadata as it's used
+ * in phases 3, 4 and 6, while other metadata is only used in 3 & 4.
+ */
+
+/* intermediate directory btree nodes - can't be queued */
+#define B_DIR_BMAP     CACHE_PREFETCH_PRIORITY + 7
+/* directory metadata in secondary queue */
+#define B_DIR_META_2   CACHE_PREFETCH_PRIORITY + 6
+/* dir metadata that had to fetched from the primary queue to avoid stalling */
+#define B_DIR_META_H   CACHE_PREFETCH_PRIORITY + 5
+/* single block of directory metadata (can't batch read) */
+#define B_DIR_META_S   CACHE_PREFETCH_PRIORITY + 4
+/* dir metadata with more than one block fetched in a single I/O */
+#define B_DIR_META     CACHE_PREFETCH_PRIORITY + 3
+/* inode clusters with directory inodes */
+#define B_DIR_INODE    CACHE_PREFETCH_PRIORITY + 2
+/* intermediate extent btree nodes */
+#define B_BMAP         CACHE_PREFETCH_PRIORITY + 1
+/* inode clusters without any directory entries */
+#define B_INODE                CACHE_PREFETCH_PRIORITY
+
+/*
+ * Test if bit 0 or 2 is set in the "priority tag" of the buffer to see if
+ * the buffer is for an inode or other metadata.
+ */
+#define B_IS_INODE(f)  (((f) & 5) == 0)
+#define B_IS_META(f)   (((f) & 5) != 0)
 
 #define DEF_BATCH_BYTES        0x10000