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

Commit 5eae5b96 authored by Mark Fasheh's avatar Mark Fasheh
Browse files

ocfs2: Remove open coded readdir()



ocfs2_queue_orphans() has an open coded readdir loop which can easily just
use a directory accessor function.

Signed-off-by: default avatarMark Fasheh <mark.fasheh@oracle.com>
Reviewed-by: default avatarJoel Becker <joel.becker@oracle.com>
parent 7e853679
Loading
Loading
Loading
Loading
+24 −4
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
			       struct ocfs2_alloc_context *meta_ac,
			       struct buffer_head **new_bh);

int ocfs2_check_dir_entry(struct inode * dir,
static int ocfs2_check_dir_entry(struct inode * dir,
				 struct ocfs2_dir_entry * de,
				 struct buffer_head * bh,
				 unsigned long offset)
@@ -531,6 +531,26 @@ static int ocfs2_dir_foreach_blk(struct inode *inode, unsigned long *f_version,
	return stored;
}

/*
 * This is intended to be called from inside other kernel functions,
 * so we fake some arguments.
 */
int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv,
		      filldir_t filldir)
{
	int ret = 0;
	unsigned long version = inode->i_version;

	while (*f_pos < i_size_read(inode)) {
		ret = ocfs2_dir_foreach_blk(inode, &version, f_pos, priv,
					    filldir);
		if (ret)
			break;
	}

	return 0;
}

/*
 * ocfs2_readdir()
 *
+2 −5
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ int ocfs2_find_files_on_disk(const char *name,
			     struct buffer_head **dirent_bh,
			     struct ocfs2_dir_entry **dirent);
int ocfs2_readdir(struct file *filp, void *dirent, filldir_t filldir);
int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv,
		      filldir_t filldir);
int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
				 struct inode *dir,
				 struct buffer_head *parent_fe_bh,
@@ -76,9 +78,4 @@ int ocfs2_fill_new_dir(struct ocfs2_super *osb,
		       struct buffer_head *fe_bh,
		       struct ocfs2_alloc_context *data_ac);

int ocfs2_check_dir_entry(struct inode *dir,
			  struct ocfs2_dir_entry *de,
			  struct buffer_head *bh,
			  unsigned long offset);

#endif /* OCFS2_DIR_H */
+44 −74
Original line number Diff line number Diff line
@@ -1213,17 +1213,49 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
	return status;
}

struct ocfs2_orphan_filldir_priv {
	struct inode		*head;
	struct ocfs2_super	*osb;
};

static int ocfs2_orphan_filldir(void *priv, const char *name, int name_len,
				loff_t pos, u64 ino, unsigned type)
{
	struct ocfs2_orphan_filldir_priv *p = priv;
	struct inode *iter;

	if (name_len == 1 && !strncmp(".", name, 1))
		return 0;
	if (name_len == 2 && !strncmp("..", name, 2))
		return 0;

	/* Skip bad inodes so that recovery can continue */
	iter = ocfs2_iget(p->osb, ino,
			  OCFS2_FI_FLAG_ORPHAN_RECOVERY);
	if (IS_ERR(iter))
		return 0;

	mlog(0, "queue orphan %llu\n",
	     (unsigned long long)OCFS2_I(iter)->ip_blkno);
	/* No locking is required for the next_orphan queue as there
	 * is only ever a single process doing orphan recovery. */
	OCFS2_I(iter)->ip_next_orphan = p->head;
	p->head = iter;

	return 0;
}

static int ocfs2_queue_orphans(struct ocfs2_super *osb,
			       int slot,
			       struct inode **head)
{
	int status;
	struct inode *orphan_dir_inode = NULL;
	struct inode *iter;
	unsigned long offset, blk, local;
	struct buffer_head *bh = NULL;
	struct ocfs2_dir_entry *de;
	struct super_block *sb = osb->sb;
	struct ocfs2_orphan_filldir_priv priv;
	loff_t pos = 0;

	priv.osb = osb;
	priv.head = *head;

	orphan_dir_inode = ocfs2_get_system_file_inode(osb,
						       ORPHAN_DIR_SYSTEM_INODE,
@@ -1241,77 +1273,15 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb,
		goto out;
	}

	offset = 0;
	iter = NULL;
	while(offset < i_size_read(orphan_dir_inode)) {
		blk = offset >> sb->s_blocksize_bits;

		bh = ocfs2_bread(orphan_dir_inode, blk, &status, 0);
		if (!bh)
			status = -EINVAL;
		if (status < 0) {
			if (bh)
				brelse(bh);
	status = ocfs2_dir_foreach(orphan_dir_inode, &pos, &priv,
				   ocfs2_orphan_filldir);
	if (status) {
		mlog_errno(status);
			goto out_unlock;
		}

		local = 0;
		while(offset < i_size_read(orphan_dir_inode)
		      && local < sb->s_blocksize) {
			de = (struct ocfs2_dir_entry *) (bh->b_data + local);

			if (!ocfs2_check_dir_entry(orphan_dir_inode,
						  de, bh, local)) {
				status = -EINVAL;
				mlog_errno(status);
				brelse(bh);
				goto out_unlock;
			}

			local += le16_to_cpu(de->rec_len);
			offset += le16_to_cpu(de->rec_len);

			/* I guess we silently fail on no inode? */
			if (!le64_to_cpu(de->inode))
				continue;
			if (de->file_type > OCFS2_FT_MAX) {
				mlog(ML_ERROR,
				     "block %llu contains invalid de: "
				     "inode = %llu, rec_len = %u, "
				     "name_len = %u, file_type = %u, "
				     "name='%.*s'\n",
				     (unsigned long long)bh->b_blocknr,
				     (unsigned long long)le64_to_cpu(de->inode),
				     le16_to_cpu(de->rec_len),
				     de->name_len,
				     de->file_type,
				     de->name_len,
				     de->name);
				continue;
		goto out;
	}
			if (de->name_len == 1 && !strncmp(".", de->name, 1))
				continue;
			if (de->name_len == 2 && !strncmp("..", de->name, 2))
				continue;

			iter = ocfs2_iget(osb, le64_to_cpu(de->inode),
					  OCFS2_FI_FLAG_ORPHAN_RECOVERY);
			if (IS_ERR(iter))
				continue;

			mlog(0, "queue orphan %llu\n",
			     (unsigned long long)OCFS2_I(iter)->ip_blkno);
			/* No locking is required for the next_orphan
			 * queue as there is only ever a single
			 * process doing orphan recovery. */
			OCFS2_I(iter)->ip_next_orphan = *head;
			*head = iter;
		}
		brelse(bh);
	}
	*head = priv.head;

out_unlock:
	ocfs2_meta_unlock(orphan_dir_inode, 0);
out:
	mutex_unlock(&orphan_dir_inode->i_mutex);