| To: | "xfs@xxxxxxxxxxx" <xfs@xxxxxxxxxxx> |
|---|---|
| Subject: | REVIEW: Improve caching in libxfs |
| From: | "Barry Naujok" <bnaujok@xxxxxxx> |
| Date: | Wed, 03 Sep 2008 16:38:34 +1000 |
| Organization: | SGI |
| Sender: | xfs-bounce@xxxxxxxxxxx |
| User-agent: | Opera Mail/9.51 (Win32) |
An old patch I wrote a while ago which speeds up a libxfs cache full of referenced blocks when trying to find a free/unused node. The old/current mechanisms stores all buffers, referenced and unreferenced in an MRU list. When a new buffer is needed, and there are a lot of referenced blocks (multi-threaded AG prefetch with lots of out-of-order seeks), a lot of CPU time can be spent trying to find a block (and even failing). This patch changes the MRU to only store unreferenced blocks so the searching doesn't scan through referenced blocks. The buffer priority mechanism has been tweaked too to stop prefetching jamming with small cache sizes. --- xfsprogs/include/cache.h | 2 - xfsprogs/libxfs/cache.c | 68 ++++++++++++++++++++++----------------------- xfsprogs/libxfs/rdwr.c | 6 +-- xfsprogs/repair/prefetch.c | 18 +++++------ 4 files changed, 47 insertions(+), 47 deletions(-) Index: xfs-cmds/xfsprogs/include/cache.h =================================================================== --- xfs-cmds.orig/xfsprogs/include/cache.h +++ xfs-cmds/xfsprogs/include/cache.h @@ -95,7 +95,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: xfs-cmds/xfsprogs/libxfs/cache.c
===================================================================
--- xfs-cmds.orig/xfsprogs/libxfs/cache.c
+++ xfs-cmds/xfsprogs/libxfs/cache.c
@@ -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: xfs-cmds/xfsprogs/libxfs/rdwr.c
===================================================================
--- xfs-cmds.orig/xfsprogs/libxfs/rdwr.c
+++ xfs-cmds/xfsprogs/libxfs/rdwr.c
@@ -393,7 +393,7 @@ libxfs_getbuf(dev_t device, xfs_daddr_t
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) - 8);
#ifdef XFS_BUF_TRACING
pthread_mutex_lock(&libxfs_bcache->c_mutex);
lock_buf_count++;
@@ -422,7 +422,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 +794,7 @@ libxfs_iget(xfs_mount_t *mp, xfs_trans_t
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: xfs-cmds/xfsprogs/repair/prefetch.c =================================================================== --- xfs-cmds.orig/xfsprogs/repair/prefetch.c +++ xfs-cmds/xfsprogs/repair/prefetch.c @@ -38,16 +38,16 @@ static void pf_read_inode_dirs(prefetch /* 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_DIR_META_2 14 /* metadata in secondary queue */ +#define B_DIR_META_H 13 /* metadata fetched for PF_META_ONLY */ +#define B_DIR_META_S 12 /* single block of metadata */ +#define B_DIR_META 11 +#define B_DIR_INODE 10 +#define B_BMAP 9 +#define B_INODE 8 -#define B_IS_INODE(b) (((b) & 1) == 0) -#define B_IS_META(b) (((b) & 1) != 0) +#define B_IS_INODE(f) (((f) & 5) == 0) +#define B_IS_META(f) (((f) & 5) != 0) #define DEF_BATCH_BYTES 0x10000 |
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| ||
| Previous by Date: | [PATCH V2] Don't do I/O beyond eof when unreserving space, Lachlan McIlroy |
|---|---|
| Next by Date: | REVIEW: Zero rest of superblock sector always, Barry Naujok |
| Previous by Thread: | [PATCH V2] Don't do I/O beyond eof when unreserving space, Lachlan McIlroy |
| Next by Thread: | Re: REVIEW: Improve caching in libxfs, Christoph Hellwig |
| Indexes: | [Date] [Thread] [Top] [All Lists] |