[Ocfs2-tools-devel] [PATCH 10/11] tunefs.ocfs2: Support inline_data in tunefs.

Tao Ma tao.ma at oracle.com
Tue Jul 22 15:52:29 PDT 2008


Allow tunefs.ocfs2 to enable/disable inline_data for a formatted
volume by --fs-features like "inline-data" and "noinline-data".

Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
 tunefs.ocfs2/Makefile      |    3 +-
 tunefs.ocfs2/features.c    |   21 +++++-
 tunefs.ocfs2/inline_data.c |  171 ++++++++++++++++++++++++++++++++++++++++++++
 tunefs.ocfs2/sparse_file.c |    2 +-
 tunefs.ocfs2/tunefs.c      |    1 +
 tunefs.ocfs2/tunefs.h      |    6 ++
 6 files changed, 200 insertions(+), 4 deletions(-)
 create mode 100644 tunefs.ocfs2/inline_data.c

diff --git a/tunefs.ocfs2/Makefile b/tunefs.ocfs2/Makefile
index 8333971..c186f7c 100644
--- a/tunefs.ocfs2/Makefile
+++ b/tunefs.ocfs2/Makefile
@@ -27,7 +27,8 @@ CFILES =		\
 	sparse_file.c	\
 	features.c	\
 	resize.c	\
-	format_slotmap.c
+	format_slotmap.c \
+	inline_data.c
 
 HFILES = tunefs.h
 
diff --git a/tunefs.ocfs2/features.c b/tunefs.ocfs2/features.c
index 36307c8..b7d39e3 100644
--- a/tunefs.ocfs2/features.c
+++ b/tunefs.ocfs2/features.c
@@ -36,9 +36,11 @@ extern ocfs2_tune_opts opts;
 #define TUNEFS_RO_COMPAT_SET	OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
 #define TUNEFS_RO_COMPAT_CLEAR	OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
 #define TUNEFS_INCOMPAT_SET	(OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC | \
-				 OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP)
+				 OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP | \
+				 OCFS2_FEATURE_INCOMPAT_INLINE_DATA)
 #define TUNEFS_INCOMPAT_CLEAR	(OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC | \
-				 OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP)
+				 OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP | \
+				 OCFS2_FEATURE_INCOMPAT_INLINE_DATA)
 
 /*
  * Check whether we can add or remove a feature.
@@ -123,6 +125,14 @@ errcode_t feature_check(ocfs2_filesys *fs)
 		}
 	}
 
+	if (opts.clear_feature.incompat & OCFS2_FEATURE_INCOMPAT_INLINE_DATA) {
+		if (!ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super)))
+			goto bail;
+
+		ret = clear_inline_data_check(fs, opts.progname);
+		if (ret)
+			goto bail;
+	}
 	ret = 0;
 bail:
 	return ret;
@@ -149,6 +159,13 @@ errcode_t update_feature(ocfs2_filesys *fs)
 	    OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP)
 		ret = reformat_slot_map(fs);
 
+	if (opts.set_feature.incompat & OCFS2_FEATURE_INCOMPAT_INLINE_DATA)
+		OCFS2_SET_INCOMPAT_FEATURE(OCFS2_RAW_SB(fs->fs_super),
+					   OCFS2_FEATURE_INCOMPAT_INLINE_DATA);
+	else if (opts.clear_feature.incompat &
+		 OCFS2_FEATURE_INCOMPAT_INLINE_DATA)
+		ret = clear_inline_data_flag(fs, opts.progname);
+
 bail:
 	return ret;
 }
diff --git a/tunefs.ocfs2/inline_data.c b/tunefs.ocfs2/inline_data.c
new file mode 100644
index 0000000..25950f2
--- /dev/null
+++ b/tunefs.ocfs2/inline_data.c
@@ -0,0 +1,171 @@
+/*
+ * inline_data.c
+ *
+ * source file of inline data functions for tunefs.
+ *
+ * Copyright (C) 2008 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ */
+
+#include <ocfs2/kernel-rbtree.h>
+#include <tunefs.h>
+#include <assert.h>
+
+struct inline_file {
+	uint64_t blkno;
+	struct inline_file *next;
+};
+
+struct inline_file_list {
+	struct inline_file *files;
+	uint64_t files_num;
+};
+
+struct inline_file_list files_list;
+
+static errcode_t iterate_all_file(ocfs2_filesys *fs,
+				  char *progname)
+{
+	errcode_t ret;
+	uint64_t blkno;
+	char *buf;
+	struct ocfs2_dinode *di;
+	struct inline_file *file;
+	ocfs2_inode_scan *scan;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &buf);
+	if (ret)
+		goto out;
+
+	di = (struct ocfs2_dinode *)buf;
+
+	ret = ocfs2_open_inode_scan(fs, &scan);
+	if (ret) {
+		com_err(progname, ret, "while opening inode scan");
+		goto out_free;
+	}
+
+	for(;;) {
+		ret = ocfs2_get_next_inode(scan, &blkno, buf);
+		if (ret) {
+			com_err(progname, ret,
+				"while getting next inode");
+			break;
+		}
+		if (blkno == 0)
+			break;
+
+		if (memcmp(di->i_signature, OCFS2_INODE_SIGNATURE,
+			    strlen(OCFS2_INODE_SIGNATURE)))
+			continue;
+
+		ocfs2_swap_inode_to_cpu(di);
+
+		if (di->i_fs_generation != fs->fs_super->i_fs_generation)
+			continue;
+
+		if (!(di->i_flags & OCFS2_VALID_FL))
+			continue;
+
+		if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
+			ret = ocfs2_malloc0(sizeof(struct inline_file), &file);
+			if (ret)
+				break;
+
+			files_list.files_num++;
+			file->blkno = di->i_blkno;
+			file->next = files_list.files;
+			files_list.files = file;
+		}
+	}
+
+	ocfs2_close_inode_scan(scan);
+out_free:
+	ocfs2_free(&buf);
+
+out:
+	return ret;
+}
+
+errcode_t clear_inline_data_check(ocfs2_filesys *fs, char *progname)
+{
+	errcode_t ret;
+	uint32_t free_clusters;
+
+	memset(&files_list, 0, sizeof(files_list));
+
+	ret = iterate_all_file(fs, progname);
+	if (ret)
+		goto bail;
+
+	ret = get_total_free_clusters(fs, &free_clusters);
+	if (ret)
+		goto bail;
+
+	printf("We have %u clusters free and need %"PRIu64" clusters "
+	       "for inline data\n", free_clusters, files_list.files_num);
+
+	if (free_clusters < files_list.files_num) {
+		com_err(progname, 0, "Don't have enough free space.");
+		ret = OCFS2_ET_NO_SPACE;
+	}
+bail:
+	return ret;
+}
+
+errcode_t clear_inline_data_flag(ocfs2_filesys *fs, char *progname)
+{
+	errcode_t ret = 0;
+	struct inline_file *file = files_list.files;
+	ocfs2_cached_inode *ci = NULL;
+
+	while (file) {
+		ret = ocfs2_read_cached_inode(fs, file->blkno, &ci);
+		if (ret)
+			goto bail;
+
+		ret = ocfs2_convert_inline_data_to_extents(ci);
+		if (ret)
+			goto bail;
+
+		file = file->next;
+	}
+
+	if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super)))
+		OCFS2_CLEAR_INCOMPAT_FEATURE(OCFS2_RAW_SB(fs->fs_super),
+					 OCFS2_FEATURE_INCOMPAT_INLINE_DATA);
+
+bail:
+	if (ci)
+		ocfs2_free_cached_inode(fs, ci);
+	free_inline_data_ctxt();
+	return ret;
+}
+
+void free_inline_data_ctxt(void)
+{
+	struct inline_file *file = files_list.files, *next;
+
+	while (file) {
+		next = file->next;
+		ocfs2_free(&file);
+		file = next;
+	}
+
+	files_list.files = NULL;
+}
diff --git a/tunefs.ocfs2/sparse_file.c b/tunefs.ocfs2/sparse_file.c
index e068524..c890ff9 100644
--- a/tunefs.ocfs2/sparse_file.c
+++ b/tunefs.ocfs2/sparse_file.c
@@ -163,7 +163,7 @@ out:
 	return ret;
 }
 
-static errcode_t get_total_free_clusters(ocfs2_filesys *fs, uint32_t *clusters)
+errcode_t get_total_free_clusters(ocfs2_filesys *fs, uint32_t *clusters)
 {
 	errcode_t ret;
 	uint64_t blkno;
diff --git a/tunefs.ocfs2/tunefs.c b/tunefs.ocfs2/tunefs.c
index 6d52062..1924bb2 100644
--- a/tunefs.ocfs2/tunefs.c
+++ b/tunefs.ocfs2/tunefs.c
@@ -1596,6 +1596,7 @@ close:
 	block_signals(SIG_UNBLOCK);
 
 	free_clear_ctxt();
+	free_inline_data_ctxt();
 
 	free_opts();
 
diff --git a/tunefs.ocfs2/tunefs.h b/tunefs.ocfs2/tunefs.h
index c7b4acf..430b5c5 100644
--- a/tunefs.ocfs2/tunefs.h
+++ b/tunefs.ocfs2/tunefs.h
@@ -123,4 +123,10 @@ int validate_vol_size(ocfs2_filesys *fs);
 errcode_t online_resize_check(ocfs2_filesys *fs);
 errcode_t online_resize_lock(ocfs2_filesys *fs);
 errcode_t online_resize_unlock(ocfs2_filesys *fs);
+
+errcode_t get_total_free_clusters(ocfs2_filesys *fs, uint32_t *clusters);
+
+errcode_t clear_inline_data_check(ocfs2_filesys *fs, char *progname);
+errcode_t clear_inline_data_flag(ocfs2_filesys *fs, char *progname);
+void free_inline_data_ctxt(void);
 #endif /* _TUNEFS_H */
-- 
1.5.4.GIT




More information about the Ocfs2-tools-devel mailing list