allow larger block group descriptors Signed-off-by: Alexandre Ratchov Index: e2fsprogs-1.39/lib/ext2fs/ext2fs.h =================================================================== --- e2fsprogs-1.39.orig/lib/ext2fs/ext2fs.h 2006-09-22 15:52:50.000000000 +0200 +++ e2fsprogs-1.39/lib/ext2fs/ext2fs.h 2006-09-22 15:53:09.000000000 +0200 @@ -213,6 +213,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; Index: e2fsprogs-1.39/lib/ext2fs/swapfs.c =================================================================== --- e2fsprogs-1.39.orig/lib/ext2fs/swapfs.c 2006-09-22 15:52:50.000000000 +0200 +++ e2fsprogs-1.39/lib/ext2fs/swapfs.c 2006-09-22 15:53:09.000000000 +0200 @@ -63,6 +63,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/misc/mke2fs.c =================================================================== --- e2fsprogs-1.39.orig/misc/mke2fs.c 2006-09-22 15:52:50.000000000 +0200 +++ e2fsprogs-1.39/misc/mke2fs.c 2006-09-22 15:53:09.000000000 +0200 @@ -94,7 +94,7 @@ int linux_version_code = 0; static void usage(void) { fprintf(stderr, _("Usage: %s [-c|-t|-l filename] [-b block-size] " - "[-f fragment-size]\n\t[-i bytes-per-inode] [-I inode-size] " + "[-f fragment-size]\n\t[-i bytes-per-inode] [-I inode-size] [-D descriptor-size]" "[-j] [-J journal-options]\n" "\t[-N number-of-inodes] [-m reserved-blocks-percentage] " "[-o creator-os]\n\t[-g blocks-per-group] [-L volume-label] " @@ -680,6 +680,8 @@ static void show_stats(ext2_filsys fs) s->s_log_block_size); printf(_("Fragment size=%u (log=%u)\n"), fs->fragsize, s->s_log_frag_size); + if (s->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) + printf(_("Descriptor size=%u\n"), fs->desc_size); printf(_("%u inodes, %llu blocks\n"), s->s_inodes_count, EXT2_BLOCKS_COUNT(s)); printf(_("%llu blocks (%2.2f%%) reserved for the super user\n"), @@ -689,7 +691,7 @@ static void show_stats(ext2_filsys fs) if (s->s_reserved_gdt_blocks) printf(_("Maximum filesystem blocks=%llu\n"), (blk_t)((s->s_reserved_gdt_blocks + fs->desc_blocks) * - (fs->blocksize / sizeof(struct ext2_group_desc)) * + (fs->blocksize / fs->desc_size) * s->s_blocks_per_group)); if (fs->group_desc_count > 1) printf(_("%u block groups\n"), fs->group_desc_count); @@ -822,7 +824,7 @@ static void parse_extended_opts(struct e bpg = param->s_blocks_per_group; if (!bpg) bpg = blocksize * 8; - gdpb = blocksize / sizeof(struct ext2_group_desc); + gdpb = blocksize / EXT2_DESC_SIZE(param); group_desc_count = ext2fs_div_ceil(EXT2_BLOCKS_COUNT(param), bpg); desc_blocks = (group_desc_count + @@ -861,7 +863,8 @@ static __u32 ok_features[3] = { EXT2_FEATURE_COMPAT_LAZY_BG, /* Compat */ EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV| - EXT2_FEATURE_INCOMPAT_META_BG, + EXT2_FEATURE_INCOMPAT_META_BG| + EXT4_FEATURE_INCOMPAT_64BIT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */ }; @@ -896,6 +899,7 @@ static void PRS(int argc, char *argv[]) int blocksize = 0; int inode_ratio = 0; int inode_size = 0; + int desc_size = 0; double reserved_ratio = 5.0; int sector_size = 0; int show_version_only = 0; @@ -971,7 +975,7 @@ static void PRS(int argc, char *argv[]) } while ((c = getopt (argc, argv, - "b:cf:g:i:jl:m:no:qr:s:tvE:FI:J:L:M:N:O:R:ST:V")) != EOF) { + "b:cf:g:i:jl:m:no:qr:s:tvD:E:FI:J:L:M:N:O:R:ST:V")) != EOF) { switch (c) { case 'b': blocksize = strtol(optarg, &tmp, 0); @@ -1088,6 +1092,14 @@ static void PRS(int argc, char *argv[]) exit(1); } break; + case 'D': + desc_size = strtoul(optarg, &tmp, 0); + if (*tmp) { + com_err(program_name, 0, + _("invalid descriptor size - %s"), optarg); + exit(1); + } + break; case 'v': verbose = 1; break; @@ -1252,7 +1264,10 @@ static void PRS(int argc, char *argv[]) exit(1); } if (dev_size >> 31) { - fs_param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT; + fs_param.s_feature_incompat |= + EXT4_FEATURE_INCOMPAT_64BIT; + fs_param.s_desc_size = + EXT2_MIN_DESC_SIZE_64BIT; } EXT2_BLOCKS_COUNT_SET(&fs_param, dev_size); if (sys_page_size > EXT2_BLOCK_SIZE(&fs_param)) @@ -1438,6 +1453,26 @@ static void PRS(int argc, char *argv[]) inode_size); fs_param.s_inode_size = inode_size; } + + if (desc_size) { + unsigned desc_size_min; + + if (fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) + desc_size_min = EXT2_MIN_DESC_SIZE_64BIT; + else + desc_size_min = EXT2_MIN_DESC_SIZE; + + if (desc_size < desc_size_min || + desc_size > EXT2_MAX_DESC_SIZE || + desc_size & (desc_size - 1)) { + com_err(program_name, 0, + _("invalid descriptor size %d (min %d/max %d)"), + desc_size, EXT2_MIN_DESC_SIZE, + EXT2_MAX_DESC_SIZE); + exit(1); + } + fs_param.s_desc_size = desc_size; + } /* Make sure number of inodes specified will fit in 32 bits */ if (num_inodes == 0) { Index: e2fsprogs-1.39/lib/ext2fs/openfs.c =================================================================== --- e2fsprogs-1.39.orig/lib/ext2fs/openfs.c 2006-09-22 15:52:50.000000000 +0200 +++ e2fsprogs-1.39/lib/ext2fs/openfs.c 2006-09-22 15:53:09.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 = EXT2_GROUP_BASE(fs->super, bg) + has_super; @@ -87,8 +87,10 @@ errcode_t ext2fs_open2(const char *name, unsigned long i; int j, groups_per_block, blocks_per_group, io_flags; blk_t group_block, blk; - char *dest, *cp; + char *cp; struct ext2_group_desc *gdp; + char shadow_block[EXT2_MAX_BLOCK_SIZE]; + size_t desc_buflen; EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER); @@ -231,6 +233,13 @@ errcode_t ext2fs_open2(const char *name, goto cleanup; } } + + if (fs->super->s_feature_incompat & + EXT4_FEATURE_INCOMPAT_64BIT) { + fs->desc_size = EXT2_DESC_SIZE(fs->super); + } else { + fs->desc_size = EXT2_MIN_DESC_SIZE; + } /* * Set the blocksize to the filesystem's blocksize. */ @@ -262,27 +271,32 @@ errcode_t ext2fs_open2(const char *name, blocks_per_group); fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count, EXT2_DESC_PER_BLOCK(fs->super)); - retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize, - &fs->group_desc); + + desc_buflen = fs->desc_blocks * EXT2_DESC_PER_BLOCK(fs->super) * + sizeof(struct ext2_group_desc); + retval = ext2fs_get_mem(desc_buflen, &fs->group_desc); if (retval) goto cleanup; + memset(fs->group_desc, 0, desc_buflen); + 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++) { + memcpy(gdp, shadow_block + j * fs->desc_size, 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-09-22 15:52:50.000000000 +0200 +++ e2fsprogs-1.39/lib/ext2fs/closefs.c 2006-09-22 15:53:09.000000000 +0200 @@ -80,7 +80,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) || @@ -204,14 +204,14 @@ static errcode_t write_backup_super(ext2 errcode_t ext2fs_flush(ext2_filsys fs) { - dgrp_t i,j; + dgrp_t i; errcode_t retval; unsigned long fs_state; struct ext2_super_block *super_shadow = 0; - struct ext2_group_desc *group_shadow = 0; - struct ext2_group_desc *s, *t; - char *group_ptr; - int old_desc_blocks; + struct ext2_group_desc *gd; + char *desc_shadow = NULL; + size_t desc_buflen; + int old_desc_blocks; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); @@ -219,33 +219,36 @@ errcode_t ext2fs_flush(ext2_filsys fs) fs->super->s_wtime = fs->now ? fs->now : time(NULL); fs->super->s_block_group_nr = 0; + + desc_buflen = fs->desc_blocks * fs->blocksize; + retval = ext2fs_get_mem(desc_buflen, &desc_shadow); + if (retval) + goto errout; + memset(desc_shadow, 0, desc_buflen); + + /* + * copy the group descriptors adjusting size to the + * on-disk size. If needed, also bswap them on the fly + */ + for (i = 0; i < fs->group_desc_count; i++) { + gd = (struct ext2_group_desc *)(desc_shadow + i * fs->desc_size); + memcpy(gd, &fs->group_desc[i], fs->desc_size); +#ifdef EXT2FS_ENABLE_SWAPFS + if (fs->flags & EXT2_FLAG_SWAP_BYTES) + ext2fs_swap_group_desc(gd); +#endif + } + #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 /* @@ -273,7 +276,6 @@ errcode_t ext2fs_flush(ext2_filsys fs) * Write out the master group descriptors, and the backup * superblocks and group descriptors. */ - group_ptr = (char *) group_shadow; if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) old_desc_blocks = fs->super->s_first_meta_bg; else @@ -297,13 +299,14 @@ errcode_t ext2fs_flush(ext2_filsys fs) if ((old_desc_blk) && (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) { retval = io_channel_write_blk(fs->io, - old_desc_blk, old_desc_blocks, group_ptr); + old_desc_blk, old_desc_blocks, desc_shadow); if (retval) goto errout; } if (new_desc_blk) { - retval = io_channel_write_blk(fs->io, new_desc_blk, - 1, group_ptr + (meta_bg*fs->blocksize)); + retval = io_channel_write_blk( + fs->io, new_desc_blk, 1, + desc_shadow + meta_bg * fs->blocksize); if (retval) goto errout; } @@ -352,8 +355,8 @@ errout: if (fs->flags & EXT2_FLAG_SWAP_BYTES) { if (super_shadow) ext2fs_free_mem(&super_shadow); - if (group_shadow) - ext2fs_free_mem(&group_shadow); + if (desc_shadow) + ext2fs_free_mem(&desc_shadow); } return retval; } Index: e2fsprogs-1.39/lib/ext2fs/ext2_fs.h =================================================================== --- e2fsprogs-1.39.orig/lib/ext2fs/ext2_fs.h 2006-09-22 15:52:50.000000000 +0200 +++ e2fsprogs-1.39/lib/ext2fs/ext2_fs.h 2006-09-22 18:23:10.000000000 +0200 @@ -225,6 +225,12 @@ struct ext2_dx_countlimit { /* * Macro-instructions used to manage group descriptors */ +#define EXT2_MIN_DESC_SIZE 32 +#define EXT2_MIN_DESC_SIZE_64BIT 64 +#define EXT2_MAX_DESC_SIZE EXT2_MIN_BLOCK_SIZE +#define EXT2_DESC_SIZE(s) \ + ((EXT2_SB(s)->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) ? \ + EXT2_SB(s)->s_desc_size : EXT2_MIN_DESC_SIZE) #define EXT2_BLOCKS_PER_GROUP(s) ((__u64)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)) @@ -235,7 +241,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 /* @@ -556,7 +562,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 */ Index: e2fsprogs-1.39/lib/ext2fs/initialize.c =================================================================== --- e2fsprogs-1.39.orig/lib/ext2fs/initialize.c 2006-09-22 15:52:50.000000000 +0200 +++ e2fsprogs-1.39/lib/ext2fs/initialize.c 2006-09-22 15:53:09.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; @@ -106,6 +106,7 @@ errcode_t ext2fs_initialize(const char * int io_flags; char *buf; blk_t inodes; + size_t desc_buflen; if (!param || !EXT2_BLOCKS_COUNT(param)) return EXT2_ET_INVALID_ARGUMENT; @@ -149,6 +150,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, 0); 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 +180,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; set_field(s_blocks_per_group, fs->blocksize * 8); @@ -350,12 +353,12 @@ ipg_retry: ext2fs_free_mem(&buf); - retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize, - &fs->group_desc); + desc_buflen = fs->desc_blocks * EXT2_DESC_PER_BLOCK(fs->super) * + sizeof(struct ext2_group_desc); + retval = ext2fs_get_mem(desc_buflen, &fs->group_desc); if (retval) goto cleanup; - - memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize); + memset(fs->group_desc, 0, desc_buflen); /* * Reserve the superblock and group descriptors for each Index: e2fsprogs-1.39/resize/resize2fs.c =================================================================== --- e2fsprogs-1.39.orig/resize/resize2fs.c 2006-09-22 15:52:50.000000000 +0200 +++ e2fsprogs-1.39/resize/resize2fs.c 2006-09-22 15:53:09.000000000 +0200 @@ -187,6 +187,7 @@ errcode_t adjust_fs_info(ext2_filsys fs, unsigned long i, j, old_desc_blocks, max_group; unsigned int meta_bg, meta_bg_size; int has_super; + size_t odesc_buflen, ndesc_buflen; __u64 new_inodes; /* u64 to check for overflow */ EXT2_BLOCKS_COUNT_SET(fs->super, new_size); @@ -276,17 +277,20 @@ retry: * Reallocate the group descriptors as necessary. */ if (old_fs->desc_blocks != fs->desc_blocks) { - retval = ext2fs_resize_mem(old_fs->desc_blocks * - fs->blocksize, - fs->desc_blocks * fs->blocksize, + odesc_buflen = old_fs->desc_blocks * + EXT2_DESC_PER_BLOCK(old_fs->super) * + sizeof(struct ext2_group_desc); + ndesc_buflen = fs->desc_blocks * + EXT2_DESC_PER_BLOCK(fs->super) * + sizeof(struct ext2_group_desc); + retval = ext2fs_resize_mem(odesc_buflen, ndesc_buflen, &fs->group_desc); if (retval) goto errout; if (fs->desc_blocks > old_fs->desc_blocks) - memset((char *) fs->group_desc + - (old_fs->desc_blocks * fs->blocksize), 0, - (fs->desc_blocks - old_fs->desc_blocks) * - fs->blocksize); + memset(&fs->group_desc[old_fs->group_desc_count], 0, + (fs->group_desc_count - old_fs->group_desc_count) * + sizeof(struct ext2_group_desc)); } /* @@ -365,8 +369,7 @@ retry: fs->super->s_reserved_gdt_blocks; for (i = old_fs->group_desc_count; i < fs->group_desc_count; i++) { - memset(&fs->group_desc[i], 0, - sizeof(struct ext2_group_desc)); + memset(&fs->group_desc[i], 0, sizeof(struct ext2_group_desc)); adjblocks = 0; if (i == fs->group_desc_count-1) { @@ -383,8 +386,7 @@ retry: ext2fs_mark_block_bitmap(fs->block_map, group_block); adjblocks++; } - meta_bg_size = (fs->blocksize / - sizeof (struct ext2_group_desc)); + meta_bg_size = fs->blocksize / fs->desc_size; meta_bg = i / meta_bg_size; if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || @@ -550,7 +552,7 @@ static errcode_t mark_table_blocks(ext2_ unsigned long meta_bg_size; unsigned int old_desc_blocks; - meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc)); + meta_bg_size = fs->blocksize / fs->desc_size; if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) old_desc_blocks = fs->super->s_first_meta_bg; else @@ -717,7 +719,7 @@ static errcode_t blocks_to_move(ext2_res * If we're increasing the number of descriptor blocks, life * gets interesting.... */ - meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc)); + meta_bg_size = fs->blocksize / fs->desc_size; for (i = 0; i < max_groups; i++) { has_super = ext2fs_bg_has_super(fs, i); if (has_super) Index: e2fsprogs-1.39/lib/ext2fs/dupfs.c =================================================================== --- e2fsprogs-1.39.orig/lib/ext2fs/dupfs.c 2006-09-22 15:08:12.000000000 +0200 +++ e2fsprogs-1.39/lib/ext2fs/dupfs.c 2006-09-22 15:53:09.000000000 +0200 @@ -23,6 +23,7 @@ errcode_t ext2fs_dup_handle(ext2_filsys { ext2_filsys fs; errcode_t retval; + size_t desc_buflen; EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS); @@ -59,12 +60,13 @@ errcode_t ext2fs_dup_handle(ext2_filsys goto errout; memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE); - retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize, - &fs->group_desc); + + desc_buflen = fs->desc_blocks * EXT2_DESC_PER_BLOCK(fs->super) * + sizeof(struct ext2_group_desc); + retval = ext2fs_get_mem(desc_buflen, &fs->group_desc); if (retval) goto errout; - memcpy(fs->group_desc, src->group_desc, - (size_t) fs->desc_blocks * fs->blocksize); + memcpy(fs->group_desc, src->group_desc, desc_buflen); if (src->inode_map) { retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map);