Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8bc5f4f authored by Mark Fasheh's avatar Mark Fasheh
Browse files

ocfs2: Abstract out core dir listing functionality



Put this in it's own function so that the functionality can be overridden.

Signed-off-by: default avatarMark Fasheh <mark.fasheh@oracle.com>
Reviewed-by: default avatarJoel Becker <joel.becker@oracle.com>
parent 316f4b9f
Loading
Loading
Loading
Loading
+56 −47
Original line number Original line Diff line number Diff line
@@ -414,11 +414,8 @@ int __ocfs2_add_entry(handle_t *handle,
	return retval;
	return retval;
}
}


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

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


	stored = 0;
	stored = 0;
	bh = NULL;
	bh = NULL;


	error = ocfs2_meta_lock_atime(inode, filp->f_vfsmnt, &lock_level);
	offset = (*f_pos) & (sb->s_blocksize - 1);
	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);


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


@@ -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
		 * readdir(2), then we might be pointing to an invalid
		 * dirent right now.  Scan from the start of the block
		 * dirent right now.  Scan from the start of the block
		 * to make sure. */
		 * 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; ) {
			for (i = 0; i < sb->s_blocksize && i < offset; ) {
				de = (struct ocfs2_dir_entry *) (bh->b_data + i);
				de = (struct ocfs2_dir_entry *) (bh->b_data + i);
				/* It's too expensive to do a full
				/* It's too expensive to do a full
@@ -505,21 +480,20 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
				i += le16_to_cpu(de->rec_len);
				i += le16_to_cpu(de->rec_len);
			}
			}
			offset = i;
			offset = i;
			filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
			*f_pos = ((*f_pos) & ~(sb->s_blocksize - 1))
				| offset;
				| 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) {
		       && offset < sb->s_blocksize) {
			de = (struct ocfs2_dir_entry *) (bh->b_data + offset);
			de = (struct ocfs2_dir_entry *) (bh->b_data + offset);
			if (!ocfs2_check_dir_entry(inode, de, bh, offset)) {
			if (!ocfs2_check_dir_entry(inode, de, bh, offset)) {
				/* On error, skip the f_pos to the
				/* On error, skip the f_pos to the
				   next block. */
				   next block. */
				filp->f_pos = (filp->f_pos |
				*f_pos = ((*f_pos) | (sb->s_blocksize - 1)) + 1;
					       (sb->s_blocksize - 1)) + 1;
				brelse(bh);
				brelse(bh);
				goto bail;
				goto out;
			}
			}
			offset += le16_to_cpu(de->rec_len);
			offset += le16_to_cpu(de->rec_len);
			if (le64_to_cpu(de->inode)) {
			if (le64_to_cpu(de->inode)) {
@@ -530,36 +504,71 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
				 * not the directory has been modified
				 * not the directory has been modified
				 * during the copy operation.
				 * during the copy operation.
				 */
				 */
				unsigned long version = filp->f_version;
				unsigned long version = *f_version;
				unsigned char d_type = DT_UNKNOWN;
				unsigned char d_type = DT_UNKNOWN;


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


	stored = 0;
	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);
	ocfs2_meta_unlock(inode, lock_level);


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


	return stored;
	return error;
}
}


/*
/*