Whamcloud - gitweb
add debugfs command to print known features
authorAndreas Dilger <adilger@sun.com>
Sun, 24 Aug 2008 03:42:46 +0000 (21:42 -0600)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 25 Aug 2008 01:31:52 +0000 (21:31 -0400)
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>
debugfs/debug_cmds.ct
debugfs/debugfs.c
lib/e2p/Makefile.in
lib/e2p/e2p.h
lib/e2p/feature.c

index a4a5a4c..59314b8 100644 (file)
@@ -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;
 
index 935df81..620a513 100644 (file)
@@ -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;
index 6557480..2c56ab5 100644 (file)
@@ -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
index 06e2120..ad607f6 100644 (file)
@@ -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'. */
index 12cb8a3..e3a7204 100644 (file)
@@ -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