[Ocfs2-tools-devel] [PATCH 11/19] Ocfs2-tools: Add utility funcs of doing fiemap statistics.

Sunil Mushran sunil.mushran at oracle.com
Fri Apr 16 16:16:30 PDT 2010


Leave this out for now

Tristan Ye wrote:
> Common functions to do fiemaps which will be used for task('--space-usage')
> and task('--file-statistics').
>
> Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
> ---
>  o2info/operations.c |  205 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 205 insertions(+), 0 deletions(-)
>
> diff --git a/o2info/operations.c b/o2info/operations.c
> index cd134e5..68e8cdd 100644
> --- a/o2info/operations.c
> +++ b/o2info/operations.c
> @@ -319,3 +319,208 @@ out:
>  DEFINE_O2INFO_OP(fs_features,
>  		 fs_features_run,
>  		 NULL);
> +
> +/*
> + * File statistics from fiemap.
> + */
> +struct o2info_fiemap_stats {
> +	uint32_t blocksize;
> +	uint32_t clustersize;
> +	uint32_t num_extents;
> +	uint32_t num_extents_xattr;
> +	uint32_t clusters;
> +	float frag;
> +	float score;
> +	uint32_t shared;
> +	uint32_t holes;
> +	uint32_t unwrittens;
> +	uint32_t xattr;
> +};
> +
> +static int ul_log2(unsigned long arg)
> +{
> +	unsigned int i = 0;
> +
> +	arg >>= 1;
> +	while (arg) {
> +		i++;
> +		arg >>= 1;
> +	}
> +
> +	return i;
> +}
> +
> +static int figure_extents(int fd, uint32_t *num, int flags)
> +{
> +	int ret;
> +	static struct fiemap fiemap;
> +
> +	fiemap.fm_start = 0ULL;
> +	fiemap.fm_length = FIEMAP_MAX_OFFSET;
> +
> +	if (flags & FIEMAP_FLAG_XATTR)
> +		fiemap.fm_flags = FIEMAP_FLAG_XATTR;
> +
> +	fiemap.fm_extent_count = 0;
> +	ret = ioctl(fd, FS_IOC_FIEMAP, &fiemap);
> +	if (ret < 0) {
> +		ret = errno;
> +		tcom_err(ret, "fiemap get count error");
> +		return -1;
> +	}
> +
> +	*num = fiemap.fm_mapped_extents;
> +
> +	return 0;
> +}
> +
> +static uint32_t clusters_in_bytes(uint32_t clustersize, uint32_t bytes)
> +{
> +	uint64_t ret = bytes + clustersize - 1;
> +
> +	if (ret < bytes)
> +		ret = UINT64_MAX;
> +
> +	ret = ret >> ul_log2(clustersize);
> +	if (ret > UINT32_MAX)
> +		ret = UINT32_MAX;
> +
> +	return (uint32_t)ret;
> +}
> +
> +static int do_fiemap(int fd, int flags, struct o2info_fiemap_stats *ofs,
> +		     struct o2info_operation *op)
> +{
> +
> +	char buf[4096];
> +
> +	int ret = 0, last = 0;
> +	int cluster_shift = 0, blk_shift = 0;
> +	int count = (sizeof(buf) - sizeof(struct fiemap)) /
> +		     sizeof(struct fiemap_extent);
> +
> +	struct fiemap *fiemap = (struct fiemap *)buf;
> +	struct fiemap_extent *fm_ext = &fiemap->fm_extents[0];
> +	uint32_t num_extents = 0, extents_got = 0, i;
> +
> +	uint32_t prev_start = 0, prev_len = 0;
> +	uint32_t start = 0, len = 0, phy_pos = 0;
> +
> +	if (ofs->clustersize)
> +		cluster_shift = ul_log2(ofs->clustersize);
> +
> +	if (ofs->blocksize)
> +		blk_shift = ul_log2(ofs->blocksize);
> +
> +	memset(fiemap, 0, sizeof(*fiemap));
> +
> +	ret = figure_extents(fd, &num_extents, 0);
> +	if (ret)
> +		return -1;
> +
> +	do {
> +		fiemap->fm_length = ~0ULL;
> +		if (flags & FIEMAP_FLAG_XATTR)
> +			fiemap->fm_flags = FIEMAP_FLAG_XATTR;
> +		else
> +			fiemap->fm_flags = flags;
> +		fiemap->fm_extent_count = count;
> +
> +		ret = ioctl(fd, FS_IOC_FIEMAP, (unsigned long)fiemap);
> +		if (ret < 0) {
> +			ret = errno;
> +			if (errno == EBADR) {
> +				o2i_error(op, "fiemap failed with unsupported"
> +					  " flags %x\n", fiemap->fm_flags);
> +			} else
> +				o2i_error(op, "fiemap error: %s\n",
> +					  strerror(ret));
> +			return -1;
> +		}
> +
> +		if (!fiemap->fm_mapped_extents)
> +			break;
> +
> +		for (i = 0; i < fiemap->fm_mapped_extents; i++) {
> +
> +			start = fm_ext[i].fe_logical >> cluster_shift;
> +			len = fm_ext[i].fe_length >> cluster_shift;
> +			phy_pos = fm_ext[i].fe_physical >> blk_shift;
> +
> +			if (fiemap->fm_flags & FIEMAP_FLAG_XATTR) {
> +				ofs->xattr += len;
> +			} else {
> +				if (fm_ext[i].fe_flags &
> +				    FIEMAP_EXTENT_UNWRITTEN)
> +					ofs->unwrittens += len;
> +
> +				if (fm_ext[i].fe_flags & FIEMAP_EXTENT_SHARED)
> +					ofs->shared += len;
> +
> +				if ((prev_start + prev_len) < start)
> +					ofs->holes += start - prev_start -
> +						      prev_len;
> +			}
> +
> +			if (fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST)
> +				last = 1;
> +
> +			prev_start = start;
> +			prev_len = len;
> +
> +			extents_got++;
> +			ofs->clusters += len;
> +		}
> +
> +		fiemap->fm_start = (fm_ext[i-1].fe_logical +
> +				    fm_ext[i-1].fe_length);
> +	} while (!last);
> +
> +	if (extents_got != num_extents) {
> +		o2i_error(op, "Got wrong extents number, expected:%lu, "
> +			  "got:%lu\n", num_extents, extents_got);
> +		return -1;
> +	}
> +
> +	if (flags & FIEMAP_FLAG_XATTR)
> +		ofs->num_extents_xattr = num_extents;
> +	else
> +		ofs->num_extents = num_extents;
> +
> +	return ret;
> +}
> +
> +static int get_fiemap_stats(struct o2info_operation *op,
> +			    struct o2info_method *om,
> +			    struct o2info_fiemap_stats *ofs)
> +{
> +	int ret = 0, flags = 0;
> +	static struct o2info_volinfo vf;
> +
> +	memset(ofs, 0, sizeof(*ofs));
> +
> +	if (om->om_method == O2INFO_USE_IOCTL)
> +		ret = get_volinfo_ioctl(op, om->om_fd, &vf);
> +	else
> +		ret = get_volinfo_libocfs2(op, om->om_fs, &vf);
> +	if (ret)
> +		return -1;
> +
> +	ofs->blocksize = vf.blocksize;
> +	ofs->clustersize = vf.clustersize;
> +
> +	ret = do_fiemap(om->om_fd, flags, ofs, op);
> +	if (ret)
> +		return ret;
> +
> +	if (ofs->clusters > 1 && ofs->num_extents) {
> +		float e = ofs->num_extents, c = ofs->clusters;
> +		int clusters_per_mb = clusters_in_bytes(ofs->clustersize,
> +							OCFS2_MAX_CLUSTERSIZE);
> +		ofs->frag = 100 * (e / c);
> +		ofs->score = ofs->frag * clusters_per_mb;
> +	}
> +
> +	return ret;
> +}
> +
>   




More information about the Ocfs2-tools-devel mailing list