diff options
author | Mark Fasheh <mark.fasheh@oracle.com> | 2006-04-21 16:49:02 -0400 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2006-09-20 18:53:40 -0400 |
commit | aa9588741db907785e4d92c8b768dd6c9077e6f0 (patch) | |
tree | d34da288a9d296a8a2ba19dfa0f1df8429bd3e33 /fs/ocfs2/dir.c | |
parent | e0b4096d34fbd6b30838c417100c9d0ef73c71f2 (diff) |
ocfs2: implement directory read-ahead
Uptodate.c now knows about read-ahead buffers. Use some more aggressive
logic in ocfs2_readdir().
The two functions which currently use directory read-ahead are
ocfs2_find_entry() and ocfs2_readdir().
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2/dir.c')
-rw-r--r-- | fs/ocfs2/dir.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 3d494d1a5f36..04e01915b86e 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -74,14 +74,14 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
74 | int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | 74 | int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) |
75 | { | 75 | { |
76 | int error = 0; | 76 | int error = 0; |
77 | unsigned long offset, blk; | 77 | unsigned long offset, blk, last_ra_blk = 0; |
78 | int i, num, stored; | 78 | int i, stored; |
79 | struct buffer_head * bh, * tmp; | 79 | struct buffer_head * bh, * tmp; |
80 | struct ocfs2_dir_entry * de; | 80 | struct ocfs2_dir_entry * de; |
81 | int err; | 81 | int err; |
82 | struct inode *inode = filp->f_dentry->d_inode; | 82 | struct inode *inode = filp->f_dentry->d_inode; |
83 | struct super_block * sb = inode->i_sb; | 83 | struct super_block * sb = inode->i_sb; |
84 | int have_disk_lock = 0; | 84 | unsigned int ra_sectors = 16; |
85 | 85 | ||
86 | mlog_entry("dirino=%llu\n", | 86 | mlog_entry("dirino=%llu\n", |
87 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 87 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
@@ -95,9 +95,8 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
95 | mlog_errno(error); | 95 | mlog_errno(error); |
96 | /* we haven't got any yet, so propagate the error. */ | 96 | /* we haven't got any yet, so propagate the error. */ |
97 | stored = error; | 97 | stored = error; |
98 | goto bail; | 98 | goto bail_nolock; |
99 | } | 99 | } |
100 | have_disk_lock = 1; | ||
101 | 100 | ||
102 | offset = filp->f_pos & (sb->s_blocksize - 1); | 101 | offset = filp->f_pos & (sb->s_blocksize - 1); |
103 | 102 | ||
@@ -113,16 +112,21 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
113 | continue; | 112 | continue; |
114 | } | 113 | } |
115 | 114 | ||
116 | /* | 115 | /* The idea here is to begin with 8k read-ahead and to stay |
117 | * Do the readahead (8k) | 116 | * 4k ahead of our current position. |
118 | */ | 117 | * |
119 | if (!offset) { | 118 | * TODO: Use the pagecache for this. We just need to |
120 | for (i = 16 >> (sb->s_blocksize_bits - 9), num = 0; | 119 | * make sure it's cluster-safe... */ |
120 | if (!last_ra_blk | ||
121 | || (((last_ra_blk - blk) << 9) <= (ra_sectors / 2))) { | ||
122 | for (i = ra_sectors >> (sb->s_blocksize_bits - 9); | ||
121 | i > 0; i--) { | 123 | i > 0; i--) { |
122 | tmp = ocfs2_bread(inode, ++blk, &err, 1); | 124 | tmp = ocfs2_bread(inode, ++blk, &err, 1); |
123 | if (tmp) | 125 | if (tmp) |
124 | brelse(tmp); | 126 | brelse(tmp); |
125 | } | 127 | } |
128 | last_ra_blk = blk; | ||
129 | ra_sectors = 8; | ||
126 | } | 130 | } |
127 | 131 | ||
128 | revalidate: | 132 | revalidate: |
@@ -194,9 +198,9 @@ revalidate: | |||
194 | 198 | ||
195 | stored = 0; | 199 | stored = 0; |
196 | bail: | 200 | bail: |
197 | if (have_disk_lock) | 201 | ocfs2_meta_unlock(inode, 0); |
198 | ocfs2_meta_unlock(inode, 0); | ||
199 | 202 | ||
203 | bail_nolock: | ||
200 | mlog_exit(stored); | 204 | mlog_exit(stored); |
201 | 205 | ||
202 | return stored; | 206 | return stored; |