parted (2.3-5) update-ext4-code.patch

Summary

 libparted/fs/ext2/ext2.c        |    9 ++--
 libparted/fs/ext2/ext2_fs.h     |   82 ++++++++++++++++++++++++++++++++++------
 libparted/fs/ext2/ext2_mkfs.c   |    8 +--
 libparted/fs/ext2/ext2_resize.c |   22 +++++++---
 libparted/fs/ext2/interface.c   |   46 +++++++++++++---------
 5 files changed, 122 insertions(+), 45 deletions(-)

    
download this patch

Patch contents

From: Colin Watson <cjwatson@ubuntu.com>
Forwarded: http://lists.alioth.debian.org/pipermail/parted-devel/2009-January/002503.html
Bug: http://parted.alioth.debian.org/cgi-bin/trac.cgi/ticket/188
Last-Update: 2009-01-05
Description: Improve ext4 code

Index: b/libparted/fs/ext2/ext2.c
===================================================================
--- a/libparted/fs/ext2/ext2.c
+++ b/libparted/fs/ext2/ext2.c
@@ -185,8 +185,8 @@
 
 		fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16
 			(EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group]) + diff);
-		fs->sb.s_free_blocks_count = PED_CPU_TO_LE32
-			(EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) + diff);
+		ext2_super_free_blocks_count_set(&fs->sb,
+			EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) + diff);
 		fs->metadirty |= EXT2_META_SB | EXT2_META_GD;
 	}
 	return 1;
@@ -606,7 +606,7 @@
 	if (wmeta == EXT2_META_CLEAN)
 		return 1;
 
-	fs->sb.s_r_blocks_count = PED_CPU_TO_LE32 (
+	ext2_super_r_blocks_count_set(&fs->sb,
 		fs->r_frac * (loff_t)EXT2_SUPER_BLOCKS_COUNT(fs->sb)
 				  / 100);
 
@@ -722,7 +722,8 @@
 			    EXT2_FEATURE_COMPAT_HAS_DIR_INDEX)) ||
 	    (EXT2_SUPER_FEATURE_INCOMPAT(fs->sb)
 	    		& ~(EXT2_FEATURE_INCOMPAT_FILETYPE |
-			    EXT3_FEATURE_INCOMPAT_RECOVER)) ||
+			    EXT3_FEATURE_INCOMPAT_RECOVER |
+			    EXT4_FEATURE_INCOMPAT_64BIT)) ||
 	    (EXT2_SUPER_FEATURE_RO_COMPAT(fs->sb)
 			& ~(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER |
 			    EXT2_FEATURE_RO_COMPAT_LARGE_FILE)))
Index: b/libparted/fs/ext2/ext2_fs.h
===================================================================
--- a/libparted/fs/ext2/ext2_fs.h
+++ b/libparted/fs/ext2/ext2_fs.h
@@ -176,9 +176,9 @@
 struct ext2_super_block
 {
 	uint32_t	s_inodes_count;		/* Inodes count */
-	uint32_t	s_blocks_count;		/* Blocks count */
-	uint32_t	s_r_blocks_count;	/* Reserved blocks count */
-	uint32_t	s_free_blocks_count;	/* Free blocks count */
+	uint32_t	s_blocks_count_lo;	/* Blocks count */
+	uint32_t	s_r_blocks_count_lo;	/* Reserved blocks count */
+	uint32_t	s_free_blocks_count_lo;	/* Free blocks count */
 	uint32_t	s_free_inodes_count;	/* Free inodes count */
 	uint32_t	s_first_data_block;	/* First Data Block */
 	uint32_t	s_log_block_size;	/* Block size */
@@ -237,10 +237,38 @@
 	uint32_t	s_journal_inum;		/* inode number of journal file */
 	uint32_t	s_journal_dev;		/* device number of journal file */
 	uint32_t	s_last_orphan;		/* start of list of inodes to delete */
+	uint32_t	s_hash_seed[4];		/* HTREE hash seed */
+	uint8_t		s_def_hash_version;	/* Default hash version to use */
+	uint8_t		s_reserved_char_pad;
+	uint16_t	s_desc_size;		/* size of group descriptor */
+	uint32_t	s_default_mount_opts;
+	uint32_t	s_first_meta_bg;	/* First metablock block group */
+	uint32_t	s_mkfs_time;		/* When the filesystem was created */
+	uint32_t	s_jnl_blocks[17];	/* Backup of the journal inode */
+	/* 64bit support valid if EXT4_FEATURE_INCOMPAT_64BIT */
+	uint32_t	s_blocks_count_hi;	/* Blocks count */
+	uint32_t	s_r_blocks_count_hi;	/* Reserved blocks count */
+	uint32_t	s_free_blocks_count_hi;	/* Free blocks count */
+	uint16_t	s_min_extra_isize;	/* All inodes have at least # bytes */
+	uint16_t	s_want_extra_isize;	/* New inodes should reserve # bytes */
+	uint32_t	s_flags;		/* Miscellaneous flags */
+	uint16_t	s_raid_stride;		/* RAID stride */
+	uint16_t	s_mmp_interval;		/* # seconds to wait in MMP checking */
+	uint64_t	s_mmp_block;		/* Block for multi-mount protection */
+	uint32_t	s_raid_stripe_width;	/* blocks on all data disks (N*stride) */
+	uint8_t		s_log_groups_per_flex;	/* FLEX_BG group size */
+	uint8_t		s_reserved_char_pad2;
+	uint16_t	s_reserved_pad;
 
-	uint32_t	s_reserved[197];	/* Padding to the end of the block */
+	uint32_t	s_reserved[162];	/* Padding to the end of the block */
 };
 
+#define EXT2_SUPER_FEATURE_COMPAT(sb)	(PED_LE32_TO_CPU((sb).s_feature_compat))
+#define EXT2_SUPER_FEATURE_INCOMPAT(sb) \
+		(PED_LE32_TO_CPU((sb).s_feature_incompat))
+#define EXT2_SUPER_FEATURE_RO_COMPAT(sb) \
+		(PED_LE32_TO_CPU((sb).s_feature_ro_compat))
+
 #define EXT2_DIRENT_INODE(dir_ent)	(PED_LE32_TO_CPU((dir_ent).inode))
 #define EXT2_DIRENT_REC_LEN(dir_ent)	(PED_LE16_TO_CPU((dir_ent).rec_len))
 #define EXT2_DIRENT_NAME_LEN(dir_ent)	((dir_ent).name_len)
@@ -273,10 +301,45 @@
 #define EXT2_INODE_BLOCK(inode, blk)	(PED_LE32_TO_CPU((inode).i_block[blk]))
 
 #define EXT2_SUPER_INODES_COUNT(sb)	(PED_LE32_TO_CPU((sb).s_inodes_count))
-#define EXT2_SUPER_BLOCKS_COUNT(sb)	(PED_LE32_TO_CPU((sb).s_blocks_count))
-#define EXT2_SUPER_R_BLOCKS_COUNT(sb)	(PED_LE32_TO_CPU((sb).s_r_blocks_count))
+
+#define EXT2_SUPER_BLOCKS_COUNT(sb) \
+		((EXT2_SUPER_FEATURE_INCOMPAT((sb)) & EXT4_FEATURE_INCOMPAT_64BIT) \
+		 ? (((uint64_t) PED_LE32_TO_CPU((sb).s_blocks_count_hi) << 32) \
+		    | PED_LE32_TO_CPU((sb).s_blocks_count_lo)) \
+		 : PED_LE32_TO_CPU((sb).s_blocks_count_lo))
+#define EXT2_SUPER_R_BLOCKS_COUNT(sb) \
+		((EXT2_SUPER_FEATURE_INCOMPAT((sb)) & EXT4_FEATURE_INCOMPAT_64BIT) \
+		 ? (((uint64_t) PED_LE32_TO_CPU((sb).s_r_blocks_count_hi) << 32) \
+		    | PED_LE32_TO_CPU((sb).s_r_blocks_count_lo)) \
+		 : PED_LE32_TO_CPU((sb).s_r_blocks_count_lo))
+
 #define EXT2_SUPER_FREE_BLOCKS_COUNT(sb) \
-		(PED_LE32_TO_CPU((sb).s_free_blocks_count))
+		((EXT2_SUPER_FEATURE_INCOMPAT((sb)) & EXT4_FEATURE_INCOMPAT_64BIT) \
+		 ? (((uint64_t) PED_LE32_TO_CPU((sb).s_free_blocks_count_hi) << 32) \
+		    | PED_LE32_TO_CPU((sb).s_free_blocks_count_lo)) \
+		 : PED_LE32_TO_CPU((sb).s_free_blocks_count_lo))
+
+static inline void ext2_super_blocks_count_set(struct ext2_super_block *sb, uint64_t blk)
+{
+	sb->s_blocks_count_lo = PED_CPU_TO_LE32((uint32_t) blk);
+	if (EXT2_SUPER_FEATURE_INCOMPAT(*sb) & EXT4_FEATURE_INCOMPAT_64BIT)
+		sb->s_blocks_count_hi = PED_CPU_TO_LE32(blk >> 32);
+}
+
+static inline void ext2_super_free_blocks_count_set(struct ext2_super_block *sb, uint64_t blk)
+{
+	sb->s_free_blocks_count_lo = PED_CPU_TO_LE32((uint32_t) blk);
+	if (EXT2_SUPER_FEATURE_INCOMPAT(*sb) & EXT4_FEATURE_INCOMPAT_64BIT)
+		sb->s_free_blocks_count_hi = PED_CPU_TO_LE32(blk >> 32);
+}
+
+static inline void ext2_super_r_blocks_count_set(struct ext2_super_block *sb, uint64_t blk)
+{
+	sb->s_r_blocks_count_lo = PED_CPU_TO_LE32((uint32_t) blk);
+	if (EXT2_SUPER_FEATURE_INCOMPAT(*sb) & EXT4_FEATURE_INCOMPAT_64BIT)
+		sb->s_r_blocks_count_hi = PED_CPU_TO_LE32(blk >> 32);
+}
+
 #define EXT2_SUPER_FREE_INODES_COUNT(sb) \
 		(PED_LE32_TO_CPU((sb).s_free_inodes_count))
 #define EXT2_SUPER_FIRST_DATA_BLOCK(sb) \
@@ -310,11 +373,6 @@
 #define EXT2_SUPER_FIRST_INO(sb)	(PED_LE32_TO_CPU((sb).s_first_ino))
 #define EXT2_SUPER_INODE_SIZE(sb)	(PED_LE16_TO_CPU((sb).s_inode_size))
 #define EXT2_SUPER_BLOCK_GROUP_NR(sb)	(PED_LE16_TO_CPU((sb).s_block_group_nr))
-#define EXT2_SUPER_FEATURE_COMPAT(sb)	(PED_LE32_TO_CPU((sb).s_feature_compat))
-#define EXT2_SUPER_FEATURE_INCOMPAT(sb) \
-		(PED_LE32_TO_CPU((sb).s_feature_incompat))
-#define EXT2_SUPER_FEATURE_RO_COMPAT(sb) \
-		(PED_LE32_TO_CPU((sb).s_feature_ro_compat))
 #define EXT2_SUPER_UUID(sb)		((sb).s_uuid)
 #define EXT2_SUPER_VOLUME_NAME(sb)	((sb).s_volume_name)
 #define EXT2_SUPER_LAST_MOUNTED(sb)	((sb).s_last_mounted)
Index: b/libparted/fs/ext2/ext2_mkfs.c
===================================================================
--- a/libparted/fs/ext2/ext2_mkfs.c
+++ b/libparted/fs/ext2/ext2_mkfs.c
@@ -240,7 +240,7 @@
 		gd[i].bg_reserved[1] = 0;
 		gd[i].bg_reserved[2] = 0;
 
-		sb->s_free_blocks_count = PED_CPU_TO_LE32 (
+		ext2_super_free_blocks_count_set(sb,
 			EXT2_SUPER_FREE_BLOCKS_COUNT(*sb)
 			+ EXT2_GROUP_FREE_BLOCKS_COUNT(gd[i]));
 	}
@@ -425,14 +425,14 @@
 	memset(sb, 0, 1024);
 
 	sb->s_inodes_count = PED_CPU_TO_LE32(numgroups * inodes_per_group);
-	sb->s_blocks_count = PED_CPU_TO_LE32(numblocks);
-	sb->s_r_blocks_count = PED_CPU_TO_LE32(((uint64_t)numblocks
+	ext2_super_blocks_count_set(sb, numblocks);
+	ext2_super_r_blocks_count_set(sb, ((uint64_t)numblocks
 				* reserved_block_percentage) / 100);
 
 	/* hack: this get's inc'd as we go through each group in
 	 * ext2_mkfs_write_meta()
 	 */
-	sb->s_free_blocks_count = 0;
+	ext2_super_free_blocks_count_set(sb, 0);
 	sb->s_free_inodes_count = PED_CPU_TO_LE32 (numgroups
 							* inodes_per_group);
 	sb->s_first_data_block = PED_CPU_TO_LE32(first_block);
Index: a/libparted/fs/ext2/ext2_resize.c
===================================================================
--- a/libparted/fs/ext2/ext2_resize.c
+++ a/libparted/fs/ext2/ext2_resize.c
@@ -105,9 +105,9 @@
 	fs->sb.s_inodes_count = PED_CPU_TO_LE32(
 		EXT2_SUPER_INODES_COUNT(fs->sb)
 		+ EXT2_SUPER_INODES_PER_GROUP(fs->sb));
-	fs->sb.s_blocks_count = PED_CPU_TO_LE32(
+	ext2_super_blocks_count_set(&fs->sb,
 		EXT2_SUPER_BLOCKS_COUNT(fs->sb) + groupsize);
-	fs->sb.s_free_blocks_count = PED_CPU_TO_LE32(
+	ext2_super_free_blocks_count_set(&fs->sb,
 		EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) + groupsize - admin);
 	fs->sb.s_free_inodes_count = PED_CPU_TO_LE32(
 		EXT2_SUPER_FREE_INODES_COUNT(fs->sb)
@@ -304,9 +304,9 @@
 	fs->sb.s_inodes_count = PED_CPU_TO_LE32(
 		EXT2_SUPER_INODES_COUNT(fs->sb)
 		- EXT2_SUPER_INODES_PER_GROUP(fs->sb));
-	fs->sb.s_blocks_count = PED_CPU_TO_LE32(
+	ext2_super_blocks_count_set(&fs->sb,
 		EXT2_SUPER_BLOCKS_COUNT(fs->sb) - groupsize);
-	fs->sb.s_free_blocks_count = PED_CPU_TO_LE32(
+	ext2_super_free_blocks_count_set(&fs->sb,
 		EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) - (groupsize - admin));
 	fs->sb.s_free_inodes_count = PED_CPU_TO_LE32(
 		EXT2_SUPER_FREE_INODES_COUNT(fs->sb)
@@ -358,7 +358,7 @@
 	for (i=gblocks;i<newsize;i++)
 		ext2_set_block_state(fs, groupoff + i, 0, 1);
 
-	fs->sb.s_blocks_count = PED_CPU_TO_LE32(
+	ext2_super_blocks_count_set(&fs->sb,
 		EXT2_SUPER_BLOCKS_COUNT(fs->sb) + newsize - gblocks);
 	fs->metadirty |= EXT2_META_SB;
 
@@ -433,9 +433,9 @@
 	}
 
 	i = gblocks - newsize;
-	fs->sb.s_blocks_count = PED_CPU_TO_LE32(
+	ext2_super_blocks_count_set(&fs->sb,
 		EXT2_SUPER_BLOCKS_COUNT(fs->sb) - i);
-	fs->sb.s_free_blocks_count = PED_CPU_TO_LE32(
+	ext2_super_free_blocks_count_set(&fs->sb,
 		EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) - i);
 	fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16(
 		EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group]) - i);
@@ -685,6 +685,14 @@
 		fs->metadirty |= EXT2_META_SB;
 	}
 
+	if (EXT2_SUPER_FEATURE_INCOMPAT(fs->sb)
+			& EXT4_FEATURE_INCOMPAT_EXTENTS) {
+		ped_exception_throw (
+			PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
+			_("Parted cannot resize ext4 file systems yet."));
+		return 0;
+	}
+
 	if (!ext2_determine_itoffset(fs) && ped_exception_throw (
                         PED_EXCEPTION_WARNING,
                         PED_EXCEPTION_OK_CANCEL,
Index: b/libparted/fs/ext2/interface.c
===================================================================
--- a/libparted/fs/ext2/interface.c
+++ b/libparted/fs/ext2/interface.c
@@ -28,6 +28,7 @@
 
 static PedFileSystemType _ext2_type;
 static PedFileSystemType _ext3_type;
+static PedFileSystemType _ext4_type;
 
 struct ext2_dev_handle* ext2_make_dev_handle_from_parted_geometry(PedGeometry* geom);
 
@@ -51,29 +52,25 @@
 
 		is_ext3 = (EXT2_SUPER_FEATURE_COMPAT (*sb)
 			   & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0;
-		if (is_ext3) {
-			is_ext4 = ((EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
-				    & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
-				   || (EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
-				       & EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
-				   || (EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
-				       & EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
-				   || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
-				       & EXT4_FEATURE_INCOMPAT_EXTENTS)
-				   || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
-				       & EXT4_FEATURE_INCOMPAT_64BIT)
-				   || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
-				       & EXT4_FEATURE_INCOMPAT_FLEX_BG));
-			if (is_ext4)
-				is_ext3 = 0;
-		}
+		is_ext4 = ((EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
+			    & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+			   || (EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
+			       & EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
+			   || (EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
+			       & EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
+			   || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
+			       & EXT4_FEATURE_INCOMPAT_EXTENTS)
+			   || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
+			       & EXT4_FEATURE_INCOMPAT_64BIT)
+			   || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
+			       & EXT4_FEATURE_INCOMPAT_FLEX_BG));
 		free (sb);
 
 		if (expect_ext_ver == 2 && (is_ext3 || is_ext4))
 			return NULL;
-		if (expect_ext_ver == 3 && !is_ext3)
+		if (expect_ext_ver == 3 && (!is_ext3 || is_ext4))
 			return NULL;
-		else if (expect_ext_ver == 4 && !is_ext4)
+		if (expect_ext_ver == 4 && !is_ext4)
 			return NULL;
 
 		if (version > 0 && group_nr > 0) {
@@ -366,6 +363,18 @@
 
 static PedFileSystemOps _ext4_ops = {
 	probe:		_ext4_probe,
+#ifndef DISCOVER_ONLY
+	clobber:	_ext2_clobber,
+	open:		_ext2_open,
+	create:         NULL,
+	close:		_ext2_close,
+	check:          _ext2_check,
+	resize:		_ext2_resize,
+	copy:           NULL,
+	get_create_constraint:	_ext2_get_create_constraint,
+	get_copy_constraint:	NULL,
+	get_resize_constraint:	_ext2_get_resize_constraint
+#else /* !DISCOVER_ONLY */
 	clobber:	NULL,
 	open:		NULL,
 	create:         NULL,
@@ -376,6 +385,7 @@
 	get_create_constraint:	NULL,
 	get_copy_constraint:	NULL,
 	get_resize_constraint:	NULL
+#endif /* !DISCOVER_ONLY */
 };
 
 #define EXT23_BLOCK_SIZES ((int[6]){512, 1024, 2048, 4096, 8192, 0})