[Ocfs2-devel] [PATCH 14/15] ocfs2: Read support for directories with inline data

Joel Becker Joel.Becker at oracle.com
Thu Sep 20 16:47:40 PDT 2007


On Wed, Sep 12, 2007 at 01:01:18PM -0700, Mark Fasheh wrote:
> +static int ocfs2_dir_foreach_blk_id(struct inode *inode,
> +				    unsigned long *f_version,
> +				    loff_t *f_pos, void *priv,
> +				    filldir_t filldir)
> +{

	Isn't this function basically the center of foreach_blk_el()?
Is there any way to consolidate that?

Joel

> +	int ret, i, filldir_ret;
> +	unsigned long offset = *f_pos;
> +	struct buffer_head *di_bh = NULL;
> +	struct ocfs2_dinode *di;
> +	struct ocfs2_inline_data *data;
> +	struct ocfs2_dir_entry *de;
> +
> +	ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), OCFS2_I(inode)->ip_blkno,
> +			       &di_bh, OCFS2_BH_CACHED, inode);
> +	if (ret) {
> +		mlog(ML_ERROR, "Unable to read inode block for dir %llu\n",
> +		     (unsigned long long)OCFS2_I(inode)->ip_blkno);
> +		goto out;
> +	}
> +
> +	di = (struct ocfs2_dinode *)di_bh->b_data;
> +	data = &di->id2.i_data;
> +
> +	while (*f_pos < i_size_read(inode)) {
> +revalidate:
> +		/* If the dir block has changed since the last call to
> +		 * readdir(2), then we might be pointing to an invalid
> +		 * dirent right now.  Scan from the start of the block
> +		 * to make sure. */
> +		if (*f_version != inode->i_version) {
> +			for (i = 0; i < i_size_read(inode) && i < offset; ) {
> +				de = (struct ocfs2_dir_entry *)
> +					(data->id_data + i);
> +				/* It's too expensive to do a full
> +				 * dirent test each time round this
> +				 * loop, but we do have to test at
> +				 * least that it is non-zero.  A
> +				 * failure will be detected in the
> +				 * dirent test below. */
> +				if (le16_to_cpu(de->rec_len) <
> +				    OCFS2_DIR_REC_LEN(1))
> +					break;
> +				i += le16_to_cpu(de->rec_len);
> +			}
> +			*f_pos = offset = i;
> +			*f_version = inode->i_version;
> +		}
> +
> +		de = (struct ocfs2_dir_entry *) (data->id_data + *f_pos);
> +		if (!ocfs2_check_dir_entry(inode, de, di_bh, *f_pos)) {
> +			/* On error, skip the f_pos to the end. */
> +			*f_pos = i_size_read(inode);
> +			goto out;
> +		}
> +		offset += le16_to_cpu(de->rec_len);
> +		if (le64_to_cpu(de->inode)) {
> +			/* We might block in the next section
> +			 * if the data destination is
> +			 * currently swapped out.  So, use a
> +			 * version stamp to detect whether or
> +			 * not the directory has been modified
> +			 * during the copy operation.
> +			 */
> +			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];
> +
> +			filldir_ret = filldir(priv, de->name,
> +					      de->name_len,
> +					      *f_pos,
> +					      le64_to_cpu(de->inode),
> +					      d_type);
> +			if (filldir_ret)
> +				break;
> +			if (version != *f_version)
> +				goto revalidate;
> +		}
> +		*f_pos += le16_to_cpu(de->rec_len);
> +	}
> +
> +out:
> +	brelse(di_bh);
> +
> +	return 0;
> +}

-- 

"Here's something to think about:  How come you never see a headline
 like ``Psychic Wins Lottery''?"
	- Jay Leno

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127



More information about the Ocfs2-devel mailing list