diff options
author | Andreas Dilger <adilger@sun.com> | 2008-08-23 21:42:46 -0600 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-08-24 21:31:52 -0400 |
commit | 03efde8abe79c80ff369206d06d4f1e476b08f53 (patch) | |
tree | 38fbb40a61b67a044cae622b79e5545af994aeb7 | |
parent | 28b74daa10bfd4e6d908ca030a9d9c5b8269a26c (diff) | |
download | e2fsprogs-03efde8abe79c80ff369206d06d4f1e476b08f53.tar.gz |
add debugfs command to print known features
Print out the currently supported features of e2fsprogs/libext2fs
via a new "debugfs supported_features" command. This helps scripts
to know whether it is possible to try and enable specific features
in the filesystem.
Signed-off-by: Kalpak Shah <kalpak.shah@sun.com>
Signed-off-by: Andreas Dilger <adilger@sun.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r-- | debugfs/debug_cmds.ct | 3 | ||||
-rw-r--r-- | debugfs/debugfs.c | 66 | ||||
-rw-r--r-- | lib/e2p/Makefile.in | 10 | ||||
-rw-r--r-- | lib/e2p/e2p.h | 3 | ||||
-rw-r--r-- | lib/e2p/feature.c | 130 |
5 files changed, 210 insertions, 2 deletions
diff --git a/debugfs/debug_cmds.ct b/debugfs/debug_cmds.ct index a4a5a4c1..59314b81 100644 --- a/debugfs/debug_cmds.ct +++ b/debugfs/debug_cmds.ct @@ -154,5 +154,8 @@ request do_dump_unused, "Dump unused blocks", request do_set_current_time, "Set current time to use when setting filesystme fields", set_current_time; +request do_supported_features, "Print features supported by this version of e2fsprogs", + supported_features; + end; diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c index 935df812..620a513c 100644 --- a/debugfs/debugfs.c +++ b/debugfs/debugfs.c @@ -36,6 +36,7 @@ extern char *optarg; #include <ext2fs/ext2_ext_attr.h> #include "../version.h" +#include "jfs_user.h" extern ss_request_table debug_cmds; ss_request_table *extra_cmds; @@ -1806,6 +1807,71 @@ void do_set_current_time(int argc, char *argv[]) } } +static int find_supp_feature(__u32 *supp, int feature_type, char *name) +{ + int compat, bit, ret; + unsigned int feature_mask; + + if (name) { + if (feature_type == E2P_FS_FEATURE) + ret = e2p_string2feature(name, &compat, &feature_mask); + else + ret = e2p_jrnl_string2feature(name, &compat, + &feature_mask); + if (ret) + return ret; + + if (!(supp[compat] & feature_mask)) + return 1; + } else { + for (compat = 0; compat < 3; compat++) { + for (bit = 0, feature_mask = 1; bit < 32; + bit++, feature_mask <<= 1) { + if (supp[compat] & feature_mask) { + if (feature_type == E2P_FS_FEATURE) + fprintf(stdout, " %s", + e2p_feature2string(compat, + feature_mask)); + else + fprintf(stdout, " %s", + e2p_jrnl_feature2string(compat, + feature_mask)); + } + } + } + fprintf(stdout, "\n"); + } + + return 0; +} + +void do_supported_features(int argc, char *argv[]) +{ + int i, j, ret; + __u32 supp[3] = { EXT2_LIB_FEATURE_COMPAT_SUPP, + EXT2_LIB_FEATURE_INCOMPAT_SUPP, + EXT2_LIB_FEATURE_RO_COMPAT_SUPP }; + __u32 jrnl_supp[3] = { JFS_KNOWN_COMPAT_FEATURES, + JFS_KNOWN_INCOMPAT_FEATURES, + JFS_KNOWN_ROCOMPAT_FEATURES }; + + if (argc > 1) { + ret = find_supp_feature(supp, E2P_FS_FEATURE, argv[1]); + if (ret) { + ret = find_supp_feature(jrnl_supp, E2P_JOURNAL_FEATURE, + argv[1]); + } + if (ret) + com_err(argv[0], 0, "Unknown feature: %s\n", argv[1]); + else + fprintf(stdout, "Supported feature: %s\n", argv[1]); + } else { + fprintf(stdout, "Supported features:"); + ret = find_supp_feature(supp, E2P_FS_FEATURE, NULL); + ret = find_supp_feature(jrnl_supp, E2P_JOURNAL_FEATURE, NULL); + } +} + static int source_file(const char *cmd_file, int sci_idx) { FILE *f; diff --git a/lib/e2p/Makefile.in b/lib/e2p/Makefile.in index 65574802..2c56ab5f 100644 --- a/lib/e2p/Makefile.in +++ b/lib/e2p/Makefile.in @@ -69,8 +69,14 @@ tst_ostype: $(srcdir)/ostype.c @$(CC) -DTEST_PROGRAM -I$(top_srcdir)/lib -o tst_ostype \ $(srcdir)/ostype.c $(ALL_CFLAGS) -check:: tst_ostype +tst_feature: $(srcdir)/feature.c + @echo " LD $@" + @$(CC) -DTEST_PROGRAM -I$(top_srcdir)/lib -o tst_feature \ + $(srcdir)/feature.c $(ALL_CFLAGS) + +check:: tst_ostype tst_feature ./tst_ostype + ./tst_feature installdirs:: @echo " MKINSTALLDIRS $(libdir) $(includedir)/e2p" @@ -96,7 +102,7 @@ uninstall:: clean:: $(RM) -f \#* *.s *.o *.a *~ *.bak core profiled/* checker/* - $(RM) -f ../libe2p.a ../libe2p_p.a tst_ostype + $(RM) -f ../libe2p.a ../libe2p_p.a tst_ostype tst_feature mostlyclean:: clean distclean:: clean diff --git a/lib/e2p/e2p.h b/lib/e2p/e2p.h index 06e2120d..ad607f68 100644 --- a/lib/e2p/e2p.h +++ b/lib/e2p/e2p.h @@ -11,6 +11,9 @@ #define E2P_FEATURE_NEGATE_FLAG 0x80 +#define E2P_FS_FEATURE 0 +#define E2P_JOURNAL_FEATURE 1 + /* `options' for print_flags() */ #define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */ diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c index 12cb8a32..e3a72047 100644 --- a/lib/e2p/feature.c +++ b/lib/e2p/feature.c @@ -15,6 +15,8 @@ #include <errno.h> #include "e2p.h" +#include <ext2fs/ext2fs.h> +#include <ext2fs/jfs_user.h> struct feature { int compat; @@ -74,6 +76,17 @@ static struct feature feature_list[] = { { 0, 0, 0 }, }; +static struct feature jrnl_feature_list[] = { + { E2P_FEATURE_COMPAT, JFS_FEATURE_COMPAT_CHECKSUM, + "journal_checksum" }, + + { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_REVOKE, + "journal_incompat_revoke" }, + { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_ASYNC_COMMIT, + "journal_async_commit" }, + { 0, 0, 0 }, +}; + const char *e2p_feature2string(int compat, unsigned int mask) { struct feature *f; @@ -148,6 +161,79 @@ int e2p_string2feature(char *string, int *compat_type, unsigned int *mask) return 0; } +const char *e2p_jrnl_feature2string(int compat, unsigned int mask) +{ + struct feature *f; + static char buf[20]; + char fchar; + int fnum; + + for (f = jrnl_feature_list; f->string; f++) { + if ((compat == f->compat) && + (mask == f->mask)) + return f->string; + } + switch (compat) { + case E2P_FEATURE_COMPAT: + fchar = 'C'; + break; + case E2P_FEATURE_INCOMPAT: + fchar = 'I'; + break; + case E2P_FEATURE_RO_INCOMPAT: + fchar = 'R'; + break; + default: + fchar = '?'; + break; + } + for (fnum = 0; mask >>= 1; fnum++); + sprintf(buf, "FEATURE_%c%d", fchar, fnum); + return buf; +} + +int e2p_jrnl_string2feature(char *string, int *compat_type, unsigned int *mask) +{ + struct feature *f; + char *eptr; + int num; + + for (f = jrnl_feature_list; f->string; f++) { + if (!strcasecmp(string, f->string)) { + *compat_type = f->compat; + *mask = f->mask; + return 0; + } + } + if (strncasecmp(string, "FEATURE_", 8)) + return 1; + + switch (string[8]) { + case 'c': + case 'C': + *compat_type = E2P_FEATURE_COMPAT; + break; + case 'i': + case 'I': + *compat_type = E2P_FEATURE_INCOMPAT; + break; + case 'r': + case 'R': + *compat_type = E2P_FEATURE_RO_INCOMPAT; + break; + default: + return 1; + } + if (string[9] == 0) + return 1; + num = strtol(string+9, &eptr, 10); + if (num > 32 || num < 0) + return 1; + if (*eptr) + return 1; + *mask = 1 << num; + return 0; +} static char *skip_over_blanks(char *cp) { while (*cp && isspace(*cp)) @@ -252,3 +338,47 @@ int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array) { return e2p_edit_feature2(str, compat_array, ok_array, 0, 0, 0); } + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + int compat, compat2, i; + unsigned int mask, mask2; + const char *str; + struct feature *f; + + for (i = 0; i < 2; i++) { + if (i == 0) { + f = feature_list; + printf("Feature list:\n"); + } else { + printf("\nJournal feature list:\n"); + f = jrnl_feature_list; + } + for (; f->string; f++) { + if (i == 0) { + e2p_string2feature((char *)f->string, &compat, + &mask); + str = e2p_feature2string(compat, mask); + } else { + e2p_jrnl_string2feature((char *)f->string, + &compat, &mask); + str = e2p_jrnl_feature2string(compat, mask); + } + + printf("\tCompat = %d, Mask = %u, %s\n", + compat, mask, f->string); + if (strcmp(f->string, str)) { + if (e2p_string2feature((char *) str, &compat2, + &mask2) || + (compat2 != compat) || + (mask2 != mask)) { + fprintf(stderr, "Failure!\n"); + exit(1); + } + } + } + } + exit(0); +} +#endif |