[Ocfs2-tools-devel] [PATCH 2/5] O2info: O2info: Add new running codes for '--freeinode'
Tristan Ye
tristan.ye at oracle.com
Tue Nov 23 02:32:38 PST 2010
Patch teaches o2info to dump fs's free inode space among nodes.
Task of '--freeinode' will also be capable of two approaches,
including libocfs2 and ioctl solutions.
Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
include/ocfs2-kernel/ocfs2_ioctl.h | 11 +++++
o2info/libo2info.c | 58 +++++++++++++++++++++++++++
o2info/libo2info.h | 11 +++++
o2info/o2info.1.in | 6 ++-
o2info/o2info.c | 15 +++++++
o2info/operations.c | 75 ++++++++++++++++++++++++++++++++++++
6 files changed, 175 insertions(+), 1 deletions(-)
diff --git a/include/ocfs2-kernel/ocfs2_ioctl.h b/include/ocfs2-kernel/ocfs2_ioctl.h
index 9bc5354..57aa718 100644
--- a/include/ocfs2-kernel/ocfs2_ioctl.h
+++ b/include/ocfs2-kernel/ocfs2_ioctl.h
@@ -142,6 +142,16 @@ struct ocfs2_info_journal_size {
__u64 ij_journal_size;
};
+struct ocfs2_info_freeinode {
+ struct ocfs2_info_request ifi_req;
+ struct ocfs2_info_local_freeinode {
+ __u64 lfi_total;
+ __u64 lfi_free;
+ } ifi_stat[OCFS2_MAX_SLOTS];
+ __u32 ifi_slotnum; /* out */
+ __u32 ifi_pad;
+};
+
/* Codes for ocfs2_info_request */
enum ocfs2_info_type {
OCFS2_INFO_CLUSTERSIZE = 1,
@@ -151,6 +161,7 @@ enum ocfs2_info_type {
OCFS2_INFO_UUID,
OCFS2_INFO_FS_FEATURES,
OCFS2_INFO_JOURNAL_SIZE,
+ OCFS2_INFO_FREEINODE,
OCFS2_INFO_NUM_TYPES
};
diff --git a/o2info/libo2info.c b/o2info/libo2info.c
index 6db04d0..912c938 100644
--- a/o2info/libo2info.c
+++ b/o2info/libo2info.c
@@ -21,6 +21,8 @@
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
+#include <inttypes.h>
+
#include "ocfs2/ocfs2.h"
#include "tools-internal/verbose.h"
#include "libo2info.h"
@@ -95,3 +97,59 @@ out:
return err;
}
+
+int o2info_get_freeinode(ocfs2_filesys *fs, struct o2info_freeinode *ofi)
+{
+
+ int ret = 0, i, j;
+ char *block = NULL;
+ uint64_t inode_alloc;
+
+ struct ocfs2_dinode *dinode_alloc = NULL;
+ struct ocfs2_chain_list *cl = NULL;
+ struct ocfs2_chain_rec *rec = NULL;
+ struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super);
+
+ ofi->slotnum = sb->s_max_slots;
+
+ ret = ocfs2_malloc_block(fs->fs_io, &block);
+ if (ret) {
+ tcom_err(ret, "while allocating block buffer");
+ goto out;
+ }
+
+ dinode_alloc = (struct ocfs2_dinode *)block;
+
+ for (i = 0; i < ofi->slotnum; i++) {
+
+ ofi->fi[i].total = ofi->fi[i].free = 0;
+
+ ret = ocfs2_lookup_system_inode(fs, INODE_ALLOC_SYSTEM_INODE,
+ i, &inode_alloc);
+ if (ret) {
+ tcom_err(ret, "while looking up the global"
+ " bitmap inode");
+ goto out;
+ }
+
+ ret = ocfs2_read_inode(fs, inode_alloc, (char *)dinode_alloc);
+ if (ret) {
+ tcom_err(ret, "reading global_bitmap inode "
+ "%"PRIu64" for stats", inode_alloc);
+ goto out;
+ }
+
+ cl = &(dinode_alloc->id2.i_chain);
+
+ for (j = 0; j < cl->cl_next_free_rec; j++) {
+ rec = &(cl->cl_recs[j]);
+ ofi->fi[i].total += rec->c_total;
+ ofi->fi[i].free += rec->c_free;
+ }
+ }
+out:
+ if (block)
+ ocfs2_free(&block);
+
+ return ret;
+}
diff --git a/o2info/libo2info.h b/o2info/libo2info.h
index 081eace..08a0500 100644
--- a/o2info/libo2info.h
+++ b/o2info/libo2info.h
@@ -40,8 +40,19 @@ struct o2info_mkfs {
uint64_t journal_size;
};
+struct o2info_local_freeinode {
+ unsigned long total;
+ unsigned long free;
+};
+
+struct o2info_freeinode {
+ int slotnum;
+ struct o2info_local_freeinode fi[OCFS2_MAX_SLOTS];
+};
+
int o2info_get_fs_features(ocfs2_filesys *fs, struct o2info_fs_features *ofs);
int o2info_get_volinfo(ocfs2_filesys *fs, struct o2info_volinfo *vf);
int o2info_get_mkfs(ocfs2_filesys *fs, struct o2info_mkfs *oms);
+int o2info_get_freeinode(ocfs2_filesys *fs, struct o2info_freeinode *ofi);
#endif
diff --git a/o2info/o2info.1.in b/o2info/o2info.1.in
index 3ddfba6..2c77457 100644
--- a/o2info/o2info.1.in
+++ b/o2info/o2info.1.in
@@ -2,7 +2,7 @@
.SH "NAME"
o2info \- Dump \fIOCFS2\fR file system information on disk.
.SH "SYNOPSIS"
-\fBo2info\fR [\fB\-C|\-\-cluster\-coherent\fR] [\fB\-\-fs\-features\fR] [\fB\-\-volinfo\fR] [\fB\-\-mkfs\fR] <\fBdevice or file\fR>
+\fBo2info\fR [\fB\-C|\-\-cluster\-coherent\fR] [\fB\-\-fs\-features\fR] [\fB\-\-volinfo\fR] [\fB\-\-mkfs\fR] [\fB\-\-freeinode\fR] <\fBdevice or file\fR>
.SH "DESCRIPTION"
.PP
@@ -27,6 +27,10 @@ Dump an original format of mkfs.ocfs's arguments, importantly, which can be used
#mkfs.ocfs2 "$(o2info --mkfs /dev/name/or/path/of/file)" /dev/sdaX
.TP
+\fB\-\-freeinode\fR
+Display free inode space for all nodes in \fIOCFS2\fR cluster.
+
+.TP
\fB\-V, \-\-version\fR
Show version and exit.
diff --git a/o2info/o2info.c b/o2info/o2info.c
index 9e23cfb..62a92f1 100644
--- a/o2info/o2info.c
+++ b/o2info/o2info.c
@@ -37,6 +37,7 @@
extern struct o2info_operation fs_features_op;
extern struct o2info_operation volinfo_op;
extern struct o2info_operation mkfs_op;
+extern struct o2info_operation freeinode_op;
static LIST_HEAD(o2info_op_task_list);
static int o2info_op_task_count;
@@ -141,6 +142,19 @@ static struct o2info_option mkfs_option = {
.opt_private = NULL,
};
+static struct o2info_option freeinode_option = {
+ .opt_option = {
+ .name = "freeinode",
+ .val = CHAR_MAX,
+ .has_arg = 0,
+ .flag = NULL,
+ },
+ .opt_help = " --freeinode",
+ .opt_handler = NULL,
+ .opt_op = &freeinode_op,
+ .opt_private = NULL,
+};
+
static struct o2info_option *options[] = {
&help_option,
&version_option,
@@ -148,6 +162,7 @@ static struct o2info_option *options[] = {
&fs_features_option,
&volinfo_option,
&mkfs_option,
+ &freeinode_option,
NULL,
};
diff --git a/o2info/operations.c b/o2info/operations.c
index f7216d8..a0e85d6 100644
--- a/o2info/operations.c
+++ b/o2info/operations.c
@@ -537,3 +537,78 @@ out:
DEFINE_O2INFO_OP(mkfs,
mkfs_run,
NULL);
+
+static int get_freeinode_ioctl(struct o2info_operation *op,
+ int fd,
+ struct o2info_freeinode *ofi)
+{
+ uint64_t reqs[1];
+ int ret = 0, flags = 0;
+ struct ocfs2_info info;
+ struct ocfs2_info_freeinode oifi;
+ uint32_t unknowns = 0, errors = 0, fills = 0;
+
+ memset(ofi, 0, sizeof(*ofi));
+
+ if (!cluster_coherent)
+ flags |= OCFS2_INFO_FL_NON_COHERENT;
+
+ o2info_fill_request((struct ocfs2_info_request *)&oifi, sizeof(oifi),
+ OCFS2_INFO_FREEINODE, flags);
+
+ reqs[0] = (unsigned long)&oifi;
+
+ info.oi_requests = (uint64_t)reqs;
+ info.oi_count = 1;
+
+ ret = ioctl(fd, OCFS2_IOC_INFO, &info);
+ if (ret) {
+ ret = errno;
+ o2i_error(op, "ioctl failed: %s\n", strerror(ret));
+ o2i_scan_requests(op, info, &unknowns, &errors, &fills);
+ goto out;
+ }
+
+ if (oifi.ifi_req.ir_flags & OCFS2_INFO_FL_FILLED) {
+ ofi->slotnum = oifi.ifi_slotnum;
+ memcpy(ofi->fi, oifi.ifi_stat,
+ sizeof(struct o2info_local_freeinode) * OCFS2_MAX_SLOTS);
+ }
+
+out:
+ return ret;
+}
+
+static int freeinode_run(struct o2info_operation *op,
+ struct o2info_method *om,
+ void *arg)
+{
+ int ret = 0, i;
+
+ struct o2info_freeinode ofi;
+ unsigned long total = 0, free = 0;
+
+ if (om->om_method == O2INFO_USE_IOCTL)
+ ret = get_freeinode_ioctl(op, om->om_fd, &ofi);
+ else
+ ret = o2info_get_freeinode(om->om_fs, &ofi);
+
+ if (ret)
+ return ret;
+
+ fprintf(stdout, "Slot\t\tSpace\t\tFree\n");
+ for (i = 0; i < ofi.slotnum ; i++) {
+ fprintf(stdout, "%3d\t%13lu\t%12lu\n", i, ofi.fi[i].total,
+ ofi.fi[i].free);
+ total += ofi.fi[i].total;
+ free += ofi.fi[i].free;
+ }
+
+ fprintf(stdout, "Total\t%13lu\t%12lu\n", total, free);
+
+ return ret;
+}
+
+DEFINE_O2INFO_OP(freeinode,
+ freeinode_run,
+ NULL);
--
1.5.5
More information about the Ocfs2-tools-devel
mailing list