[Ocfs2-tools-devel] [PATCH 11/19] Ocfs2-tools: Add utility funcs of doing fiemap statistics.
Tristan Ye
tristan.ye at oracle.com
Tue Apr 13 19:50:11 PDT 2010
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;
+}
+
--
1.5.5
More information about the Ocfs2-tools-devel
mailing list