[rfc, patch 2/3] larger block group descriptors

Alexandre Ratchov <[email protected]>
Newsgroups gmane.comp.file-systems.ext2.devel
Message-ID <[email protected]>
make e2fsprogs-1.39 use variable length block group descriptors. mke2fs,
debugfs, dumpe2fs and fsck should work.

Index: e2fsprogs-1.39/lib/ext2fs/swapfs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/swapfs.c	2006-06-07 13:49:36.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/swapfs.c	2006-06-07 13:50:04.000000000 +0200
@@ -60,6 +60,7 @@ void ext2fs_swap_super(struct ext2_super
 	sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum);
 	sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev);
 	sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan);
+	sb->s_desc_size = ext2fs_swab16(sb->s_desc_size);
 	sb->s_default_mount_opts = ext2fs_swab32(sb->s_default_mount_opts);
 	sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg);
 	sb->s_mkfs_time = ext2fs_swab32(sb->s_mkfs_time);
Index: e2fsprogs-1.39/lib/ext2fs/ext2fs.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2fs.h	2006-06-07 13:49:36.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2fs.h	2006-06-07 13:50:04.000000000 +0200
@@ -210,6 +210,7 @@ struct struct_ext2_filsys {
 	char *				device_name;
 	struct ext2_super_block	* 	super;
 	unsigned int			blocksize;
+	unsigned int			desc_size;
 	int				fragsize;
 	dgrp_t				group_desc_count;
 	unsigned long			desc_blocks;
@@ -453,12 +454,14 @@ typedef struct ext2_icount *ext2_icount_
 					 EXT2_FEATURE_INCOMPAT_COMPRESSION|\
 					 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
 					 EXT2_FEATURE_INCOMPAT_META_BG|\
-					 EXT3_FEATURE_INCOMPAT_RECOVER)
+					 EXT3_FEATURE_INCOMPAT_RECOVER|\
+					 EXT3_FEATURE_INCOMPAT_DESC_SIZE)
 #else
 #define EXT2_LIB_FEATURE_INCOMPAT_SUPP	(EXT2_FEATURE_INCOMPAT_FILETYPE|\
 					 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
 					 EXT2_FEATURE_INCOMPAT_META_BG|\
-					 EXT3_FEATURE_INCOMPAT_RECOVER)
+					 EXT3_FEATURE_INCOMPAT_RECOVER|\
+					 EXT3_FEATURE_INCOMPAT_DESC_SIZE)
 #endif
 #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
 					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
Index: e2fsprogs-1.39/lib/ext2fs/openfs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/openfs.c	2006-06-07 13:49:36.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/openfs.c	2006-06-07 13:50:04.000000000 +0200
@@ -39,7 +39,7 @@ blk_t ext2fs_descriptor_block_loc(ext2_f
 	    (i < fs->super->s_first_meta_bg))
 		return (group_block + i + 1);
 
-	bg = (fs->blocksize / sizeof (struct ext2_group_desc)) * i;
+	bg = (fs->blocksize / fs->desc_size) * i;
 	if (ext2fs_bg_has_super(fs, bg))
 		has_super = 1;
 	ret_blk = (fs->super->s_first_data_block + has_super + 
@@ -90,6 +90,7 @@ errcode_t ext2fs_open2(const char *name,
 	blk_t		group_block, blk;
 	char		*dest, *cp;
 	struct ext2_group_desc *gdp;
+	char		shadow_block[EXT2_MAX_BLOCK_SIZE];
 	
 	EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
 
@@ -232,6 +233,13 @@ errcode_t ext2fs_open2(const char *name,
 			goto cleanup;
 		}
 	}
+	
+	if (fs->super->s_feature_incompat & 
+	    EXT3_FEATURE_INCOMPAT_DESC_SIZE) {
+		fs->desc_size = EXT2_DESC_SIZE(fs->super);
+	} else {
+		fs->desc_size = EXT2_MIN_DESC_SIZE;
+	}
 	/*
 	 * Set the blocksize to the filesystem's blocksize.
 	 */
@@ -270,21 +278,22 @@ errcode_t ext2fs_open2(const char *name,
 		goto cleanup;
 	if (!group_block)
 		group_block = fs->super->s_first_data_block;
-	dest = (char *) fs->group_desc;
-	groups_per_block = fs->blocksize / sizeof(struct ext2_group_desc);
+	gdp = fs->group_desc;
+	groups_per_block = fs->blocksize / fs->desc_size;
 	for (i=0 ; i < fs->desc_blocks; i++) {
 		blk = ext2fs_descriptor_block_loc(fs, group_block, i);
-		retval = io_channel_read_blk(fs->io, blk, 1, dest);
+		retval = io_channel_read_blk(fs->io, blk, 1, shadow_block);
 		if (retval)
 			goto cleanup;
+		
+		for (j=0; j < groups_per_block; j++) {
+			*gdp = *(struct ext2_group_desc *)(shadow_block + j * fs->desc_size);
 #ifdef EXT2FS_ENABLE_SWAPFS
-		if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
-			gdp = (struct ext2_group_desc *) dest;
-			for (j=0; j < groups_per_block; j++)
-				ext2fs_swap_group_desc(gdp++);
-		}
+			if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+					ext2fs_swap_group_desc(gdp);
 #endif
-		dest += fs->blocksize;
+			gdp++;
+		}
 	}
 
 	*ret_fs = fs;
Index: e2fsprogs-1.39/lib/ext2fs/closefs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/closefs.c	2006-06-07 13:49:36.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/closefs.c	2006-06-07 13:50:04.000000000 +0200
@@ -81,7 +81,7 @@ int ext2fs_super_and_bgd_loc(ext2_filsys
 		super_blk = group_block;
 		numblocks--;
 	}
-	meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
+	meta_bg_size = (fs->blocksize / fs->desc_size);
 	meta_bg = group / meta_bg_size;
 
 	if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
@@ -221,33 +221,34 @@ errcode_t ext2fs_flush(ext2_filsys fs)
 
 	fs->super->s_wtime = fs->now ? fs->now : time(NULL);
 	fs->super->s_block_group_nr = 0;
+
+	retval = ext2fs_get_mem((size_t)(fs->blocksize * fs->desc_blocks),
+				&group_shadow);
+	if (retval)
+		goto errout;
+	memset(group_shadow, 0, (size_t) fs->blocksize * fs->desc_blocks);
+
+	/* swap the group descriptors */
+	for (j=0, s=fs->group_desc, t=group_shadow;
+	     j < fs->group_desc_count; j++, s++) {
+		*t = *s;
+#ifdef EXT2FS_ENABLE_SWAPFS
+		if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+			ext2fs_swap_group_desc(t);
+#endif
+		t = (struct ext2_group_desc *)((__u8 *)t + fs->desc_size);
+	}
+
 #ifdef EXT2FS_ENABLE_SWAPFS
 	if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
-		retval = EXT2_ET_NO_MEMORY;
 		retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
 		if (retval)
 			goto errout;
-		retval = ext2fs_get_mem((size_t)(fs->blocksize *
-						 fs->desc_blocks),
-					&group_shadow);
-		if (retval)
-			goto errout;
-		memset(group_shadow, 0, (size_t) fs->blocksize *
-		       fs->desc_blocks);
-
-		/* swap the group descriptors */
-		for (j=0, s=fs->group_desc, t=group_shadow;
-		     j < fs->group_desc_count; j++, t++, s++) {
-			*t = *s;
-			ext2fs_swap_group_desc(t);
-		}
 	} else {
 		super_shadow = fs->super;
-		group_shadow = fs->group_desc;
 	}
 #else
 	super_shadow = fs->super;
-	group_shadow = fs->group_desc;
 #endif
 	
 	/*
Index: e2fsprogs-1.39/lib/ext2fs/ext2_fs.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2_fs.h	2006-06-07 13:49:36.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2_fs.h	2006-06-07 13:50:04.000000000 +0200
@@ -190,6 +190,9 @@ struct ext2_dx_countlimit {
 /*
  * Macro-instructions used to manage group descriptors
  */
+#define EXT2_MIN_DESC_SIZE		32
+#define EXT2_MAX_DESC_SIZE		EXT2_MIN_BLOCK_SIZE
+#define EXT2_DESC_SIZE(s)		(EXT2_SB(s)->s_desc_size)
 #define EXT2_BLOCKS_PER_GROUP(s)	(EXT2_SB(s)->s_blocks_per_group)
 #define EXT2_INODES_PER_GROUP(s)	(EXT2_SB(s)->s_inodes_per_group)
 #define EXT2_INODES_PER_BLOCK(s)	(EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
@@ -200,7 +203,7 @@ struct ext2_dx_countlimit {
 #define EXT2_DESC_PER_BLOCK(s)		(EXT2_SB(s)->s_desc_per_block)
 #define EXT2_DESC_PER_BLOCK_BITS(s)	(EXT2_SB(s)->s_desc_per_block_bits)
 #else
-#define EXT2_DESC_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
+#define EXT2_DESC_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s))
 #endif
 
 /*
@@ -521,7 +524,7 @@ struct ext2_super_block {
 	__u32	s_hash_seed[4];		/* HTREE hash seed */
 	__u8	s_def_hash_version;	/* Default hash version to use */
 	__u8	s_jnl_backup_type; 	/* Default type of journal backup */
-	__u16	s_reserved_word_pad;
+	__u16	s_desc_size;		/* size of group descriptor */
 	__u32	s_default_mount_opts;
 	__u32	s_first_meta_bg;	/* First metablock group */
 	__u32	s_mkfs_time;		/* When the filesystem was created */
@@ -582,9 +585,9 @@ struct ext2_super_block {
 #define EXT3_FEATURE_INCOMPAT_RECOVER		0x0004 /* Needs recovery */
 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008 /* Journal device */
 #define EXT2_FEATURE_INCOMPAT_META_BG		0x0010
+#define EXT3_FEATURE_INCOMPAT_DESC_SIZE		0x0020
 #define EXT3_FEATURE_INCOMPAT_EXTENTS		0x0040
 
-
 #define EXT2_FEATURE_COMPAT_SUPP	0
 #define EXT2_FEATURE_INCOMPAT_SUPP	(EXT2_FEATURE_INCOMPAT_FILETYPE)
 #define EXT2_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
Index: e2fsprogs-1.39/lib/ext2fs/initialize.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/initialize.c	2006-06-07 13:49:36.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/initialize.c	2006-06-07 13:50:04.000000000 +0200
@@ -67,7 +67,7 @@ static unsigned int calc_reserved_gdt_bl
 {
 	struct ext2_super_block *sb = fs->super;
 	unsigned long bpg = sb->s_blocks_per_group;
-	unsigned int gdpb = fs->blocksize / sizeof(struct ext2_group_desc);
+	unsigned int gdpb = fs->blocksize / fs->desc_size;
 	unsigned long max_blocks = 0xffffffff;
 	unsigned long rsv_groups;
 	unsigned int rsv_gdb;
@@ -149,6 +149,7 @@ errcode_t ext2fs_initialize(const char *
 
 	set_field(s_log_block_size, 0);	/* default blocksize: 1024 bytes */
 	set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */
+	set_field(s_desc_size, EXT2_MIN_DESC_SIZE);
 	set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
 	set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
 	set_field(s_errors, EXT2_ERRORS_DEFAULT);
@@ -178,6 +179,7 @@ errcode_t ext2fs_initialize(const char *
 
 	fs->blocksize = EXT2_BLOCK_SIZE(super);
 	fs->fragsize = EXT2_FRAG_SIZE(super);
+	fs->desc_size = EXT2_DESC_SIZE(super);
 	frags_per_block = fs->blocksize / fs->fragsize;
 
 	/* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */
Index: e2fsprogs-1.39/lib/e2p/ls.c
===================================================================
--- e2fsprogs-1.39.orig/lib/e2p/ls.c	2006-05-31 15:44:49.000000000 +0200
+++ e2fsprogs-1.39/lib/e2p/ls.c	2006-06-07 16:04:38.000000000 +0200
@@ -199,6 +199,7 @@ void list_super2(struct ext2_super_block
 	fprintf(f, "First block:              %u\n", sb->s_first_data_block);
 	fprintf(f, "Block size:               %u\n", EXT2_BLOCK_SIZE(sb));
 	fprintf(f, "Fragment size:            %u\n", EXT2_FRAG_SIZE(sb));
+	fprintf(f, "Descriptor size:          %u\n", EXT2_DESC_SIZE(sb));
 	if (sb->s_reserved_gdt_blocks)
 		fprintf(f, "Reserved GDT blocks:      %u\n", 
 			sb->s_reserved_gdt_blocks);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.