[Ocfs2-tools-devel] [PATCH 1/7] Move feature string parsing out of mkfs.ocfs2, take 3

Tao Ma tao.ma at oracle.com
Sun Nov 4 23:38:49 PST 2007


tunfs.ocfs2 now also have to parse the feature-strings,
so move the feature string parsing out of mkfs.ocfs2 and create
a new file named feature_string.c in libocfs2 to handle this work.
Now tunefs.ocfs2 can also use it.

Signed-off-by: Tao Ma <tao.ma at oracle.com>
Signed-off-by: Mark Fasheh <mark.fasheh at oracle.com>
---
 libocfs2/Makefile                 |    6 +-
 libocfs2/feature_string.c         |  234 +++++++++++++++++++++++++++++++++++
 libocfs2/include/feature_string.h |   67 ++++++++++
 mkfs.ocfs2/mkfs.c                 |  247 +++----------------------------------
 mkfs.ocfs2/mkfs.h                 |   10 +--
 5 files changed, 322 insertions(+), 242 deletions(-)
 create mode 100644 libocfs2/feature_string.c
 create mode 100644 libocfs2/include/feature_string.h

diff --git a/libocfs2/Makefile b/libocfs2/Makefile
index cfbce83..18d255b 100644
--- a/libocfs2/Makefile
+++ b/libocfs2/Makefile
@@ -81,7 +81,8 @@ CFILES = 		\
 	unix_io.c	\
 	unlink.c	\
 	lockid.c	\
-	backup_super.c
+	backup_super.c	\
+	feature_string.c
 
 HFILES =				\
 	include/bitmap.h		\
@@ -96,7 +97,8 @@ HFILES =				\
 	include/ocfs1_fs_compat.h	\
 	include/ocfs2_lockid.h		\
 	include/ocfs2_fs.h		\
-	include/ocfs2.h
+	include/ocfs2.h			\
+	include/feature_string.h
 
 HFILES_GEN =		\
 	include/ocfs2_err.h
diff --git a/libocfs2/feature_string.c b/libocfs2/feature_string.c
new file mode 100644
index 0000000..40720b8
--- /dev/null
+++ b/libocfs2/feature_string.c
@@ -0,0 +1,234 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * feature_strings.c
+ *
+ * Routines for analyzing a feature string.
+ *
+ * Copyright (C) 2007 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, version 2,  as published by the Free Software Foundation.
+ *
+ * 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 <feature_string.h>
+
+struct feature_level_translation {
+	const char *fl_str;
+	enum feature_level_indexes fl_type;
+};
+
+static struct feature_level_translation ocfs2_feature_levels_table[] = {
+	{"default", FEATURE_LEVEL_DEFAULT},
+	{"max-compat", FEATURE_LEVEL_MAX_COMPAT},
+	{"max-features", FEATURE_LEVEL_MAX_FEATURES},
+	{NULL, FEATURE_LEVEL_DEFAULT},
+};
+
+static fs_options feature_level_defaults[] = {
+	{OCFS2_FEATURE_COMPAT_BACKUP_SB,
+	 OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC,
+	 0},  /* FEATURE_LEVEL_DEFAULT */
+
+	{OCFS2_FEATURE_COMPAT_BACKUP_SB,
+	 0,
+	 0}, /* FEATURE_LEVEL_MAX_COMPAT */
+
+	{OCFS2_FEATURE_COMPAT_BACKUP_SB,
+	 OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC,
+	 OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* FEATURE_LEVEL_MAX_FEATURES */
+};
+
+static struct fs_feature_flags ocfs2_supported_features[] = {
+	{
+		"local",
+		{0, OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT, 0},
+		{0, OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT, 0},
+	},
+	{
+		"sparse",
+		{0, OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, 0},
+		{0, OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, 0},
+	},
+	{
+		"backup-super",
+		{OCFS2_FEATURE_COMPAT_BACKUP_SB, 0, 0},
+		{OCFS2_FEATURE_COMPAT_BACKUP_SB, 0, 0},
+	},
+	{
+		"unwritten",
+		{0, 0, OCFS2_FEATURE_RO_COMPAT_UNWRITTEN},
+		{0, OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC,
+		 OCFS2_FEATURE_RO_COMPAT_UNWRITTEN},
+	},
+	{
+		NULL,
+		{0, 0, 0},
+		{0, 0, 0}
+	},
+};
+
+static inline void merge_features(fs_options *features,
+				  fs_options new_features)
+{
+	features->compat |= new_features.compat;
+	features->incompat |= new_features.incompat;
+	features->ro_compat |= new_features.ro_compat;
+}
+
+/* Get the feature level according to the value set by "--fs-feature-level". */
+int parse_feature_level(const char *typestr,
+			 enum feature_level_indexes *index)
+{
+	int i;
+
+	for(i = 0; ocfs2_feature_levels_table[i].fl_str; i++) {
+		if (strcmp(typestr,
+			  ocfs2_feature_levels_table[i].fl_str) == 0) {
+			*index = ocfs2_feature_levels_table[i].fl_type;
+			break;
+		}
+	}
+
+	if (!ocfs2_feature_levels_table[i].fl_str) {
+		return OCFS2_ET_UNSUPP_FEATURE;
+	}
+
+	return 0;
+}
+
+static int check_feature_flags(fs_options *fs_flags,
+			       fs_options *fs_r_flags)
+{
+	int ret = 1;
+
+	if (fs_r_flags->compat &&
+	    fs_flags->compat & fs_r_flags->compat)
+		ret = 0;
+	else if (fs_r_flags->incompat &&
+		 fs_flags->incompat & fs_r_flags->incompat)
+		ret = 0;
+	else if (fs_r_flags->ro_compat &&
+		 fs_flags->ro_compat & fs_r_flags->ro_compat)
+		ret = 0;
+
+	return ret;
+}
+
+/*
+ * Check and Merge all the diffent features set by the user.
+ *
+ * index: the feature level.
+ * feature_set: all the features a user set by "--fs-features".
+ * reverse_set: all the features a user want to clear by "--fs-features".
+ */
+int merge_feature_flags_with_level(fs_options *dest,
+				   int index,
+				   fs_options *feature_set,
+				   fs_options *reverse_set)
+{
+	int i;
+	fs_options level_set = feature_level_defaults[index];
+	/*
+	 * "Check whether the user asked for a flag to be set and cleared,
+	 * which is illegal. The feature_set and reverse_set are both set
+	 * by "--fs-features", so they shouldn't collide with each other.
+	 */
+	if (!check_feature_flags(feature_set, reverse_set))
+		return 0;
+
+	/* Now combine all the features the user has set. */
+	*dest = level_set;
+	merge_features(dest, *feature_set);
+
+	/*
+	 * We have to remove all the features in the reverse set
+	 * and other features which depend on them.
+	 */
+	for(i = 0; ocfs2_supported_features[i].ff_str; i++) {
+		if ((reverse_set->compat &
+			ocfs2_supported_features[i].ff_flags.compat) ||
+		    (reverse_set->incompat &
+			ocfs2_supported_features[i].ff_flags.incompat) ||
+		    (reverse_set->ro_compat &
+			ocfs2_supported_features[i].ff_flags.ro_compat)) {
+			dest->compat &=
+			~ocfs2_supported_features[i].ff_own_flags.compat;
+
+			dest->incompat &=
+			~ocfs2_supported_features[i].ff_own_flags.incompat;
+
+			dest->ro_compat &=
+			~ocfs2_supported_features[i].ff_own_flags.ro_compat;
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * Parse the feature string.
+ *
+ * For those the user want to clear(with "no" in the beginning),
+ * they are stored in "reverse_flags".
+ *
+ * For those the user want to set, they are stored in "feature_flags".
+ */
+errcode_t parse_feature(const char *opts,
+		        fs_options *feature_flags,
+		        fs_options *reverse_flags)
+{
+	char *options, *token, *next, *p, *arg;
+	int i, reverse = 0;
+
+	memset(feature_flags, 0, sizeof(fs_options));
+	memset(reverse_flags, 0, sizeof(fs_options));
+
+	options = strdup(opts);
+	for (token = options; token && *token; token = next) {
+		reverse = 0;
+		p = strchr(token, ',');
+		next = NULL;
+
+		if (p) {
+			*p = '\0';
+			next = p + 1;
+		}
+
+		arg = strstr(token, "no");
+		if (arg && arg == token) {
+			reverse = 1;
+			token += 2;
+		}
+
+		for(i = 0; ocfs2_supported_features[i].ff_str; i++) {
+			if (strcmp(token,
+				   ocfs2_supported_features[i].ff_str) == 0) {
+				if (!reverse)
+					merge_features(feature_flags,
+					ocfs2_supported_features[i].ff_flags);
+				else
+					merge_features(reverse_flags,
+					ocfs2_supported_features[i].ff_own_flags);
+				break;
+			}
+		}
+		if (!ocfs2_supported_features[i].ff_str)
+			return OCFS2_ET_UNSUPP_FEATURE;
+	}
+
+	free(options);
+
+	return 0;
+}
diff --git a/libocfs2/include/feature_string.h b/libocfs2/include/feature_string.h
new file mode 100644
index 0000000..b8e860d
--- /dev/null
+++ b/libocfs2/include/feature_string.h
@@ -0,0 +1,67 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * feature_strings.h
+ *
+ * Routines for analyzing a feature string.
+ *
+ * Copyright (C) 2007 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, version 2,  as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __FEATURE_STRING_H
+#define __FEATURE_STRING_H
+
+#include <ocfs2.h>
+
+typedef struct _fs_options fs_options;
+
+struct _fs_options {
+	uint32_t compat;
+	uint32_t incompat;
+	uint32_t ro_compat;
+};
+
+struct fs_feature_flags {
+	const char *ff_str;
+	/* this flag is the feature's own flag. */
+	fs_options ff_own_flags;
+	/*
+	 * this flag includes the feature's own flag and
+	 * all the other features' flag it depends on.
+	 */
+	fs_options ff_flags;
+};
+
+enum feature_level_indexes {
+	FEATURE_LEVEL_DEFAULT = 0,
+	FEATURE_LEVEL_MAX_COMPAT,
+	FEATURE_LEVEL_MAX_FEATURES,
+};
+
+errcode_t parse_feature(const char *opts,
+			fs_options *feature_flags,
+			fs_options *reverse_flags);
+
+int parse_feature_level(const char *typestr,
+			enum feature_level_indexes *index);
+
+int merge_feature_flags_with_level(fs_options *dest,
+				   int index,
+				   fs_options *feature_set,
+				   fs_options *reverse_set);
+#endif /* __FEATURE_STIRNG_H */
diff --git a/mkfs.ocfs2/mkfs.c b/mkfs.ocfs2/mkfs.c
index 77bc6b7..0ade0ab 100644
--- a/mkfs.ocfs2/mkfs.c
+++ b/mkfs.ocfs2/mkfs.c
@@ -120,78 +120,6 @@ enum {
 	FEATURES_OPTION,
 };
 
-struct fs_feature_flags {
-	const char *ff_str;
-	/* this flag is the feature's own flag. */
-	fs_options ff_own_flags;
-	/*
-	 * this flag includes the feature's own flag and
-	 * all the other features' flag it depends on.
-	 */
-	fs_options ff_flags;
-};
-
-static struct fs_feature_flags ocfs2_supported_features[] = {
-	{
-		"local",
-		{0, OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT, 0},
-		{0, OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT, 0},
-	},
-	{
-		"sparse",
-		{0, OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, 0},
-		{0, OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, 0},
-	},
-	{
-		"backup-super",
-		{OCFS2_FEATURE_COMPAT_BACKUP_SB, 0, 0},
-		{OCFS2_FEATURE_COMPAT_BACKUP_SB, 0, 0},
-	},
-	{
-		"unwritten",
-		{0, 0, OCFS2_FEATURE_RO_COMPAT_UNWRITTEN},
-		{0, OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC,
-		 OCFS2_FEATURE_RO_COMPAT_UNWRITTEN},
-	},
-	{
-		NULL,
-		{0, 0, 0},
-		{0, 0, 0}
-	},
-};
-
-enum feature_level_indexes {
-	FEATURE_LEVEL_DEFAULT = 0,
-	FEATURE_LEVEL_MAX_COMPAT,
-	FEATURE_LEVEL_MAX_FEATURES,
-};
-
-struct feature_level_translation {
-	const char *fl_str;
-	enum feature_level_indexes fl_type;
-};
-
-static struct feature_level_translation ocfs2_feature_levels_table[] = {
-	{"default", FEATURE_LEVEL_DEFAULT},
-	{"max-compat", FEATURE_LEVEL_MAX_COMPAT},
-	{"max-features", FEATURE_LEVEL_MAX_FEATURES},
-	{NULL, FEATURE_LEVEL_DEFAULT},
-};
-
-static fs_options feature_level_defaults[] = {
-	{OCFS2_FEATURE_COMPAT_BACKUP_SB,
-	 OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC,
-	 0},  /* FEATURE_LEVEL_DEFAULT */
-
-	{OCFS2_FEATURE_COMPAT_BACKUP_SB,
-	 0,
-	 0}, /* FEATURE_LEVEL_MAX_COMPAT */
-
-	{OCFS2_FEATURE_COMPAT_BACKUP_SB,
-	 OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC,
-	 OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* FEATURE_LEVEL_MAX_FEATURES */
-};
-
 static uint64_t align_bytes_to_clusters_ceil(State *s,
 					     uint64_t bytes)
 {
@@ -579,159 +507,6 @@ parse_fs_type_opts(char *progname, const char *typestr,
 	}
 }
 
-/* Get the feature level according to the value set by "--fs-feature-level". */
-static void parse_feature_level_opts(char *progname, const char *typestr,
-				     enum feature_level_indexes *index)
-{
-	int i;
-
-	for(i = 0; ocfs2_feature_levels_table[i].fl_str; i++) {
-		if (strcmp(typestr,
-			  ocfs2_feature_levels_table[i].fl_str) == 0) {
-			*index = ocfs2_feature_levels_table[i].fl_type;
-			break;
-		}
-	}
-
-	if (!ocfs2_feature_levels_table[i].fl_str) {
-		com_err(progname, 0,
-			"unrecognized fs-feature-level:%s", typestr);
-		exit(1);
-	}
-}
-
-static void inline merge_features(fs_options *features,
-				  fs_options new_features)
-{
-	features->compat |= new_features.compat;
-	features->incompat |= new_features.incompat;
-	features->ro_compat |= new_features.ro_compat;
-}
-
-/*
- * Parse the feature string set by the user in "--fs-features".
- * for all the features the user want to set, they are added into
- * the "feature_flags". For those the user want to clear(with "no"
- * in the beginning), they are stored in the "reverse_flags".
- */
-static void parse_feature_opts(char *progname, const char *opts,
-			       fs_options *feature_flags,
-			       fs_options *reverse_flags)
-{
-	char *options, *token, *next, *p, *arg;
-	int i, reverse = 0;
-
-	memset(feature_flags, 0, sizeof(fs_options));
-	memset(reverse_flags, 0, sizeof(fs_options));
-
-	options = strdup(opts);
-	for (token = options; token && *token; token = next) {
-		reverse = 0;
-		p = strchr(token, ',');
-		next = NULL;
-
-		if (p) {
-			*p = '\0';
-			next = p + 1;
-		}
-
-		arg = strstr(token, "no");
-		if (arg && arg == token) {
-			reverse = 1;
-			token += 2;
-		}
-
-		for(i = 0; ocfs2_supported_features[i].ff_str; i++) {
-			if (strcmp(token,
-				   ocfs2_supported_features[i].ff_str) == 0) {
-				if (!reverse)
-					merge_features(feature_flags,
-					ocfs2_supported_features[i].ff_flags);
-				else
-					merge_features(reverse_flags,
-					ocfs2_supported_features[i].ff_own_flags);
-				break;
-			}
-		}
-		if (!ocfs2_supported_features[i].ff_str) {
-			com_err(progname, 0,
-				"unrecognized fs-feature-string:%s", token);
-			exit(1);
-		}
-	}
-
-	free(options);
-}
-
-static int check_feature_flags(fs_options *fs_flags,
-			       fs_options *fs_r_flags)
-{
-	int ret = 1;
-
-	if (fs_r_flags->compat &&
-	    fs_flags->compat & fs_r_flags->compat)
-		ret = 0;
-	else if (fs_r_flags->incompat &&
-		 fs_flags->incompat & fs_r_flags->incompat)
-		ret = 0;
-	else if (fs_r_flags->ro_compat &&
-		 fs_flags->ro_compat & fs_r_flags->ro_compat)
-		ret = 0;
-
-	return ret;
-}
-
-/*
- * Check and Merge all the diffent features set by the user.
- *
- * level_set: all the features a user set by choose a feature level.
- * feature_set: all the features a user set by "--fs-features".
- * reverse_set: all the features a user want to clear by "--fs-features".
- */
-static int merge_feature_flags_with_level(State *s,
-					  fs_options *level_set,
-					  fs_options *feature_set,
-					  fs_options *reverse_set)
-{
-	int i;
-
-	/*
-	 * "Check whether the user asked for a flag to be set and cleared,
-	 * which is illegal. The feature_set and reverse_set are both set
-	 * by "--fs-features", so they shouldn't collide with each other.
-	 */
-	if (!check_feature_flags(feature_set, reverse_set))
-		return 0;
-
-	/* Now combine all the features the user has set. */
-	s->feature_flags = *level_set;
-	merge_features(&s->feature_flags, *feature_set);
-
-	/*
-	 * We have to remove all the features in the reverse set
-	 * and other features which depend on them.
-	 */
-	for(i = 0; ocfs2_supported_features[i].ff_str; i++) {
-		if ((reverse_set->compat &
-			ocfs2_supported_features[i].ff_flags.compat) ||
-		    (reverse_set->incompat &
-			ocfs2_supported_features[i].ff_flags.incompat) ||
-		    (reverse_set->ro_compat &
-			ocfs2_supported_features[i].ff_flags.ro_compat)) {
-			s->feature_flags.compat &=
-	    		~ocfs2_supported_features[i].ff_own_flags.compat;
-
-			s->feature_flags.incompat &=
-	    		~ocfs2_supported_features[i].ff_own_flags.incompat;
-
-			s->feature_flags.ro_compat &=
-	    		~ocfs2_supported_features[i].ff_own_flags.ro_compat;
-		}
-	}
-
-	return 1;
-}
-
 static State *
 get_state(int argc, char **argv)
 {
@@ -905,14 +680,23 @@ get_state(int argc, char **argv)
 			break;
 
 		case FEATURE_LEVEL:
-			parse_feature_level_opts(progname, optarg,
-						 &index);
+			ret = parse_feature_level(optarg, &index);
+			if (ret) {
+				com_err(progname, ret,
+					"when parsing fs-feature-level string");
+				exit(1);
+			}
 			break;
 
 		case FEATURES_OPTION:
-			parse_feature_opts(progname, optarg,
-					      &feature_flags,
-					      &reverse_flags);
+			ret = parse_feature(optarg,
+					    &feature_flags,
+					    &reverse_flags);
+			if (ret) {
+				com_err(progname, ret,
+					"when parsing fs-features string");
+				exit(1);
+			}
 			break;
 
 		default:
@@ -977,7 +761,8 @@ get_state(int argc, char **argv)
 
 	s->fs_type = fs_type;
 
-	if(!merge_feature_flags_with_level(s, &feature_level_defaults[index],
+	if(!merge_feature_flags_with_level(&s->feature_flags,
+					   index,
 					   &feature_flags, &reverse_flags)) {
 		com_err(s->progname, 0,
 			"Incompatible feature flags"
diff --git a/mkfs.ocfs2/mkfs.h b/mkfs.ocfs2/mkfs.h
index cd1b5f3..5cef74a 100644
--- a/mkfs.ocfs2/mkfs.h
+++ b/mkfs.ocfs2/mkfs.h
@@ -56,7 +56,7 @@
 #include <libgen.h>
 
 #include "jbd.h"
-
+#include <feature_string.h>
 
 #ifndef MAX
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
@@ -193,14 +193,6 @@ struct _DirData {
 	SystemFileDiskRecord *record;
 };
 
-typedef struct _fs_options fs_options;
-
-struct _fs_options {
-	uint32_t compat;
-	uint32_t incompat;
-	uint32_t ro_compat;
-};
-
 typedef struct _State State;
 
 struct _State {
-- 
1.5.3.2.g4f337



More information about the Ocfs2-tools-devel mailing list