[PATCH] reiserfsprogs: Support for reiserfs 3.7

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 This patch contains support for handling the new 3.7 feature extension.

 Note that it does not actually implement *any* optional features, it just
 adds support for checking, debugging, and tuning them.

 reiserfstune supports setting and clearing feature bits (with --force,
 since none are supported right now), converting between 3.6 and 3.7, and
 converting back to 3.6 provided none of the optional features are
 enabled.

Signed-off-by: Jeff Mahoney <jeffm@xxxxxxxx>
---
 debugreiserfs/pack.c        |    4 
 fsck/fsck.h                 |    4 
 fsck/main.c                 |   48 ++++++++++-
 fsck/reiserfsck.8           |   12 ++
 fsck/super.c                |  154 ++++++++++++++++++++++++++++++++++-
 include/reiserfs_fs.h       |   46 ++++++++++
 include/reiserfs_lib.h      |    8 +
 mkreiserfs/mkreiserfs.c     |   38 ++++++--
 reiserfscore/Makefile.am    |    2 
 reiserfscore/feature.c      |  104 ++++++++++++++++++++++++
 reiserfscore/node_formats.c |   25 +++++
 reiserfscore/prints.c       |   44 +++++++++-
 reiserfscore/reiserfslib.c  |    8 +
 tune/reiserfstune.8         |   11 ++
 tune/tune.c                 |  190 ++++++++++++++++++++++++++++++++++++++++----
 15 files changed, 650 insertions(+), 48 deletions(-)

--- a/debugreiserfs/pack.c
+++ b/debugreiserfs/pack.c
@@ -567,8 +567,8 @@ static void pack_frozen_data (reiserfs_f
     __u16 magic16;
     int sent_journal_start_magic = 0;
     unsigned int i;
-    
-    if (is_reiserfs_jr_magic_string(fs->fs_ondisk_sb) &&
+
+    if (has_nonstandard_journal(fs->fs_ondisk_sb) &&
 	get_jp_journal_dev(sb_jp(fs->fs_ondisk_sb)) &&
 	!journal_device_name(fs)) {
 	if (!user_confirmed (stderr,
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -44,9 +44,10 @@ int main (int argc, char * argv []);
 #define FSCK_ROLLBACK_CHANGES   5
 #define FSCK_CLEAN_ATTRIBUTES	7
 #define FSCK_AUTO               8 /* -a || -p specified */
+#define FSCK_FIX_FEATURES	9
 
 /* temporary */
-#define DO_TEST                 9
+#define DO_TEST                 10
 
 /*
  * options
@@ -483,6 +484,7 @@ int replay_journal (reiserfs_filsys_t *)
 
 /*pass1: rebuild super block*/
 void rebuild_sb (reiserfs_filsys_t * fs, char * filename, struct fsck_data * data);
+int check_features(reiserfs_filsys_t * fs);
 
 
 #define fsck_log(fmt, list...) \
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -94,6 +94,7 @@ static char * parse_options (struct fsck
 	    /* modes */
 	    {"check", no_argument, &mode, FSCK_CHECK},
 	    {"fix-fixable", no_argument, &mode, FSCK_FIX_FIXABLE},
+	    {"fix-features", no_argument, &mode, FSCK_FIX_FEATURES},
 	    {"rebuild-sb", no_argument, &mode, FSCK_SB},
 	    {"rebuild-tree", no_argument, &mode, FSCK_REBUILD},
 	    {"rollback-fsck-changes", no_argument, &mode, FSCK_ROLLBACK_CHANGES},
@@ -371,6 +372,10 @@ void warn_what_will_be_done (char * file
 	
 	break;
 
+    case FSCK_FIX_FEATURES:
+	reiserfs_warning (warn_to, "Will check and optionally repair features that are unsupported by this version of reiserfsck.\n");
+	break;
+
     case FSCK_REBUILD:
 	if (data->options & OPT_SAVE_PASSES_DUMP) {
 	    reiserfs_warning (warn_to, "Will run only 1 step of the rebuilding, "
@@ -839,6 +844,16 @@ static void prepare_fs_for_check(reiserf
 	/* filesystem is not mounted, replay journal before checking */
         reiserfsck_replay_journal (fs);
     }
+
+    /* Check feature bits. We shouldn't continue on a file system with
+     * feature bits we don't know about. --fix-features will fix this. */
+    if (fsck_mode(fs) != FSCK_FIX_FEATURES && is_reiserfs_3_7_magic_string(fs->fs_ondisk_sb)) {
+	int ret = check_features(fs);
+	if (ret) {
+	    reiserfs_close (fs);
+	    exit(EXIT_FATAL);
+	}
+    }
 }
 
 static void rebuild_tree (reiserfs_filsys_t * fs) {
@@ -917,7 +932,7 @@ static void clean_attributes (reiserfs_f
         exit(EXIT_USER);
     }
 
-    if (get_reiserfs_format (fs->fs_ondisk_sb) != REISERFS_FORMAT_3_6) {
+    if (get_reiserfs_format (fs->fs_ondisk_sb) < REISERFS_FORMAT_3_6) {
         fsck_progress ("Filesystems of 3_5 format do not support extended "
 	    "attributes.\n");
 	
@@ -1078,6 +1093,30 @@ error:
     exit(EXIT_FATAL);
 }
 
+static int fix_features(reiserfs_filsys_t *fs)
+{
+    int ret = 0;
+    /* Check feature bits. We shouldn't continue on a file system with
+     * feature bits we don't know about. OTOH, we can't really abort
+     * fsck entirely on a particular type of corruption. */
+    if (is_reiserfs_3_7_magic_string(fs->fs_ondisk_sb)) {
+	int ret;
+	init_rollback_file (state_rollback_file(fs), &fs->fs_blocksize,
+	    fsck_data(fs)->log);
+
+	prepare_fs_for_check (fs);
+
+	ret = check_features(fs);
+	reiserfs_close (fs);
+	if (ret)
+	    exit (EXIT_FATAL);
+	exit (EXIT_OK);
+    } else {
+	fsck_progress("Optional features are not supported on reiserfs formats prior to 3.7\n");
+    }
+    return ret;
+}
+
 /* check umounted or read-only mounted filesystems only */
 static void check_fs (reiserfs_filsys_t * fs)
 {
@@ -1357,7 +1396,8 @@ int main (int argc, char * argv [])
 		    exit(EXIT_OPER);
 	        }
 	    }
-	
+
+
 	    if (data->options & BADBLOCKS_FILE) {
 		if (create_badblock_bitmap (fs, badblocks_file) != 0) 
 		    exit(EXIT_OPER);
@@ -1371,6 +1411,10 @@ int main (int argc, char * argv [])
     case FSCK_SB:
 	rebuild_sb (fs, file_name, data);
 	break;
+
+    case FSCK_FIX_FEATURES:
+	fix_features(fs);
+	break;
     
     case FSCK_AUTO:
 	/* perform some light-weight checks. If error, do fixable job. */
--- a/fsck/reiserfsck.8
+++ b/fsck/reiserfsck.8
@@ -1,13 +1,14 @@
 .\" -*- nroff -*-
 .\" Copyright 1996-2004 Hans Reiser.
 .\" 
-.TH REISERFSCK 8 "January 2009" "Reiserfsprogs-3.6.21"
+.TH REISERFSCK 8 "November 2010" "Reiserfsprogs-3.6.21"
 .SH NAME
 reiserfsck \- The checking tool for the ReiserFS filesystem.
 .SH SYNOPSIS
 .B reiserfsck 
 [ \fB-aprVy\fR ]
 [ \fB--rebuild-sb\fR | \fB--check\fR | \fB--fix-fixable\fR
+| \fB--fix-features\fR
 | \fB--rebuild-tree\fR | \fB--clean-attributes\fR ]
 .\" [ \fB-i\fR | \fB--interactive\fR ]
 [ \fB-j\fR | \fB--journal\fR \fIdevice\fR ]
@@ -56,6 +57,15 @@ you only need this option if the \fB--ch
 zeroing invalid data-block pointers, correcting st_size and st_blocks 
 for directories, and deleting invalid directory entries.
 .TP
+.B --fix-features
+This option checks the optional feature fields added in the 3.7 format.
+This is used when reiserfsck refuses to run because there are features
+indicated as used in the superblock that reiserfsck doesn't support.
+This should only be used if you are certain that there is corruption
+in the fields and that the features aren't actually in use. It will
+offer to clear all unknown fields or allow the administrator to
+choose which unknown features to clear specifically.
+.TP
 .B --rebuild-tree
 This option rebuilds the entire filesystem tree using leaf nodes 
 found on the device.  Normally you only need this option if the 
--- a/fsck/super.c
+++ b/fsck/super.c
@@ -24,10 +24,11 @@ int what_fs_version ()
         "\t(2) >=3.5.9 (introduced in the middle of 1999) (if you use linux 2.2, choose this one)\n"
         "\t(3) < 3.5.9 converted to new format (don't choose if unsure)\n"
         "\t(4) < 3.5.9 (this is very old format, don't choose if unsure)\n"
+	"\t(5) 3.7.x\n"
         "\t(X)   exit\n");
     getline (&answer, &n, stdin);
     version = atoi (answer);
-    if (version < 1 || version > 4)
+    if (version < 1 || version > 5)
         die ("rebuild_sb: wrong version");
     return version;
 }
@@ -168,6 +169,129 @@ int check_sb (reiserfs_filsys_t * fs) {
 }
 */
 
+unsigned int supported_features[3] = {
+    /* compat */
+    0,
+    /* incompat */
+    0,
+    /* ro-compat */
+    0,
+};
+
+
+static int
+ask_to_clear_features(reiserfs_filsys_t *fs, int compat, unsigned int *features,
+		      unsigned int mask)
+{
+    char *answer = NULL;
+    size_t n = 0;
+    int i;
+    int dirty = 0;
+
+    for (i = 0; i < 32; i++) {
+	if (mask & (1 << i)) {
+	    const char *f = reiserfs_feature_to_string(compat, 1 << i);
+	    do {
+		if (answer) {
+		    free(answer);
+		    answer = NULL;
+		}
+		printf("Clear %s? [Y/n] ", f);
+		getline (&answer, &n, stdin);
+	    } while (strcasecmp ("y\n", answer) &&
+		     strcasecmp ("n\n", answer) &&
+		     strcasecmp ("\n", answer));
+
+	    if (strcasecmp("n\n", answer)) {
+		*features &= ~cpu_to_le32(1 << i);
+		dirty = 1;
+		fsck_progress("Cleared %s.\n", f);
+	    }
+	    free(answer);
+	    answer = NULL;
+	}
+    }
+
+    return dirty;
+}
+
+int check_features(reiserfs_filsys_t *fs)
+{
+    struct reiserfs_super_block *sb = fs->fs_ondisk_sb;
+    unsigned int un_compat, un_incompat, un_rocompat;
+    unsigned int compat_supp = le32_to_cpu(REISERFS_FEATURE_COMPAT_SUPP);
+    unsigned int incompat_supp = le32_to_cpu(REISERFS_FEATURE_INCOMPAT_SUPP);
+    unsigned int rocompat_supp = le32_to_cpu(REISERFS_FEATURE_RO_COMPAT_SUPP);
+    int dirty = 0;
+    char *answer = NULL;
+    size_t n = 0;
+    const char *desc;
+    int need_comma;
+
+    un_compat = le32_to_cpu(sb->s_feature_compat) & ~compat_supp;
+    un_incompat = le32_to_cpu(sb->s_feature_incompat) & ~incompat_supp;
+    un_rocompat = le32_to_cpu(sb->s_feature_ro_compat) & ~rocompat_supp;
+
+    if ((un_compat|un_incompat|un_rocompat) == 0)
+	return 0;
+
+    fsck_progress ("Filesystem has unsupported features enabled (");
+    desc = reiserfs_features_to_string(REISERFS_FEATURE_INCOMPAT,
+				       un_incompat);
+    fsck_progress ("%s", desc);
+    need_comma = !!*desc;
+
+    desc = reiserfs_features_to_string(REISERFS_FEATURE_RO_COMPAT,
+				       un_rocompat);
+    fsck_progress ("%s%s", (need_comma && *desc) ? "," : "", desc);
+    need_comma = !!*desc;
+
+    desc = reiserfs_features_to_string(REISERFS_FEATURE_COMPAT, un_compat);
+    fsck_progress ("%s%s", (need_comma && *desc) ? "," : "", desc);
+    fsck_progress( ") that this version of fsck does not know about.  "
+		   "If you have already updated fsck to the latest version, "
+		   "this may indicate minor corruption in the superblock that "
+		   " will need to be repaired before fsck can continue.  You "
+		   "can repair this damage with the --fix-features option.  "
+		   "It should only be used if you are certain that the "
+		   "set feature bits are incorrect.\n");
+
+    if (fsck_mode(fs) != FSCK_FIX_FEATURES)
+	    return 1;
+    do {
+	if (answer) {
+	    free(answer);
+	    answer = NULL;
+	}
+	printf ("Clear all unsupported features? [Y/n] ");
+	getline (&answer, &n, stdin);
+    } while (strcasecmp ("y\n", answer) && strcasecmp ("n\n", answer) &&
+	     strcasecmp ("\n", answer));
+
+    if (!strcasecmp(answer, "n\n")) {
+	dirty += ask_to_clear_features(fs, REISERFS_FEATURE_COMPAT,
+				       &sb->s_feature_compat, un_compat);
+	dirty += ask_to_clear_features(fs, REISERFS_FEATURE_INCOMPAT,
+				       &sb->s_feature_incompat, un_incompat);
+	dirty += ask_to_clear_features(fs, REISERFS_FEATURE_RO_COMPAT,
+				       &sb->s_feature_ro_compat, un_rocompat);
+    } else {
+	sb->s_feature_compat &= ~(cpu_to_le32(un_compat));
+	sb->s_feature_incompat &= ~(cpu_to_le32(un_incompat));
+	sb->s_feature_ro_compat &= ~(cpu_to_le32(un_rocompat));
+	fsck_progress("Cleared all unsupported features.\n");
+	dirty = 1;
+    }
+
+    if (dirty) {
+	mark_buffer_dirty(fs->fs_super_bh);
+	fs->fs_dirt = 1;
+	bwrite(fs->fs_super_bh);
+    }
+
+    return 0;
+}
+
 void rebuild_sb (reiserfs_filsys_t * fs, char * filename, struct fsck_data * data)
 {
     int version = 0;
@@ -228,7 +352,16 @@ void rebuild_sb (reiserfs_filsys_t * fs,
         memcpy (sb, fs->fs_ondisk_sb, sizeof (*sb));
         fs->fs_ondisk_sb = sb;
 
-        if (is_reiserfs_3_6_magic_string (sb)) {
+	if (is_reiserfs_3_7_magic_string (sb)) {
+	    /* 3_7 magic */
+            if (fs->fs_super_bh->b_blocknr ==
+		REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize)
+                version = 7;
+	    else
+		reiserfs_exit (EXIT_USER, "ReiserFS v3.7 was found but in "
+			       "an invalid location.\n");
+            magic_was_found = 7;
+	} else if (is_reiserfs_3_6_magic_string (sb)) {
             /* 3_6 magic */
             if (fsck_data (fs)->journal_dev_name)
                 /* journal dev must not be specified with standard journal */
@@ -295,7 +428,9 @@ void rebuild_sb (reiserfs_filsys_t * fs,
 
         if (magic_was_found == 1 || magic_was_found == 2)
             standard_journal = 1;
-        else
+	else if (magic_was_found == 7) {
+	    standard_journal = !fsck_data (fs)->journal_dev_name;
+	} else
             standard_journal = 0;
 
         if (version == 0)
@@ -327,6 +462,7 @@ void rebuild_sb (reiserfs_filsys_t * fs,
 		    get_sb_block_size (sb), fs->fs_blocksize);
   	    set_sb_block_size (sb, fs->fs_blocksize);
         }
+
     }
 
     /* if no reiserfs_found or bad data found in that SB, what was checked in previous 
@@ -375,6 +511,8 @@ void rebuild_sb (reiserfs_filsys_t * fs,
         case 4:
             fs = reiserfs_create (filename, REISERFS_FORMAT_3_5, block_count, retval, 1, 0);
             break;
+	case 7:
+	    fs = reiserfs_create (filename, REISERFS_FORMAT_3_7, block_count, retval, 1, standard_journal);
         }
 
 	if (fs == NULL)
@@ -435,6 +573,12 @@ void rebuild_sb (reiserfs_filsys_t * fs,
 		    get_reiserfs_format (sb), REISERFS_FORMAT_3_5);
             set_sb_version (sb, REISERFS_FORMAT_3_5);
         }
+    } else if (version == 7 &&
+	       get_reiserfs_format (sb) != REISERFS_FORMAT_3_7) {
+	fsck_log("rebuild-sb: wrong reiserfs version occured (%lu), "
+		 "fixed (%lu)\n", get_reiserfs_format (sb),
+		 REISERFS_FORMAT_3_7);
+	set_sb_version (sb, REISERFS_FORMAT_3_7);
     }
 
     p_oid_maxsize = (fs->fs_blocksize - reiserfs_super_block_size (sb)) / 
@@ -503,7 +647,7 @@ void rebuild_sb (reiserfs_filsys_t * fs,
 	set_sb_hash_code (sb, 0);
     }
 
-    if (version == 1 || version == 3) {
+    if (version == 1 || version == 3 || version == 7) {
 #if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H)
         if (uuid_is_null(sb->s_uuid)) {
 	    uuid_generate(sb->s_uuid);
@@ -812,7 +956,7 @@ void rebuild_sb (reiserfs_filsys_t * fs,
     /*  whether journal header contains params with the same dev, offset, size will be 
 	checked in open_journal */
 
-    if (version == 1 || version == 3)
+    if (version == 1 || version == 3 || version == 7)
         sb_size = SB_SIZE;
     else
         sb_size = SB_SIZE_V1;
--- a/include/reiserfs_fs.h
+++ b/include/reiserfs_fs.h
@@ -185,8 +185,8 @@ struct reiserfs_super_block_v1
    only reliable on filesystem with non-standard journal */
 #define REISERFS_FORMAT_3_5 0
 #define REISERFS_FORMAT_3_6 2
+#define REISERFS_FORMAT_3_7 3
 #define REISERFS_FORMAT_UNKNOWN -1
-                                   
 
 /* values for sb_mount_state field */
 #define FS_CLEANLY_UMOUNTED    1 /* this was REISERFS_VALID_FS */
@@ -206,7 +206,11 @@ struct reiserfs_super_block
 /*118 */    __u16 s_max_mnt_count;
 /*120 */    __u32 s_lastcheck;
 /*124 */    __u32 s_check_interval;
-/*128 */    char s_unused[76] ;            /* zero filled by mkreiserfs and reiserfs_convert_objectid_map_v1()
+	    /* Only available in superblock v3/reiserfs 3.7 */
+/*128 */    __u32 s_feature_compat;
+/*132 */    __u32 s_feature_incompat;
+/*136 */    __u32 s_feature_ro_compat;
+/*140 */    char s_unused[64] ;            /* zero filled by mkreiserfs and reiserfs_convert_objectid_map_v1()
                                             * so any additions must be updated there as well. */ 
 /*204*/
 } __attribute__ ((__packed__));;
@@ -293,6 +297,10 @@ typedef enum {
 #define set_sb_v2_flag(sb, flag)	set_le32 (sb, s_flags, get_le32 (sb, s_flags) | flag)
 #define clear_sb_v2_flag(sb, flag)	set_le32 (sb, s_flags, get_le32 (sb, s_flags) & ~(flag))
 
+#define get_sb_v2_feature_incompat(sb)	get_le32 (sb, s_feature_incompat)
+#define get_sb_v2_feature_compat(sb)	get_le32 (sb, s_feature_compat)
+#define get_sb_v2_feature_ro_compat(sb)	get_le32 (sb, s_feature_ro_compat)
+
 /*
 #define journal_is_relocated(sb)        get_jp_journal_dev(sb_jp (sb))
 */
@@ -393,6 +401,7 @@ typedef enum {
 #define REISERFS_3_6_SUPER_MAGIC_STRING "ReIsEr2Fs"
 #define REISERFS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" /* JR stands for Journal
 						      Relocation */
+#define REISERFS_3_7_SUPER_MAGIC_STRING "ReIsEr7Fs"
 
 #define get_reiserfs_ondisk_offset(block_of_super_block, block_size) \
     (block_of_super_block * block_size)
@@ -406,6 +415,39 @@ typedef enum {
     ((get_reiserfs_ondisk_offset(block_of_super_block, 4096) == REISERFS_OLD_DISK_OFFSET_IN_BYTES) \
 	? 1 : 0)
 
+/* Features */
+/* reiserfs 3.7 features */
+
+#define REISERFS_FEATURE_COMPAT 0
+#define REISERFS_FEATURE_INCOMPAT 1
+#define REISERFS_FEATURE_RO_COMPAT 2
+
+#define REISERFS_HAS_COMPAT_FEATURE(sb, mask)           \
+	((sb)->s_feature_compat & cpu_to_le32(mask))
+#define REISERFS_HAS_INCOMPAT_FEATURE(sb, mask) \
+	((sb)->s_feature_incompat & cpu_to_le32(mask))
+#define REISERFS_HAS_RO_COMPAT_FEATURE(sb, mask)        \
+	((sb)->s_feature_ro_compat & cpu_to_le32(mask))
+
+#define REISERFS_SET_COMPAT_FEATURE(sb, mask)           \
+	((sb)->s_feature_compat |= cpu_to_le32(mask))
+#define REISERFS_SET_INCOMPAT_FEATURE(sb, mask) \
+	((sb)->s_feature_incompat |= cpu_to_le32(mask))
+#define REISERFS_SET_RO_COMPAT_FEATURE(sb, mask)        \
+	((sb)->s_feature_ro_compat |= cpu_to_le32(mask))
+
+#define REISERFS_CLEAR_COMPAT_FEATURE(sb, mask) \
+	((sb)->s_feature_compat &= ~cpu_to_le32(mask))
+#define REISERFS_CLEAR_INCOMPAT_FEATURE(sb, mask)       \
+	((sb)->s_feature_incompat &= ~cpu_to_le32(mask))
+#define REISERFS_CLEAR_RO_COMPAT_FEATURE(sb, mask)      \
+	((sb)->s_feature_ro_compat &= ~cpu_to_le32(mask))
+
+#define REISERFS_FEATURE_COMPAT_SUPP    0
+#define REISERFS_FEATURE_INCOMPAT_SUPP  0
+#define REISERFS_FEATURE_RO_COMPAT_SUPP 0
+
+
 /***************************************************************************/
 /*                             JOURNAL                                     */
 /***************************************************************************/
--- a/include/reiserfs_lib.h
+++ b/include/reiserfs_lib.h
@@ -223,8 +223,10 @@ int is_blocksize_correct (unsigned int b
 int is_reiserfs_3_5_magic_string (struct reiserfs_super_block * rs);
 int is_reiserfs_3_6_magic_string (struct reiserfs_super_block * rs);
 int is_reiserfs_jr_magic_string (struct reiserfs_super_block * rs);
+int is_reiserfs_3_7_magic_string (struct reiserfs_super_block * rs);
 int does_look_like_super_block (struct reiserfs_super_block * rs);
 int is_any_reiserfs_magic_string (struct reiserfs_super_block * rs);
+int has_nonstandard_journal (struct reiserfs_super_block * rs);
 int get_reiserfs_format (struct reiserfs_super_block * sb);
 int reiserfs_super_block_size (struct reiserfs_super_block * rs);
 /*int magic_2_version (struct reiserfs_super_block * rs);*/
@@ -409,4 +411,10 @@ int can_we_format_it (char * device_name
 	}\
 
 
+/* features.c */
+int reiserfs_string_to_feature(char *string, int *compat_type,
+			       unsigned int *mask);
+const char *reiserfs_feature_to_string(int compat, unsigned int mask);
+const char *reiserfs_features_to_string(int compat, unsigned int mask);
+
 #endif /* REISERFSPROGS_LIB_H */
--- a/mkreiserfs/mkreiserfs.c
+++ b/mkreiserfs/mkreiserfs.c
@@ -71,7 +71,7 @@ static void print_usage_and_exit(void)
 	"  -h | --hash rupasov|tea|r5       hash function to use by default\n"
 	"  -u | --uuid UUID                 store UUID in the superblock\n"
 	"  -l | --label LABEL               store LABEL in the superblock\n"
-	"  --format 3.5|3.6                 old 3.5 format or newer 3.6\n"
+	"  --format 3.5|3.6|3.7             old 3.5, common 3.6, or newer 3.7 format\n"
 	"  -f | --force                     specified once, make mkreiserfs the whole\n"
 	"                                   disk, not block device or mounted partition;\n"
 	"                                   specified twice, do not ask for confirmation\n"
@@ -112,7 +112,8 @@ static void make_super_block (reiserfs_f
     set_sb_umount_state (fs->fs_ondisk_sb, FS_CLEANLY_UMOUNTED);
     set_sb_tree_height (fs->fs_ondisk_sb, 2);
     set_sb_hash_code (fs->fs_ondisk_sb, Hash);
-    if (fs->fs_format == REISERFS_FORMAT_3_6) {
+    if (fs->fs_format == REISERFS_FORMAT_3_6 ||
+	fs->fs_format == REISERFS_FORMAT_3_7) {
 #if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H)
         if (uuid_is_null(UUID))
 	    uuid_generate(UUID);
@@ -308,6 +309,7 @@ static void make_root_block (reiserfs_fi
 static void report (reiserfs_filsys_t * fs, char * j_filename)
 {
 //    print_block (stdout, fs, fs->fs_super_bh);
+    const char *journal_prefix = NULL;
     struct reiserfs_super_block * sb = 
 	(struct reiserfs_super_block *)(fs->fs_super_bh->b_data);
 
@@ -334,10 +336,21 @@ static void report (reiserfs_filsys_t *
     case REISERFS_FORMAT_3_6:
 	    reiserfs_warning (stdout, "Format 3.6 with ");
 	    break;
+    case REISERFS_FORMAT_3_7:
+	    reiserfs_warning (stdout, "Format 3.7 with ");
+	    if (get_jp_journal_dev (sb_jp (sb)))
+		journal_prefix = "non-";
+	    else
+		journal_prefix = "";
+	    break;
+    }
+    if (!journal_prefix) {
+	if (is_reiserfs_jr_magic_string (sb))
+		journal_prefix = "non-";
+	else
+		journal_prefix = "";
     }
-    if (is_reiserfs_jr_magic_string (sb))
-	    reiserfs_warning (stdout, "non-");
-    reiserfs_warning (stdout, "standard journal\n");
+    reiserfs_warning (stdout, "%sstandard journal\n", journal_prefix);
     reiserfs_warning (stdout, "Count of blocks on the device: %u\n", 
 		      get_sb_block_count (sb));
     reiserfs_warning (stdout, "Number of blocks consumed by mkreiserfs "
@@ -384,7 +397,8 @@ static void report (reiserfs_filsys_t *
 			  get_sb_version (sb));
     }
 
-    if (get_reiserfs_format (sb) == REISERFS_FORMAT_3_6) {
+    if (get_reiserfs_format (sb) == REISERFS_FORMAT_3_6 ||
+	get_reiserfs_format (sb) == REISERFS_FORMAT_3_7) {
         reiserfs_warning (stdout, "inode generation number: %u\n", 
 			  get_sb_v2_inode_generation (sb));
         reiserfs_warning (stdout, "UUID: %U\n", sb->s_uuid);
@@ -415,7 +429,9 @@ static void set_reiserfs_version (char *
 {
     if (!strcmp (str, "3.5"))
 	    Format = "3.5";
-    else  {
+    else if (!strcmp (str, "3.7"))
+	    Format = "3.7";
+    else {
 	    Format = "3.6";
 	    if (strcmp (str, "3.6"))
 		    message("wrong reiserfs version specified. "
@@ -520,6 +536,9 @@ static int select_format (void)
 		if (!strcmp (Format, "3.5"))
 			return REISERFS_FORMAT_3_5;
 
+		if (!strcmp (Format, "3.7"))
+			return REISERFS_FORMAT_3_7;
+
 		if (strcmp (Format, "3.6")) {
 			message ("Unknown fromat %s specified\n", Format);
 			exit (1);
@@ -754,8 +773,9 @@ int main (int argc, char **argv)
     /* these fill buffers (super block, first bitmap, root block) with
        reiserfs structures */
 #if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H)
-    if (!uuid_is_null(UUID) && fs->fs_format != REISERFS_FORMAT_3_6) {
-	reiserfs_warning(stderr, "UUID can be specified only with 3.6 format\n");
+    if (!uuid_is_null(UUID) && (fs->fs_format != REISERFS_FORMAT_3_6 ||
+				fs->fs_format != REISERFS_FORMAT_3_7)) {
+	reiserfs_warning(stderr, "UUID can be specified only with 3.6 or 3.7 format\n");
 	return 1;
     }
 #endif
--- a/reiserfscore/Makefile.am
+++ b/reiserfscore/Makefile.am
@@ -1,5 +1,5 @@
 noinst_LIBRARIES = libcore.a
 
 libcore_a_SOURCES = do_balan.c fix_node.c hashes.c ibalance.c lbalance.c prints.c \
-stree.c node_formats.c reiserfslib.c bitmap.c journal.c includes.h
+stree.c node_formats.c reiserfslib.c bitmap.c journal.c includes.h feature.c
 
--- /dev/null
+++ b/reiserfscore/feature.c
@@ -0,0 +1,104 @@
+#include <string.h>
+#include "misc.h"
+#include "swab.h"
+#include "reiserfs_lib.h"
+
+struct feature {
+	int compat;
+	unsigned int mask;
+	const char *string;
+};
+
+struct feature feature_list[] = {
+	{},
+};
+
+int reiserfs_string_to_feature(char *string, int *compat_type,
+			       unsigned int *mask)
+{
+	struct feature *f;
+	int num;
+	char *eptr;
+
+	for (f = feature_list; f->string; f++) {
+		if (!strcasecmp(f->string, string)) {
+			*compat_type = f->compat;
+			*mask = f->mask;
+			return 0;
+		}
+	}
+
+	/* Unnamed features */
+	if (strncasecmp(string, "FEATURE_", 8))
+		return 1;
+
+	switch (string[8]) {
+	case 'C': *compat_type = REISERFS_FEATURE_COMPAT; break;
+	case 'I': *compat_type = REISERFS_FEATURE_INCOMPAT; break;
+	case 'R': *compat_type = REISERFS_FEATURE_RO_COMPAT; break;
+	default:
+		return 1;
+	};
+	num = strtol(string+9, &eptr, 10);
+	if (num > 32 || num < 0)
+		return 1;
+	if (*eptr)
+		return 1;
+	*mask = 1 << num;
+	return 0;
+}
+
+const char *reiserfs_feature_to_string(int compat, unsigned int mask)
+{
+	static char buf[256];
+	struct feature *f;
+	char prefix;
+	int fnum;
+
+	for (f = feature_list; f->string; f++) {
+		if ((compat == f->compat) &&
+		    (mask == f->mask))
+			return f->string;
+	}
+
+	/* Unnamed features */
+	switch (compat) {
+	case REISERFS_FEATURE_COMPAT:
+		prefix = 'C'; break;
+	case REISERFS_FEATURE_INCOMPAT:
+		prefix = 'I'; break;
+	case REISERFS_FEATURE_RO_COMPAT:
+		prefix = 'R'; break;
+	default:
+		prefix = '?';
+		break;
+	};
+	for (fnum = 0; mask >>= 1; fnum++);
+	sprintf(buf, "FEATURE_%c%d", prefix, fnum);
+	return buf;
+}
+
+const char *reiserfs_features_to_string(int compat, unsigned int mask)
+{
+	int i;
+	static char buf[4096];
+	const char *max = buf + sizeof(buf);
+	char *ptr = buf;
+	int first = 1;
+	const char *f;
+
+	*ptr = '\0';
+
+	for (i = 0; i < 32; i++) {
+		if (mask & (1 << i)) {
+			f = reiserfs_feature_to_string(compat, 1 << i);
+			if (!first)
+				ptr += snprintf(ptr, max - ptr, ",%s", f);
+			else
+				ptr += snprintf(ptr, max - ptr, "%s", f);
+			first = 0;
+		}
+	}
+
+	return buf;
+}
--- a/reiserfscore/node_formats.c
+++ b/reiserfscore/node_formats.c
@@ -223,6 +223,12 @@ int is_reiserfs_3_6_magic_string (struct
 		      strlen ( REISERFS_3_6_SUPER_MAGIC_STRING)));
 }
 
+int is_reiserfs_3_7_magic_string (struct reiserfs_super_block * rs)
+{
+    return (!strncmp (rs->s_v1.s_magic, REISERFS_3_7_SUPER_MAGIC_STRING,
+		      strlen ( REISERFS_3_7_SUPER_MAGIC_STRING)));
+}
+
 
 int is_reiserfs_jr_magic_string (struct reiserfs_super_block * rs)
 {
@@ -235,11 +241,22 @@ int is_any_reiserfs_magic_string (struct
 {
     if (is_reiserfs_3_5_magic_string (rs) ||
 	is_reiserfs_3_6_magic_string (rs) ||
+	is_reiserfs_3_7_magic_string (rs) ||
 	is_reiserfs_jr_magic_string (rs))
 	return 1;
     return 0;
 }
 
+int has_nonstandard_journal (struct reiserfs_super_block * rs)
+{
+    if (is_reiserfs_jr_magic_string (rs))
+	return 1;
+    if (is_reiserfs_3_7_magic_string (rs) &&
+	get_jp_journal_dev(&rs->s_v1.sb_journal) != 0)
+	return 1;
+    return 0;
+}
+
 
 int get_reiserfs_format (struct reiserfs_super_block * sb)
 {
@@ -257,6 +274,9 @@ int get_reiserfs_format (struct reiserfs
 	 get_sb_version (sb) == REISERFS_FORMAT_3_6))
 	return REISERFS_FORMAT_3_6;
 
+    if (is_reiserfs_3_7_magic_string (sb))
+	return REISERFS_FORMAT_3_7;
+
     return REISERFS_FORMAT_UNKNOWN;
 }
 
@@ -268,6 +288,7 @@ int reiserfs_super_block_size (struct re
     case REISERFS_FORMAT_3_5:
 	return SB_SIZE_V1;
     case REISERFS_FORMAT_3_6:
+    case REISERFS_FORMAT_3_7:
 	return SB_SIZE;
     }
     reiserfs_panic ("Unknown format found");
@@ -345,14 +366,14 @@ char * which_block (int code)
 
 /** */
 int block_of_journal (reiserfs_filsys_t * fs, unsigned long block) {
-    if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb)) {
+    if (!has_nonstandard_journal (fs->fs_ondisk_sb)) {
 	/* standard journal */
 	if (block >= get_journal_start_must (fs) &&
 	    block <= get_journal_start_must (fs) + get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)))
 	    return 1;
 	return 0;
     }
-    
+
     if (get_sb_reserved_for_journal (fs->fs_ondisk_sb))
 	/* there is space reserved for the journal on the host device */
 	if (block >= get_journal_start_must (fs) && 
--- a/reiserfscore/prints.c
+++ b/reiserfscore/prints.c
@@ -616,6 +616,7 @@ int print_super_block (FILE * fp, reiser
     __u16 state;
     time_t last_check = get_sb_v2_lastcheck(sb);
     char last_check_buf[26];
+    const char *journal_prefix = NULL;
 
     if (!does_look_like_super_block (sb))
 	return 1;
@@ -633,13 +634,25 @@ int print_super_block (FILE * fp, reiser
 	reiserfs_warning (fp, "format 3.6 with ");
         format = 2;
 	break;
+    case REISERFS_FORMAT_3_7:
+	reiserfs_warning (fp, "format 3.7 with ");
+        format = 2;
+	if (get_jp_journal_dev(&sb->s_v1.sb_journal))
+		journal_prefix = "non-";
+	else
+		journal_prefix = "";
+	break;
     default:
 	reiserfs_warning (fp, "unknown format with ");
 	break;
     }
-    if (is_reiserfs_jr_magic_string (sb))
-	reiserfs_warning (fp, "non-");
-    reiserfs_warning (fp, "standard journal\n");
+    if (!journal_prefix) {
+	    if (is_reiserfs_jr_magic_string (sb))
+		    journal_prefix = "non-";
+	    else
+		    journal_prefix = "";
+    }
+    reiserfs_warning (fp, "%sstandard journal\n", journal_prefix);
     if (short_print) {
 	reiserfs_warning (fp, "Blocks (total/free): %u/%u by %d bytes\n",
 		get_sb_block_count (sb), get_sb_free_blocks (sb), get_sb_block_size (sb));
@@ -677,7 +690,7 @@ int print_super_block (FILE * fp, reiser
 	reiserfs_warning (fp, "\tI/O corruptions exist.\n");
 
     reiserfs_warning (fp, "sb_version: %u\n", get_sb_version (sb));
-    if (format == 2) {
+    if (get_reiserfs_format(sb) >= REISERFS_FORMAT_3_6) {
         reiserfs_warning (fp, "inode generation number: %u\n", get_sb_v2_inode_generation (sb));
         reiserfs_warning (fp, "UUID: %U\n", sb->s_uuid);
         reiserfs_warning (fp, "LABEL: %.16s\n", sb->s_label);
@@ -710,6 +723,26 @@ int print_super_block (FILE * fp, reiser
 	else
 		reiserfs_warning(fp, "Disabled. Run fsck.reiserfs(8) or use tunefs.reiserfs(8) to enable.\n");
     }
+    if (get_reiserfs_format(sb) == REISERFS_FORMAT_3_7) {
+	    const char *features;
+	    features = reiserfs_features_to_string(REISERFS_FEATURE_INCOMPAT,
+					    get_sb_v2_feature_incompat(sb));
+	    if (!features[0])
+		features = "(none)";
+	    reiserfs_warning (fp, "Incompatible features: %s\n", features);
+
+	    features = reiserfs_features_to_string( REISERFS_FEATURE_RO_COMPAT,
+					    get_sb_v2_feature_ro_compat(sb));
+	    if (!features[0])
+		features = "(none)";
+	    reiserfs_warning (fp, "RO-compatible features: %s\n", features);
+
+	    features = reiserfs_features_to_string( REISERFS_FEATURE_COMPAT,
+					    get_sb_v2_feature_compat(sb));
+	    if (!features[0])
+		features = "(none)";
+	    reiserfs_warning (fp, "Compatible features: %s\n", features);
+    }
 
     return 0;
 }
@@ -983,7 +1016,8 @@ void print_objectid_map (FILE * fp, reis
 
 
     sb = fs->fs_ondisk_sb;
-    if (fs->fs_format == REISERFS_FORMAT_3_6)
+    if (fs->fs_format == REISERFS_FORMAT_3_6 ||
+	fs->fs_format == REISERFS_FORMAT_3_7)
 	omap = (__u32 *)(sb + 1);
     else if (fs->fs_format == REISERFS_FORMAT_3_5)
 	omap = (__u32 *)((struct reiserfs_super_block_v1 *)sb + 1);
--- a/reiserfscore/reiserfslib.c
+++ b/reiserfscore/reiserfslib.c
@@ -274,6 +274,14 @@ reiserfs_filsys_t * reiserfs_create (cha
         memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_6_SUPER_MAGIC_STRING,
                 strlen (REISERFS_3_6_SUPER_MAGIC_STRING));
 	break;
+    case REISERFS_FORMAT_3_7:
+	set_sb_oid_maxsize (fs->fs_ondisk_sb,
+	    (block_size - SB_SIZE) / sizeof(__u32) / 2 * 2);
+	/* sb_oid_cursize */
+	/* sb_state */
+        memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_7_SUPER_MAGIC_STRING,
+                strlen (REISERFS_3_7_SUPER_MAGIC_STRING));
+	break;
     }
     if (!default_journal)
         memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_JR_SUPER_MAGIC_STRING,
--- a/tune/reiserfstune.8
+++ b/tune/reiserfstune.8
@@ -1,7 +1,7 @@
 .\" -*- nroff -*-
 .\" Copyright 1996-2004 Hans Reiser.
 .\" 
-.TH REISERFSTUNE 8 "January 2009" "Reiserfsprogs-3.6.21"
+.TH REISERFSTUNE 8 "November 2010" "Reiserfsprogs-3.6.21"
 .SH NAME
 reiserfstune \- The tunning tool for the ReiserFS filesystem.
 .SH SYNOPSIS
@@ -22,6 +22,7 @@ reiserfstune \- The tunning tool for the
 [ \fB-C\fR | \fB--time-last-checked \fItimestamp\fR ]
 [ \fB-m\fR | \fB--max-mnt-count \fIcount\fR ]
 [ \fB-M\fR | \fB--mnt-count \fIcount\fR ]
+[ \fB-O\fR | \fB--feature \fIfeature\fR ]
 .I device
 .SH DESCRIPTION
 \fBreiserfstune\fR is used for tuning the ReiserFS. It can change two journal 
@@ -191,6 +192,14 @@ option,
 .BR fsck.reiserfs(8)
 will check the filesystem at the next
 reboot.
+.TP
+\fB-O\fR | \fB--feature \fIfeature\fR
+Enable, or disable by prefixing
+.B \-
+to \fIfeature\fR, an optional filesystem feature.
+Optional filesystem features may not be supported on all systems but allow
+extended functionality beyond that offered by the standard format.
+NOTE: This option is only available for v3.7 format filesystems.
 .SH POSSIBLE SCENARIOS OF USING REISERFSTUNE:
 1. You have ReiserFS on /dev/hda1, and you wish to have
 it working with its journal on the device /dev/journal
--- a/tune/tune.c
+++ b/tune/tune.c
@@ -67,6 +67,7 @@ static void print_usage_and_exit(void)
 	     "  -M | --mnt-count\t\tset the number of times the filesystem\n"
 	     "                  \t\thas been mounted\n"
 	     "  -h | --help\t\t\tprint help and exit\n"
+	     "  -O | --feature\t\t\tenable or disable (with -feature) feature\n"
 	     "  -V\t\t\t\tprint version and exit\n", program_name);
     exit (1);
 }
@@ -88,7 +89,8 @@ char * badblocks_file;
 /* If specified paramenters defines the standard journal, make it standard. */
 static int should_make_journal_standard (reiserfs_filsys_t * fs, char * j_new_dev_name)
 {
-    if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb))
+    if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb) &&
+	!is_reiserfs_3_7_magic_string (fs->fs_ondisk_sb))
 	return 0;
 /*    
     if (!user_confirmed (stderr, "ATTENTION! Filesystem with non-standard journal "
@@ -131,12 +133,15 @@ static int set_standard_journal_params (
 
     /* ondisk superblock update */
 
-    if (get_sb_version(fs->fs_ondisk_sb) == 0)
+    if (get_sb_version(fs->fs_ondisk_sb) == REISERFS_FORMAT_3_5)
 	memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_5_SUPER_MAGIC_STRING,
 		strlen (REISERFS_3_5_SUPER_MAGIC_STRING));
-    else if (get_sb_version(fs->fs_ondisk_sb) == 2)
+    else if (get_sb_version(fs->fs_ondisk_sb) == REISERFS_FORMAT_3_6)
 	memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_6_SUPER_MAGIC_STRING,
 		strlen (REISERFS_3_6_SUPER_MAGIC_STRING));
+    else if (get_sb_version(fs->fs_ondisk_sb) == REISERFS_FORMAT_3_7)
+	memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_7_SUPER_MAGIC_STRING,
+		strlen (REISERFS_3_7_SUPER_MAGIC_STRING));
     else {
 	message ("Can not set standard reiserfs magic: unknown format found %u,"
 		 " try reiserfsck first", get_sb_version(fs->fs_ondisk_sb));
@@ -250,6 +255,73 @@ static void set_mnt_count(char *str)
 	Mnt_count = str2int(str);
 }
 
+char features[3][32];
+unsigned int features_ok_to_set[3] = {
+	[REISERFS_FEATURE_INCOMPAT] = REISERFS_FEATURE_INCOMPAT_SUPP,
+	[REISERFS_FEATURE_RO_COMPAT] = REISERFS_FEATURE_RO_COMPAT_SUPP,
+	[REISERFS_FEATURE_COMPAT] = REISERFS_FEATURE_COMPAT_SUPP,
+};
+
+unsigned int features_ok_to_clear[3] = {
+	[REISERFS_FEATURE_INCOMPAT] = 0,
+	[REISERFS_FEATURE_RO_COMPAT] = 0,
+	[REISERFS_FEATURE_COMPAT] = 0,
+};
+
+static void set_features(char *str)
+{
+	char *feature;
+	while ((feature = strsep(&str, ","))) {
+		int compat;
+		unsigned int mask;
+		int fnum;
+		int ret;
+		int neg = 0;
+		if (feature[0] == '-') {
+			neg = 1;
+			feature++;
+		}
+
+		ret = reiserfs_string_to_feature(feature, &compat, &mask);
+		if (ret) {
+			printf("Invalid feature name %s\n", feature);
+			continue;
+		}
+		for (fnum = 0; mask >>= 1; fnum++);
+
+		features[compat][fnum] = neg ? 2 : 1;
+
+		if (Force)
+			continue;
+		if (neg && !(features_ok_to_clear[compat] & mask)) {
+			message("Feature %s is not allowed to be cleared\n",
+				feature);
+			exit(1);
+		} else if (!neg && !(features_ok_to_set[compat] & mask)) {
+			message("Feature %s is not allowed to be set\n",
+				feature);
+			exit(1);
+		}
+	}
+}
+
+int Convert;
+int Convert_format;
+static void set_convert(char *str)
+{
+    Convert = 1;
+    if (!strcmp(str, "3.7"))
+	Convert_format = REISERFS_FORMAT_3_7;
+    else if (!strcmp(str, "3.6"))
+	Convert_format = REISERFS_FORMAT_3_6;
+    else if (!strcmp(str, "3.5"))
+	Convert_format = REISERFS_FORMAT_3_5;
+    else {
+	message("Invalid format \"%s\" specified. Exiting.\n", str);
+	exit(1);
+    }
+}
+
 static void set_check_interval(char *str)
 {
 	if (!strcmp(str, "disable"))
@@ -380,6 +452,7 @@ int main (int argc, char **argv)
     struct reiserfs_journal_header * j_head;
     reiserfs_trans_t old, new;
     int Is_journal_or_maxtrans_size_specified = 0;
+    int need_dirty = 0;
 
     program_name = strrchr( argv[ 0 ], '/' );
 
@@ -417,11 +490,13 @@ int main (int argc, char **argv)
 	    {"time-last-checked", required_argument, 0, 'C'},
 	    {"max-mount-count", required_argument, 0, 'm'},
 	    {"mount-count", required_argument, 0, 'M'},
+	    {"feature", required_argument, 0, 'O'},
+	    {"convert", required_argument, 0, 'Z'},
 	    {0, 0, 0, 0}
 	};
 	int option_index;
       
-	c = getopt_long (argc, argv, "hj:s:t:o:fu:l:b:B:Vc:C:m:M:",
+	c = getopt_long (argc, argv, "hj:s:t:o:fu:l:b:B:Vc:C:m:M:O:",
 			 options, &option_index);
 	if (c == -1)
 	    break;
@@ -511,6 +586,14 @@ int main (int argc, char **argv)
 	case 'M':
 	    set_mnt_count(optarg);
 	    break;
+	case 'O':
+	    set_features(optarg);
+	    break;
+
+	case 'Z':
+	    set_convert(optarg);
+	    break;
+
 
 #if 0
 	case 'J': /* --journal-new-device */
@@ -633,8 +716,8 @@ int main (int argc, char **argv)
     }
 
     /* set UUID and LABEL if specified */
-    if (fs->fs_format == REISERFS_FORMAT_3_6) {
-	int need_dirty = 0;
+    if (fs->fs_format == REISERFS_FORMAT_3_6 ||
+	fs->fs_format == REISERFS_FORMAT_3_7) {
 #if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H)
         if (!uuid_is_null(UUID)) {
 	    memcpy (fs->fs_ondisk_sb->s_uuid, UUID, 16);
@@ -677,10 +760,6 @@ int main (int argc, char **argv)
 		need_dirty = 1;
 	}
 
-	if (need_dirty) {
-	    mark_buffer_dirty (fs->fs_super_bh);
-	    fs->fs_dirt = 1;
-	}
     } else {
 #if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H)
         if (!uuid_is_null(UUID))
@@ -695,6 +774,83 @@ int main (int argc, char **argv)
 	    reiserfs_exit (1, "check-interval cannot be specified for 3.5 format\n");
     }
 
+    if (Convert) {
+	    struct reiserfs_super_block *sb = fs->fs_ondisk_sb;
+	    if (fs->fs_format == REISERFS_FORMAT_3_6 &&
+		Convert_format == REISERFS_FORMAT_3_7) {
+		    set_sb_version (sb, REISERFS_FORMAT_3_7);
+		    memcpy (sb->s_v1.s_magic, REISERFS_3_7_SUPER_MAGIC_STRING,
+			    strlen (REISERFS_3_7_SUPER_MAGIC_STRING));
+		    sb->s_feature_incompat = 0;
+		    sb->s_feature_compat = 0;
+		    sb->s_feature_ro_compat = 0;
+		    fs->fs_format = REISERFS_FORMAT_3_7;
+		    need_dirty = 1;
+	    } else if (fs->fs_format == REISERFS_FORMAT_3_7 &&
+		       Convert_format == REISERFS_FORMAT_3_6) {
+		    if (sb->s_feature_incompat || sb->s_feature_compat ||
+			sb->s_feature_ro_compat) {
+			reiserfs_exit (1, "cannot convert v3.7 filesystem to v3.6 with optional features in use.\n");
+		    }
+
+		    if (get_jp_journal_dev(&sb->s_v1.sb_journal) != 0) {
+			memcpy (sb->s_v1.s_magic,
+				REISERFS_JR_SUPER_MAGIC_STRING,
+				strlen (REISERFS_JR_SUPER_MAGIC_STRING));
+		    } else {
+			memcpy (sb->s_v1.s_magic,
+				REISERFS_3_6_SUPER_MAGIC_STRING,
+				strlen (REISERFS_3_6_SUPER_MAGIC_STRING));
+		    }
+
+		    set_sb_version (sb, REISERFS_FORMAT_3_6);
+		    fs->fs_format = REISERFS_FORMAT_3_6;
+	    }
+    }
+
+    if (fs->fs_format == REISERFS_FORMAT_3_7) {
+	int i;
+	for (i = 0; i < 32; i++) {
+	    if (features[REISERFS_FEATURE_INCOMPAT][i] == 1) {
+		REISERFS_SET_INCOMPAT_FEATURE(fs->fs_ondisk_sb, 1 << i);
+		need_dirty = 1;
+	    }
+	    if (features[REISERFS_FEATURE_INCOMPAT][i] == 2) {
+		REISERFS_CLEAR_INCOMPAT_FEATURE(fs->fs_ondisk_sb, 1 << i);
+		need_dirty = 1;
+	    }
+	    if (features[REISERFS_FEATURE_COMPAT][i] == 1) {
+		REISERFS_SET_COMPAT_FEATURE(fs->fs_ondisk_sb, 1 << i);
+		need_dirty = 1;
+	    }
+	    if (features[REISERFS_FEATURE_COMPAT][i] == 2) {
+		REISERFS_CLEAR_COMPAT_FEATURE(fs->fs_ondisk_sb, 1 << i);
+		need_dirty = 1;
+	    }
+	    if (features[REISERFS_FEATURE_RO_COMPAT][i] == 1) {
+		REISERFS_SET_RO_COMPAT_FEATURE(fs->fs_ondisk_sb, 1 << i);
+		need_dirty = 1;
+	    }
+	    if (features[REISERFS_FEATURE_RO_COMPAT][i] == 2) {
+		REISERFS_CLEAR_RO_COMPAT_FEATURE(fs->fs_ondisk_sb, 1 << i);
+		need_dirty = 1;
+	    }
+	}
+    } else {
+	int i;
+	for (i = 0; i < 32; i++) {
+	    if (features[REISERFS_FEATURE_INCOMPAT][i] ||
+		features[REISERFS_FEATURE_COMPAT][i] ||
+		features[REISERFS_FEATURE_RO_COMPAT][i])
+		reiserfs_exit(1, "optional features are only available on v3.7 format filesystems\n");
+
+	}
+    }
+
+    if (need_dirty) {
+	mark_buffer_dirty (fs->fs_super_bh);
+	fs->fs_dirt = 1;
+    }
 
     if (!j_new_device_name) {
 	
@@ -759,15 +915,13 @@ int main (int argc, char **argv)
 	/* we have to put journal on main device. It is only possible if there
 	   is enough space reserved by mkreiserfs */
 
-	if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb))
-	    /* standard journal */
+	if (!has_nonstandard_journal (fs->fs_ondisk_sb))
 	    reserved = get_jp_journal_size(sb_jp(fs->fs_ondisk_sb)) + 1;
 	else
-	    /* non-standard journal */
 	    reserved = get_sb_reserved_for_journal (fs->fs_ondisk_sb);
-		
+
 	journal_size = Journal_size;
-	
+
 	if (!journal_size) {
 	    journal_size = journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1;
 	    message("Journal size has not been specified. Assuming it is the default size (%lu)", 
@@ -791,7 +945,7 @@ int main (int argc, char **argv)
     message ("Current journal parameters:");
     print_journal_params (stdout, sb_jp (fs->fs_ondisk_sb));
 
-    if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb)) {
+    if (!has_nonstandard_journal (fs->fs_ondisk_sb)) {
 	/* we have standard journal, so check if we can convert it
 	   to non-standard one */
 	
@@ -802,7 +956,9 @@ int main (int argc, char **argv)
 	}
 	*/
 	
-        if (is_reiserfs_3_6_magic_string (fs->fs_ondisk_sb))
+        if (is_reiserfs_3_7_magic_string (fs->fs_ondisk_sb))
+	    set_sb_version (fs->fs_ondisk_sb, REISERFS_FORMAT_3_7);
+        else if (is_reiserfs_3_6_magic_string (fs->fs_ondisk_sb))
 	    set_sb_version (fs->fs_ondisk_sb, REISERFS_FORMAT_3_6);
         else if (is_reiserfs_3_5_magic_string (fs->fs_ondisk_sb))
 	    set_sb_version (fs->fs_ondisk_sb, REISERFS_FORMAT_3_5);
-- 
Jeff Mahoney
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe reiserfs-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux File System Development]     [Linux BTRFS]     [Linux NFS]     [Linux Filesystems]     [Ext4 Filesystem]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Resources]

  Powered by Linux