Skip to content

Commit

Permalink
ocfs2: Abstract out core dir listing functionality
Browse files Browse the repository at this point in the history
Put this in it's own function so that the functionality can be overridden.

Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Reviewed-by: Joel Becker <joel.becker@oracle.com>
  • Loading branch information
Mark Fasheh committed Oct 12, 2007
1 parent 316f4b9 commit b8bc5f4
Showing 1 changed file with 56 additions and 47 deletions.
103 changes: 56 additions & 47 deletions fs/ocfs2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,57 +414,32 @@ int __ocfs2_add_entry(handle_t *handle,
return retval;
}

/*
* ocfs2_readdir()
*
*/
int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
static int ocfs2_dir_foreach_blk(struct inode *inode, unsigned long *f_version,
loff_t *f_pos, void *priv, filldir_t filldir)
{
int error = 0;
unsigned long offset, blk, last_ra_blk = 0;
int i, stored;
struct buffer_head * bh, * tmp;
struct ocfs2_dir_entry * de;
int err;
struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block * sb = inode->i_sb;
unsigned int ra_sectors = 16;
int lock_level = 0;

mlog_entry("dirino=%llu\n",
(unsigned long long)OCFS2_I(inode)->ip_blkno);

stored = 0;
bh = NULL;

error = ocfs2_meta_lock_atime(inode, filp->f_vfsmnt, &lock_level);
if (lock_level && error >= 0) {
/* We release EX lock which used to update atime
* and get PR lock again to reduce contention
* on commonly accessed directories. */
ocfs2_meta_unlock(inode, 1);
lock_level = 0;
error = ocfs2_meta_lock(inode, NULL, 0);
}
if (error < 0) {
if (error != -ENOENT)
mlog_errno(error);
/* we haven't got any yet, so propagate the error. */
stored = error;
goto bail_nolock;
}

offset = filp->f_pos & (sb->s_blocksize - 1);
offset = (*f_pos) & (sb->s_blocksize - 1);

while (!error && !stored && filp->f_pos < i_size_read(inode)) {
blk = (filp->f_pos) >> sb->s_blocksize_bits;
while (!error && !stored && *f_pos < i_size_read(inode)) {
blk = (*f_pos) >> sb->s_blocksize_bits;
bh = ocfs2_bread(inode, blk, &err, 0);
if (!bh) {
mlog(ML_ERROR,
"directory #%llu contains a hole at offset %lld\n",
(unsigned long long)OCFS2_I(inode)->ip_blkno,
filp->f_pos);
filp->f_pos += sb->s_blocksize - offset;
*f_pos);
*f_pos += sb->s_blocksize - offset;
continue;
}

Expand All @@ -490,7 +465,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
* readdir(2), then we might be pointing to an invalid
* dirent right now. Scan from the start of the block
* to make sure. */
if (filp->f_version != inode->i_version) {
if (*f_version != inode->i_version) {
for (i = 0; i < sb->s_blocksize && i < offset; ) {
de = (struct ocfs2_dir_entry *) (bh->b_data + i);
/* It's too expensive to do a full
Expand All @@ -505,21 +480,20 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
i += le16_to_cpu(de->rec_len);
}
offset = i;
filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
*f_pos = ((*f_pos) & ~(sb->s_blocksize - 1))
| offset;
filp->f_version = inode->i_version;
*f_version = inode->i_version;
}

while (!error && filp->f_pos < i_size_read(inode)
while (!error && *f_pos < i_size_read(inode)
&& offset < sb->s_blocksize) {
de = (struct ocfs2_dir_entry *) (bh->b_data + offset);
if (!ocfs2_check_dir_entry(inode, de, bh, offset)) {
/* On error, skip the f_pos to the
next block. */
filp->f_pos = (filp->f_pos |
(sb->s_blocksize - 1)) + 1;
*f_pos = ((*f_pos) | (sb->s_blocksize - 1)) + 1;
brelse(bh);
goto bail;
goto out;
}
offset += le16_to_cpu(de->rec_len);
if (le64_to_cpu(de->inode)) {
Expand All @@ -530,36 +504,71 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
* not the directory has been modified
* during the copy operation.
*/
unsigned long version = filp->f_version;
unsigned long version = *f_version;
unsigned char d_type = DT_UNKNOWN;

if (de->file_type < OCFS2_FT_MAX)
d_type = ocfs2_filetype_table[de->file_type];
error = filldir(dirent, de->name,
error = filldir(priv, de->name,
de->name_len,
filp->f_pos,
*f_pos,
ino_from_blkno(sb, le64_to_cpu(de->inode)),
d_type);
if (error)
break;
if (version != filp->f_version)
if (version != *f_version)
goto revalidate;
stored ++;
}
filp->f_pos += le16_to_cpu(de->rec_len);
*f_pos += le16_to_cpu(de->rec_len);
}
offset = 0;
brelse(bh);
}

stored = 0;
bail:
out:
return stored;
}

/*
* ocfs2_readdir()
*
*/
int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
int error = 0;
struct inode *inode = filp->f_path.dentry->d_inode;
int lock_level = 0;

mlog_entry("dirino=%llu\n",
(unsigned long long)OCFS2_I(inode)->ip_blkno);

error = ocfs2_meta_lock_atime(inode, filp->f_vfsmnt, &lock_level);
if (lock_level && error >= 0) {
/* We release EX lock which used to update atime
* and get PR lock again to reduce contention
* on commonly accessed directories. */
ocfs2_meta_unlock(inode, 1);
lock_level = 0;
error = ocfs2_meta_lock(inode, NULL, 0);
}
if (error < 0) {
if (error != -ENOENT)
mlog_errno(error);
/* we haven't got any yet, so propagate the error. */
goto bail_nolock;
}

error = ocfs2_dir_foreach_blk(inode, &filp->f_version, &filp->f_pos,
dirent, filldir);

ocfs2_meta_unlock(inode, lock_level);

bail_nolock:
mlog_exit(stored);
mlog_exit(error);

return stored;
return error;
}

/*
Expand Down

0 comments on commit b8bc5f4

Please sign in to comment.