[Ocfs2-tools-devel] [PATCH 02/24] libocfs2: Add ocfs2_feature_foreach()
Joel Becker
joel.becker at oracle.com
Wed Aug 13 15:56:57 PDT 2008
The ocfs2_parse_feature() function will include dependent features when
used. For example, if you ask it to parse "unwritten", it will return a
feature set that includes both unwritten extents and sparse files,
because unwritten extents depends on sparse files. The same is true in
reverse. If you ask it "nosparse", it will return a reverse set that
includes sparse files and every thing that depends on it.
However, the caller has no way of knowing which feature needs to be
added or removed first. A naively ordered program might try to add
unwritten extents before sparse files. That will fail.
We introduce ocfs2_feature_foreach() and
ocfs2_feature_reverse_foreach(). These functions take a feature set and
iterate over it, calling a supplied callback once per feature. The
former function does it in "set" order, the latter obviously in "clear"
or reverse order.
Signed-off-by: Joel Becker <joel.becker at oracle.com>
Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
include/ocfs2/ocfs2.h | 15 ++++++
libocfs2/feature_string.c | 110 ++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 119 insertions(+), 6 deletions(-)
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index ba36316..84a2a94 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -655,6 +655,21 @@ errcode_t ocfs2_merge_feature_flags_with_level(ocfs2_fs_options *dest,
ocfs2_fs_options *feature_set,
ocfs2_fs_options *reverse_set);
+/*
+ * Get a callback with each feature in feature_set in order. This will
+ * calculate the dependencies of each feature in feature_set, then call func
+ * once per feature, with only that feature passed to func.
+ */
+void ocfs2_feature_foreach(ocfs2_fs_options *feature_set,
+ int (*func)(ocfs2_fs_options *feature,
+ void *user_data),
+ void *user_data);
+/* The reverse function. It will call the features in reverse order. */
+void ocfs2_feature_reverse_foreach(ocfs2_fs_options *reverse_set,
+ int (*func)(ocfs2_fs_options *feature,
+ void *user_data),
+ void *user_data);
+
/* These are deprecated names - don't use them */
int ocfs2_get_backup_super_offset(ocfs2_filesys *fs,
diff --git a/libocfs2/feature_string.c b/libocfs2/feature_string.c
index 359e021..7eef83e 100644
--- a/libocfs2/feature_string.c
+++ b/libocfs2/feature_string.c
@@ -150,6 +150,16 @@ static int check_feature_flags(ocfs2_fs_options *fs_flags,
return ret;
}
+static int feature_match(ocfs2_fs_options *a, ocfs2_fs_options *b)
+{
+ if ((a->opt_compat & b->opt_compat) ||
+ (a->opt_incompat & b->opt_incompat) ||
+ (a->opt_ro_compat & b->opt_ro_compat))
+ return 1;
+
+ return 0;
+}
+
/*
* If we are asked to clear a feature, we also need to clear any other
* features that depend on it.
@@ -159,12 +169,8 @@ static void ocfs2_feature_clear_deps(ocfs2_fs_options *reverse_set)
int i;
for(i = 0; ocfs2_supported_features[i].ff_str; i++) {
- if ((reverse_set->opt_compat &
- ocfs2_supported_features[i].ff_flags.opt_compat) ||
- (reverse_set->opt_incompat &
- ocfs2_supported_features[i].ff_flags.opt_incompat) ||
- (reverse_set->opt_ro_compat &
- ocfs2_supported_features[i].ff_flags.opt_ro_compat)) {
+ if (feature_match(reverse_set,
+ &ocfs2_supported_features[i].ff_flags)) {
merge_features(reverse_set,
ocfs2_supported_features[i].ff_own_flags);
}
@@ -271,6 +277,71 @@ errcode_t ocfs2_parse_feature(const char *opts,
return 0;
}
+static int compare_feature_forward(const void *pa, const void *pb)
+{
+ int ia = *(int *)pa;
+ int ib = *(int *)pb;
+ struct fs_feature_flags *fa = &ocfs2_supported_features[ia];
+ struct fs_feature_flags *fb = &ocfs2_supported_features[ib];
+
+ if (feature_match(&fb->ff_flags,
+ &fa->ff_own_flags))
+ return -1;
+ if (feature_match(&fa->ff_flags,
+ &fb->ff_own_flags))
+ return 1;
+ return 0;
+}
+
+static int compare_feature_backward(const void *pa, const void *pb)
+{
+ return compare_feature_forward(pb, pa);
+}
+
+static void __feature_foreach(int reverse, ocfs2_fs_options *feature_set,
+ int (*func)(ocfs2_fs_options *feature,
+ void *user_data),
+ void *user_data)
+{
+ int i, index;
+ int num_features = sizeof(ocfs2_supported_features) /
+ sizeof(ocfs2_supported_features[0]);
+ int indices[num_features];
+
+ index = 0;
+ for (i = 0; ocfs2_supported_features[i].ff_str; i++) {
+ if (feature_match(feature_set,
+ &ocfs2_supported_features[i].ff_own_flags)) {
+ indices[index] = i;
+ index++;
+ }
+ }
+
+ qsort(indices, index, sizeof(indices[0]),
+ reverse ? compare_feature_backward : compare_feature_forward);
+
+ for (i = 0; i < index; i++) {
+ if (func(&ocfs2_supported_features[indices[i]].ff_own_flags,
+ user_data))
+ break;
+ }
+}
+
+void ocfs2_feature_foreach(ocfs2_fs_options *feature_set,
+ int (*func)(ocfs2_fs_options *feature,
+ void *user_data),
+ void *user_data)
+{
+ __feature_foreach(0, feature_set, func, user_data);
+}
+
+void ocfs2_feature_reverse_foreach(ocfs2_fs_options *reverse_set,
+ int (*func)(ocfs2_fs_options *feature,
+ void *user_data),
+ void *user_data)
+{
+ __feature_foreach(1, reverse_set, func, user_data);
+}
#ifdef DEBUG_EXE
@@ -305,6 +376,30 @@ static void print_features(char *desc, ocfs2_fs_options *feature_set)
ocfs2_supported_features[i].ff_own_flags.opt_incompat)
fprintf(stdout, " %s",
ocfs2_supported_features[i].ff_str);
+ fprintf(stdout, "\n");
+}
+
+static int p_feature(ocfs2_fs_options *feature_set, void *user_data)
+{
+ int i;
+
+ for (i = 0; ocfs2_supported_features[i].ff_str; i++) {
+ if (feature_match(feature_set,
+ &ocfs2_supported_features[i].ff_own_flags))
+ fprintf(stdout, " %s",
+ ocfs2_supported_features[i].ff_str);
+ }
+
+ return 0;
+}
+
+static void print_order(int reverse, ocfs2_fs_options *feature_set)
+{
+ fprintf(stdout, "In this order:");
+ if (reverse)
+ ocfs2_feature_reverse_foreach(feature_set, p_feature, NULL);
+ else
+ ocfs2_feature_foreach(feature_set, p_feature, NULL);
fprintf(stdout, "\n\n");
}
@@ -373,10 +468,13 @@ int main(int argc, char *argv[])
print_features("\nmkfs.ocfs2 would set these features",
&mkfs_features);
+ print_order(0, &mkfs_features);
print_features("tunefs.ocfs2 would set these features",
&set_features);
+ print_order(0, &set_features);
print_features("tunefs.ocfs2 would clear these features",
&clear_features);
+ print_order(1, &clear_features);
return 0;
}
--
1.5.6.3
More information about the Ocfs2-tools-devel
mailing list