@@ -448,6 +448,24 @@ void check_exclude_inode(e2fsck_t ctx)
clear_problem_context(&pctx);
+ /* Migrate from old to new Next3 on-disk format */
+ if (fs->super->s_feature_compat &
+ NEXT3_FEATURE_COMPAT_EXCLUDE_INODE_OLD) {
+ /* Move exclude inode from old to new position */
+ retval = ext2fs_read_inode(fs, EXT2_EXCLUDE_INO_OLD, &inode);
+ if (!retval) {
+ e2fsck_write_inode(ctx, EXT2_EXCLUDE_INO, &inode,
+ "copy_old_exclude_ino");
+ memset(&inode, 0, sizeof(inode));
+ e2fsck_write_inode(ctx, EXT2_EXCLUDE_INO_OLD, &inode,
+ "clear_old_exclude_ino");
+ /* Clear old exclude inode flag */
+ fs->super->s_feature_compat &=
+ ~NEXT3_FEATURE_COMPAT_EXCLUDE_INODE_OLD;
+ ext2fs_mark_super_dirty(fs);
+ }
+ }
+
/* Read the exclude inode */
pctx.ino = EXT2_EXCLUDE_INO;
retval = ext2fs_read_inode(fs, EXT2_EXCLUDE_INO, &inode);
@@ -51,6 +51,7 @@
#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */
#define EXT2_JOURNAL_INO 8 /* Journal inode */
#define EXT2_EXCLUDE_INO 9 /* The "exclude" inode, for snapshots */
+#define EXT2_EXCLUDE_INO_OLD 10 /* Old exclude inode */
/* First non-reserved inode for old ext2 filesystems */
#define EXT2_GOOD_OLD_FIRST_INO 11
@@ -150,6 +151,9 @@ struct ext2_group_desc
__u16 bg_checksum; /* crc16(s_uuid+grouo_num+group_desc)*/
};
+#define bg_exclude_bitmap_old bg_reserved[0] /* Old exclude bitmap cache */
+#define bg_cow_bitmap_old bg_reserved[1] /* Old COW bitmap cache */
+
/*
* Structure of a blocks group descriptor
*/
@@ -632,6 +636,12 @@ struct ext2_super_block {
#define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START)
+/* old snapshot field positions */
+#define s_snapshot_list_old s_reserved[151] /* Old snapshot list head */
+#define s_snapshot_r_blocks_old s_reserved[152] /* Old reserved for snapshot */
+#define s_snapshot_id_old s_reserved[153] /* Old active snapshot ID */
+#define s_snapshot_inum_old s_reserved[154] /* Old active snapshot inode */
+
/*
* Codes for operating systems
*/
@@ -687,6 +697,8 @@ struct ext2_super_block {
#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
#define EXT2_FEATURE_COMPAT_LAZY_BG 0x0040
#define EXT2_FEATURE_COMPAT_EXCLUDE_INODE 0x0080
+#define NEXT3_FEATURE_COMPAT_BIG_JOURNAL_OLD 0x1000 /* Old big journal */
+#define NEXT3_FEATURE_COMPAT_EXCLUDE_INODE_OLD 0x2000 /* Old exclude inode */
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
@@ -696,6 +708,10 @@ struct ext2_super_block {
#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
#define EXT4_FEATURE_RO_COMPAT_HAS_SNAPSHOT 0x0080
+#define NEXT3_FEATURE_RO_COMPAT_HAS_SNAPSHOT_OLD 0x1000 /* Old has snapshots */
+#define NEXT3_FEATURE_RO_COMPAT_IS_SNAPSHOT_OLD 0x2000 /* Old is snapshot */
+#define NEXT3_FEATURE_RO_COMPAT_FIX_SNAPSHOT_OLD 0x4000 /* Old fix snapshot */
+#define NEXT3_FEATURE_RO_COMPAT_FIX_EXCLUDE_OLD 0x8000 /* Old fix exclude */
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
@@ -521,6 +521,7 @@ typedef struct ext2_icount *ext2_icount_t;
EXT2_FEATURE_COMPAT_IMAGIC_INODES|\
EXT3_FEATURE_COMPAT_HAS_JOURNAL|\
EXT2_FEATURE_COMPAT_EXCLUDE_INODE|\
+ NEXT3_FEATURE_COMPAT_EXCLUDE_INODE_OLD|\
EXT2_FEATURE_COMPAT_RESIZE_INODE|\
EXT2_FEATURE_COMPAT_DIR_INDEX|\
EXT2_FEATURE_COMPAT_EXT_ATTR)
@@ -205,6 +205,51 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
goto cleanup;
}
+ /* Migrate super from old to new Next3 on-disk format */
+ if ((fs->super->s_feature_ro_compat &
+ NEXT3_FEATURE_RO_COMPAT_HAS_SNAPSHOT_OLD) &&
+ !(fs->super->s_feature_ro_compat &
+ EXT4_FEATURE_RO_COMPAT_HAS_SNAPSHOT)) {
+ struct ext2_super_block *sb = fs->super;
+
+ /* Copy snapshot fields to new positions */
+ sb->s_snapshot_inum = sb->s_snapshot_inum_old;
+ sb->s_snapshot_id = sb->s_snapshot_id_old;
+ sb->s_snapshot_r_blocks_count = sb->s_snapshot_r_blocks_old;
+ sb->s_snapshot_list = sb->s_snapshot_list_old;
+ /* Clear old snapshot fields */
+ sb->s_snapshot_inum_old = 0;
+ sb->s_snapshot_id_old = 0;
+ sb->s_snapshot_r_blocks_old = 0;
+ sb->s_snapshot_list_old = 0;
+ /* Copy snapshot flags to new positions */
+ fs->super->s_feature_ro_compat |=
+ EXT4_FEATURE_RO_COMPAT_HAS_SNAPSHOT;
+ if (fs->super->s_feature_compat &
+ NEXT3_FEATURE_COMPAT_EXCLUDE_INODE_OLD)
+ fs->super->s_feature_compat |=
+ EXT2_FEATURE_COMPAT_EXCLUDE_INODE;
+ if (fs->super->s_feature_ro_compat &
+ NEXT3_FEATURE_RO_COMPAT_FIX_SNAPSHOT_OLD)
+ fs->super->s_flags |= EXT2_FLAGS_FIX_SNAPSHOT;
+ if (fs->super->s_feature_ro_compat &
+ NEXT3_FEATURE_RO_COMPAT_FIX_EXCLUDE_OLD)
+ fs->super->s_flags |= EXT2_FLAGS_FIX_EXCLUDE;
+ /* Clear old snapshot flags */
+ fs->super->s_feature_ro_compat &=
+ ~(NEXT3_FEATURE_RO_COMPAT_HAS_SNAPSHOT_OLD|
+ NEXT3_FEATURE_RO_COMPAT_IS_SNAPSHOT_OLD|
+ NEXT3_FEATURE_RO_COMPAT_FIX_SNAPSHOT_OLD|
+ NEXT3_FEATURE_RO_COMPAT_FIX_EXCLUDE_OLD);
+ /* Clear deprecated big journal flag */
+ fs->super->s_feature_compat &=
+ ~NEXT3_FEATURE_COMPAT_BIG_JOURNAL_OLD;
+ /* Keep old exclude inode flag b/c inode was not moved yet */
+ if (flags & EXT2_FLAG_RW)
+ /* in read-only mode just convert the in-memory copy */
+ ext2fs_mark_super_dirty(fs);
+ }
+
/*
* Check for feature set incompatibility
*/
@@ -252,6 +252,28 @@ errcode_t ext2fs_create_exclude_inode(ext2_filsys fs, int flags)
indir_buf = (__u32 *)((char *)dindir_buf + 1*fs->blocksize);
data_buf = (__u32 *)((char *)dindir_buf + 2*fs->blocksize);
+ /* Migrate from old to new Next3 on-disk format */
+ if (fs->super->s_feature_compat &
+ NEXT3_FEATURE_COMPAT_EXCLUDE_INODE_OLD) {
+ /* Move exclude inode from old to new position */
+ retval = ext2fs_read_inode(fs, EXT2_EXCLUDE_INO_OLD, &inode);
+ if (!retval) {
+ retval = ext2fs_write_inode(fs, EXT2_EXCLUDE_INO,
+ &inode);
+ if (retval)
+ goto out_free;
+ memset(&inode, 0, sizeof(inode));
+ retval = ext2fs_write_inode(fs, EXT2_EXCLUDE_INO_OLD,
+ &inode);
+ if (retval)
+ goto out_free;
+ /* Clear old exclude inode flag */
+ fs->super->s_feature_compat &=
+ ~NEXT3_FEATURE_COMPAT_EXCLUDE_INODE_OLD;
+ ext2fs_mark_super_dirty(fs);
+ }
+ }
+
retval = ext2fs_read_inode(fs, EXT2_EXCLUDE_INO, &inode);
if (retval)
goto out_free;
@@ -377,6 +399,12 @@ errcode_t ext2fs_create_exclude_inode(ext2_filsys fs, int flags)
}
}
fs->exclude_blks[grp] = data_blk;
+ /* reset old exclude/cow bitmap cache to zero */
+ if (gd->bg_exclude_bitmap_old || gd->bg_cow_bitmap_old) {
+ gd->bg_exclude_bitmap_old = 0;
+ gd->bg_cow_bitmap_old = 0;
+ gdt_dirty = 1;
+ }
#ifdef EXCLUDE_INO_PROGRESS
printf("\b\b\b\b\b\b\b\b\b\b\b%5d/%5d", grp,
fs->group_desc_count);
@@ -76,6 +76,11 @@ void ext2fs_swap_super(struct ext2_super_block * sb)
sb->s_snapshot_r_blocks_count =
ext2fs_swab64(sb->s_snapshot_r_blocks_count);
sb->s_snapshot_list = ext2fs_swab32(sb->s_snapshot_list);
+ sb->s_snapshot_inum_old = ext2fs_swab32(sb->s_snapshot_inum_old);
+ sb->s_snapshot_id_old = ext2fs_swab32(sb->s_snapshot_id_old);
+ sb->s_snapshot_r_blocks_old =
+ ext2fs_swab32(sb->s_snapshot_r_blocks_old);
+ sb->s_snapshot_list_old = ext2fs_swab32(sb->s_snapshot_list_old);
for (i=0; i < 4; i++)
sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]);
@@ -373,6 +373,23 @@ static void remove_exclude_inode(ext2_filsys fs)
struct ext2_inode inode;
ino_t ino = EXT2_EXCLUDE_INO;
errcode_t retval;
+ struct ext2_group_desc *gd;
+ int i;
+
+ if (fs->super->s_feature_compat &
+ NEXT3_FEATURE_COMPAT_EXCLUDE_INODE_OLD) {
+ /* Remove old exclude inode */
+ ino = EXT2_EXCLUDE_INO_OLD;
+ /* Clear old exclude inode flag */
+ fs->super->s_feature_compat &=
+ ~NEXT3_FEATURE_COMPAT_EXCLUDE_INODE_OLD;
+ /* Reset old exclude/cow bitmap cache to zero */
+ for (i = 0; i < fs->group_desc_count; i++) {
+ gd = ext2fs_group_desc(fs, fs->group_desc, i);
+ gd->bg_exclude_bitmap_old = 0;
+ gd->bg_cow_bitmap_old = 0;
+ }
+ }
/* clear fix_exclude flag */
fs->super->s_flags &= ~EXT2_FLAGS_FIX_EXCLUDE;
Detect old 'has_snapshot' feature on ext2fs_open(), migrate snapshot fields and flags and set new 'has_snapshot' feature. Detect old 'exclude_inode' feature on create/check_exclude_inode(), copy old exclude inode to new exclude inode location and set the new 'exclude_inode' feature. Signed-off-by: Amir Goldstein <amir73il@users.sf.net> --- e2fsck/super.c | 18 ++++++++++++++++++ lib/ext2fs/ext2_fs.h | 16 ++++++++++++++++ lib/ext2fs/ext2fs.h | 1 + lib/ext2fs/openfs.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ lib/ext2fs/res_gdt.c | 28 ++++++++++++++++++++++++++++ lib/ext2fs/swapfs.c | 5 +++++ misc/tune2fs.c | 17 +++++++++++++++++ 7 files changed, 130 insertions(+), 0 deletions(-)