[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