[Ocfs2-tools-devel] [PATCH 2/5] O2info: O2info: Add new running codes for '--freeinode'

Tristan Ye tristan.ye at oracle.com
Sat Jan 29 22:31:25 PST 2011


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