Hi,

This patch adds read-ahead capability to GFS2's
directory hash table management.  It greatly improves
performance for some directory operations.  For example:
In one of my file systems that has 1000 directories, each
of which has 1000 files, time to execute a recursive
ls (time ls -fR /mnt/gfs2 > /dev/null) was reduced
from 2m2.814s on a stock kernel to 0m45.938s.

Regards,

Bob Peterson
Red Hat File Systems

Signed-off-by: Bob Peterson <rpete...@redhat.com> 
--
 fs/gfs2/dir.c |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 2045d70..9b4262e 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -1376,6 +1376,37 @@ out:
        return error;
 }
 
+static void gfs2_dir_readahead(struct inode *inode, __be64 *ht, unsigned hsize,
+                              u32 index)
+{
+       struct gfs2_inode *ip = GFS2_I(inode);
+       struct gfs2_glock *gl = ip->i_gl;
+       struct buffer_head *bh;
+       u64 blocknr = 0, last;
+       unsigned count = 0;
+
+       while (index < hsize) {
+               last = blocknr;
+               blocknr = be64_to_cpu(ht[index++]);
+               if (blocknr == last)
+                       continue;
+               count++;
+               if (count > 128)
+                       break;
+               bh = gfs2_getbuf(gl, blocknr, 1);
+               if (trylock_buffer(bh)) {
+                       if (buffer_uptodate(bh)) {
+                               unlock_buffer(bh);
+                               brelse(bh);
+                               continue;
+                       }
+                       bh->b_end_io = end_buffer_read_sync;
+                       submit_bh(READA | REQ_META, bh);
+                       continue;
+               }
+               brelse(bh);
+       }
+}
 
 /**
  * dir_e_read - Reads the entries from a directory into a filldir buffer
@@ -1406,6 +1437,8 @@ static int dir_e_read(struct inode *inode, u64 *offset, 
void *opaque,
        if (IS_ERR(lp))
                return PTR_ERR(lp);
 
+       gfs2_dir_readahead(inode, lp, hsize, index);
+
        while (index < hsize) {
                error = gfs2_dir_read_leaf(inode, offset, opaque, filldir,
                                           &copied, &depth,

Reply via email to